Android 自动获取验证码 两种方式BroadcastReceiver及ContentObserver总结

自动获取验证码的两种方式都需要进行注册、取消注册两个步骤
记得添加权限

<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_SMS"/>

方式一:BroadcastReceiver
自定义广播

/**
 * Created by weifeiyang on 2016/7/29 0029.
 */

import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.telephony.SmsMessage;
import android.util.Log;

/**
 * 短信监听
 *
 * @author
 */
public class SMSBroadcastReceiver extends BroadcastReceiver {

    private static MessageListener mMessageListener;
    public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";//只要注册声明权限即可收到、阻断

    @TargetApi(Build.VERSION_CODES.M)
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(SMS_RECEIVED_ACTION)) {
            //获得短信数据
            Object[] pdus = (Object[]) intent.getExtras().get("pdus");
            //短信的类型, GSM与CDMA短信的解码方式不同
            String format = intent.getStringExtra("format");

            if (null != pdus) {
                for (Object pdu : pdus) {
                    Log.e("pdu", "format" + format);
                    //23以上版本显示 createFromPdu过时,多加一个format参数即可
                    SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu, format);
                    //发送号码-可以过滤需要读取的短信的发送号码
                    String sender = smsMessage.getDisplayOriginatingAddress();
                    //短信内容
                    String content = smsMessage.getDisplayMessageBody();
                    if (content.contains("你从服务器上获取到的验证码")){
                        mMessageListener.onReceived(content);
                        abortBroadcast();//中断广播的继续传递,防止优先级低的获取到
                    }
                }
            }

        }

    }

    //回调接口
    public interface MessageListener {
        public void onReceived(String message);
    }

    public void setOnReceivedMessageListener(MessageListener messageListener) {
        this.mMessageListener = messageListener;
    }
}

其中关于format的解释可以参考
http://www.cnblogs.com/flyme/archive/2011/09/07/2169740.html 3GPP与3GPP2扫盲

广播有了后就可以使用了,在activity或者fragment的onCreate方法中调用initSMSBroadcastReceiver()进行注册,在onDestroy()中通过
//注销短信监听广播
this.unregisterReceiver(mSMSBroadcastReceiver);
取消注册

/**
     * 初始化短信监听广播
     */
    private void initSMSBroadcastReceiver() {
        //生成广播处理
        mSMSBroadcastReceiver = new SMSBroadcastReceiver(mContent);
        //实例化过滤器并设置要过滤的广播
        IntentFilter intentFilter = new IntentFilter(SMSBroadcastReceiver.SMS_RECEIVED_ACTION);
        //优先级最高
        intentFilter.setPriority(Integer.MAX_VALUE);
        //注册广播
        this.registerReceiver(mSMSBroadcastReceiver, intentFilter);
        mSMSBroadcastReceiver.setOnReceivedMessageListener(new SMSBroadcastReceiver.MessageListener() {
            @Override
            public void onReceived(String message) {
                TLog.error("message" + message);
                String code = ReadSmsContent.getDynamicPassword(message);
                seCodeEditText.setText(code);
            }
        });
    }

方式二:ContentObserver
照旧先上ContentObserver代码

/**
 * Created by weifeiyang on 2016/7/29 0029.
 */

import android.app.Activity;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.text.TextUtils;
import android.widget.EditText;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 读取短信验证码,并设置验证码
 * Created by cool on 2016/1/4.
 */
public class ReadSmsContent extends ContentObserver {
    private Cursor cursor = null;
    private Activity mActivity;
    private EditText mEditText;

    public ReadSmsContent(Handler handler, Activity activity, EditText editText) {
        super(handler);
        this.mActivity = activity;
        this.mEditText = editText;
    }

    @Override
    public void onChange(boolean selfChange, Uri uri) {

    /*
        第一次回调 不是我们想要的 直接返回
        目前发现每次收到新短信都会走好几次onChange(),
        可以通过这个方法来使得onChange中的方法只走一次
    */
        if (uri.toString().equals("content://sms/raw")) {
            return;
        }

        /*
            读取收件箱中的短信

            address 发件人手机号码:
            body 信息内容:
            read 是否查看:
            date 发送时间:
         */
        cursor = mActivity.getContentResolver().query(Uri.parse("content://sms/inbox"),
                new String[]{"_id", "address", "body", "read"}, null, null, "_id desc");//按降序排列

//        指定号码
//        mActivity.managedQuery(Uri.parse("content://sms/inbox"),
//                new String[]{"_id", "address", "body", "read"}, "address=? and read=?", new String[]{"10086", "0"}, "_id desc");

        if (null != cursor && cursor.getCount() > 0) {
            cursor.moveToNext();//指向首位
            int smsbodyColumn = cursor.getColumnIndex("body");//body位置
            String smsBody = cursor.getString(smsbodyColumn);//获取内容
            String verifyCode = getDynamicPassword(smsBody);
            if (TextUtils.isEmpty(verifyCode)) {
                return;
            }
            if (mEditText == null) {
                throw new RuntimeException("你传的EditText为空");
            }
            if (verifyCode.contains("你从服务器上获取到的验证码"))) {
                mEditText.setText(verifyCode);
                //EditText获取焦点,3个属性必须同时设置
                mEditText.setFocusable(true);
                mEditText.setFocusableInTouchMode(true);
                mEditText.requestFocus();
                mEditText.setSelection(verifyCode.length());//设置光标位置
            }

        }
        if (!cursor.isClosed()) {
            cursor.close();
        }
    }

    /**
     * 从字符串中截取连续4位数字
     * 用于从短信中获取动态密码
     *
     * @param str 短信内容
     * @return 截取得到的4位动态密码
     */
    public static String getDynamicPassword(String str) {
        Pattern continuousNumberPattern = Pattern.compile("[0-9\\.]+");
        Matcher m = continuousNumberPattern.matcher(str);
        String dynamicPassword = "";
        while (m.find()) {
            if (m.group().length() == 4) {
                dynamicPassword = m.group();
            }
        }

        return dynamicPassword;
    }
}

观察者有了后就可以使用了,在activity或者fragment的onCreate方法中调用initSmSContentObserver()进行注册,在onDestroy()中通过
//注销内容监听者
this.getContentResolver().unregisterContentObserver(readSmsContent);

取消注册

    /**
     * 初始化短信监听数据库
     */
    private void initSmSContentObserver() {
        readSmsContent = new ReadSmsContent(new Handler(), this, seCodeEditText);
        //注册短信内容监听
        this.getContentResolver().registerContentObserver(Uri.parse("content://sms/"), true, readSmsContent);

    }

上述两种方式获取到短信后,目前由于短信平台来源账号不固定,因此是通过验证码进行校验,如果有更好的办法可以联系我

邮箱:cugb_feiyang@163.com
QQ :178546852

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值