Android怎么实现获取短信验证码并自动填充

您所在的位置:网站首页 荣耀自动填充验证码怎么关 Android怎么实现获取短信验证码并自动填充

Android怎么实现获取短信验证码并自动填充

2023-04-24 03:44| 来源: 网络整理| 查看: 265

本篇内容主要讲解“Android怎么实现获取短信验证码并自动填充”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android怎么实现获取短信验证码并自动填充”吧!

权限

申请权限

短信属于隐私权限,Android 6.0后需要动态申请权限。首先在manifest里面注册权限:

在需要用的地方,动态申请下:

String[] smsPermission = {Manifest.permission.READ_SMS, Manifest.permission.RECEIVE_SMS};

小米短信权限问题

本来这样权限问题就搞定了,但是在小米手机上就不行。小米手机会把短信归类到通知类权限里:

Android怎么实现获取短信验证码并自动填充

在 ContextCompat.checkSelfPermission 的时候会直接返回true,并且不会弹出权限对话框,而是在实际使用的时候才会咨询用户,按理说好像和我们逻辑没有冲突,但是在使用receiver进行监听前,不是得确保有权限么?实际效果也是,在没有权限时,不能获取到短信的广播。

小米短信权限解决

在网上找了找办法,好像也没多少博文,但是大致有了思路:不是用的时候才申请么?那我就先用一下,再去用receiver监听。下面是方法:

// 读取一下试试,能读取到就有权限 boolean flag = false; try {     Uri uri = Uri.parse("content://sms/inbox");     ContentResolver cr = context.getContentResolver();     String[] projection = new String[]{"_id"};     Cursor cur = cr.query(uri, projection, null, null, "date desc");     if (null != cur) {         cur.close();     }     lag = true; }catch (Exception e) {     e.printStackTrace(); }

这里仅针对小米手机啊,对小米手机的判断我只是用 android.os.Build.MANUFACTURER 简单判断了下,如果有更高要求请查找资料。

使用Receiver进行监听

编写SmsReceiver

这里也是网上随便找了个代码,能用,但是在荣耀手机上却是偶尔能收到一次,后面几次就收不到了,打了log也没进入到onReceive中,这就很离奇了,排查了很久。同样的代码,在小米手机上是没问题的,那就只可能是适配问题了。

import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.telephony.SmsMessage; import android.util.Log; public class SmsReceiver extends BroadcastReceiver {     @Override     public void onReceive(Context context, Intent intent) {         //Toast.makeText(context, "收到信息", Toast.LENGTH_LONG).show();         Log.d("SmsReceiver", "onReceive: " + intent.getAction());         if(intent.getAction().equals("android.provider.Telephony.SMS_RECEIVED")){             //intent.getExtras()方法就是从过滤后的意图中获取携带的数据,             // 这里携带的是以“pdus”为key、短信内容为value的键值对             // android设备接收到的SMS是pdu形式的             Bundle bundle = intent.getExtras();             SmsMessage msg;             if (null != bundle){                 //生成一个数组,将短信内容赋值进去                 Object[] smsObg = (Object[]) bundle.get("pdus");                 //遍历pdus数组,将每一次访问得到的数据方法object中                 for (Object object:smsObg){                     //获取短信                     msg = SmsMessage.createFromPdu((byte[])object);                     //获取短信内容                     String content = msg.getDisplayMessageBody();                     Log.d("SmsReceiver", "onReceive: content = " + content);                     //获取短信发送方地址                     String from = msg.getOriginatingAddress();                     Log.d("SmsReceiver", "onReceive: from = " + from);                     // TODO ...                 }             }         }     } }

使用方法:

// 使用广播进行监听 IntentFilter smsFilter = new IntentFilter(); smsFilter.addAction("android.provider.Telephony.SMS_RECEIVED"); smsFilter.addAction("android.provider.Telephony.SMS_DELIVER"); if (smsReceiver == null) {     smsReceiver = new SmsReceiver(); } smsReceiver.setCallbackContext(callbackContext); context.registerReceiver(smsReceiver, smsFilter);

接触监听,最好在收到短信的时候就取消注册广播:

context.unregisterReceiver(smsReceiver);

解决OPPO手机无法接收短信广播问题

本来小米荣耀都搞定了,给测试一测,结果又不行了。收不到广播,用下面的ContentObserver还总拿不到对的数据。找了下资料,发现OPPO手机需要在短信APP进行设置。

ps. 后面发现华为、荣耀都是这样,会对验证码进行保护。可以使用ContentObserver 监听,能触发onChange,但是拿不到Uri,不过可以使用查询,拿到倒叙的第一条数据,取出其中的date属性,比对监听时的时间,如果短信两分钟有效,那就看看第一条数据是不是在两分钟内,如果不是,那就是没拿到,问题就出在用户开启了短信验证码保护,可以提示用户自行输入验证码(毕竟这个不是我们的锅)。

解决方法: 在短信 -> 短信设置里面 -> 打开禁止后台应用读取验证码

解决荣耀无法连续监听短信的问题

既然上面的方法没用了,只能找新的办法喽,网上很多提供了两种办法,第二种就是通过ContentResolver去监听短信添加的更新动作,其实也和广播类似,代码如下:

import android.content.Context; import android.database.ContentObserver; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.Handler; import android.provider.Telephony; import android.util.Log; import androidx.annotation.RequiresApi; @RequiresApi(api = Build.VERSION_CODES.KITKAT) public class ReadSmsObserver extends ContentObserver {     private final Context context;     public ReadSmsObserver(Handler handler, Context context) {         super(handler);         this.context = context;     }     private static final String SMS_INBOX_URI = "content://sms/inbox";//API level>=23,可直接使用Telephony.Sms.Inbox.CONTENT_URI,用于获取cusor     // private static final String SMS_URI = "content://sms";//API level>=23,可直接使用Telephony.Sms.CONTENT_URI,用于注册内容观察者     private static final String[] PROJECTION = new String[]{             Telephony.Sms._ID,             Telephony.Sms.ADDRESS,             Telephony.Sms.BODY,             Telephony.Sms.DATE     };     @Override     public void onChange(boolean selfChange, Uri uri) {         super.onChange(selfChange);         Log.d("ReadSmsObserver", "onChange: ");         // 当收到短信时调用一次,当短信显示到屏幕上时又调用一次,所以需要return掉一次调用         if(uri.toString().equals("content://sms/raw")){             return;         }         // 读取短信收件箱,只读取未读短信,即read=0,并按照默认排序         Cursor cursor = context.getContentResolver().query(Uri.parse(SMS_INBOX_URI), PROJECTION,                 Telephony.Sms.READ + "=?", new String[]{"0"}, Telephony.Sms.Inbox.DEFAULT_SORT_ORDER);         if (cursor == null) return;         // 获取倒序的第一条短信         if (cursor.moveToFirst()) {             // 读取短信发送人             String address = cursor.getString(cursor.getColumnIndex(Telephony.Sms.ADDRESS));             Log.d("ReadSmsObserver", "onChange: address = " + address);             // 读取短息内容             String smsBody = cursor.getString(cursor.getColumnIndex(Telephony.Sms.BODY));             Log.d("ReadSmsObserver", "onChange: smsBody = " + smsBody);                          // TODO 传递出去,最好切下线程         }         // 关闭cursor的方法         cursor.close();     } }

用的时候要注册和取消注册:

// 使用ContentResolver进行监听 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {     if (smsObserver == null) {         smsObserver = new ReadSmsObserver(new SmsHandler(), context);     }     smsObserver.setCallbackContext(callbackContext);     context.getContentResolver().registerContentObserver(         Uri.parse("content://sms/"), true, smsObserver); }

取消注册:

context.getContentResolver().unregisterContentObserver(smsObserver);

解决OPPO手机无法拿到最新短信问题

很神奇啊,每次使用ContentObserver去监听短信变化,明明onChange触发了,但是去拿短信就是拿不到最新的,开了上面的设置也不行,弄了好久。

最后想的解决办法是,两种方式同时监听,在onChange触发后等待三秒钟(开始试了1s还不行),看看有没有onReceive,如果有就直接使用onReceive的短信,如果没有再验证onChange内拿到的短信,看看是不是有效时间内的,连倒叙第一个都在有效时间外,那就是没拿到了,直接舍弃了。

转载请注明:Android怎么实现获取短信验证码并自动填充 | 李雷博客 - PHP博客


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3