【世界热闻】Android实现获取短信验证码并自动填充
目录
前言权限申请权限小米短信权限问题小米短信权限解决使用Receiver进行监听编写SmsReceiver解决OPPO手机无法接收短信广播问题解决荣耀无法连续监听短信的问题解决OPPO手机无法拿到最新短信问题前言
最近弄了个短信自动填充功能,一开始觉得很简单,不就是动态注册个广播接收器去监听短信消息不就可以了吗?结果没这么简单,问题就出在机型的适配上。小米的短信权限、荣耀、OPPO的短信监听都是坑,暂时就用这三个手机测了,其他的遇到了再补充。
下面简单讲讲:
权限
申请权限
短信属于隐私权限,Android 6.0后需要动态申请权限。首先在manifest里面注册权限:
【资料图】
在需要用的地方,动态申请下:
String[] smsPermission = {Manifest.permission.READ_SMS, Manifest.permission.RECEIVE_SMS};
小米短信权限问题
本来这样权限问题就搞定了,但是在小米手机上就不行。小米手机会把短信归类到通知类权限里:
在 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内拿到的短信,看看是不是有效时间内的,连倒叙第一个都在有效时间外,那就是没拿到了,直接舍弃了。
PS. 后续更新,感觉这些问题都可能是手机系统开了短信验证码保护。
思路是这样,做起来不麻烦,用个handler就可以解决,读者自行处理吧。
以上就是Android实现获取短信验证码并自动填充的详细内容,更多关于Android获取短信验证码的资料请关注脚本之家其它相关文章!
标签:
精彩推送
刀哥亲自祝福!《东北之夏2》现已免费上线Steam|全球热闻
今日,国产免费视觉小说游戏《东北之夏》开发者庄不纯宣布,DLC内容“东北之夏2”现已免费上线Steam,更...
新闻快讯
X 关闭
X 关闭
新闻快讯
- 【世界热闻】Android实现获取短信验证码并自动填充
- 当前时讯:葡萄牙金融制度_关于葡萄牙金融制度的简介
- 为什么婚外情中有些小三还没有原配优秀 全球讯息
- 感受“灵魂过山车” 探微人间真善美 “梅花夫妇”同台讲述小城故事_时快讯
- 2022年01月04日最新发布:苹果可能会在下周尽快发布新的iPad机型
- 普通高中几天放一次假_高中读几周才会放一次假
- 世乒赛:马龙晋级64强,赛后接受采访,本届赛事我没有定下任何目标
- 环球观速讯丨干得漂亮!中国台湾选手高举五星红旗登上领奖台
- 引喻失义的义是什么意思古义-引喻失义
- 环球今亮点!学籍档案在自己手里咋办_学籍状态不在籍毕业是什么意思
- 世界热议:泽连斯基已抵达日本广岛,将参加G7峰会
- 市州观察丨全力以赴打好防汛“主动仗” 眉山多措并举防汛备汛
- 干发帽怎么戴_干发帽简介_当前观察
- 海口美兰区:打造智慧安防校园 让校园长“智”久安[图]-世界快报
- 罗威谈防巴特勒:接受挑战且做好防守 这不是一个人的事情
- 丽江文化旅游学院邵宇航:扎根西部,潜心育人|今日视点
- 廊坊气象台发布雷电黄色预警 当前头条
- 环球微头条丨“最美志愿者”李东晓:在孩子心中种下梦想的种子
- 当前头条:谋杀顺序8火车攻略_谋杀顺序8
- 天天百事通!缺铁有什么症状和危害及原因_缺铁有什么症状
- 宋老师·AI闪电做课法,用AI帮你7天做出爆款课,10秒出课纲,3分钟出课稿,还比你自己
- Failed to connect to zw.gozuowen.com port 80: Timed out_天天播报
- 柿子的古诗有哪些 写柿子的古诗词有哪些? 天天时快讯
- 厦门禁建村调整为212个 适建村调整为577个
- HHOGene GPods 与光同行,打破传统耳机设计,勇敢表达自己!
- 天天短讯!股票行情快报:三全食品(002216)5月19日主力资金净买入293.88万元
- 西门庆和潘金莲做受_西门庆潘金莲床上片段
- 天天快看点丨5月19日基金净值:博时时代消费混合A最新净值0.7877,涨1.46%
- 南昌市金融支持“一枢纽四中心”建设暨重大重点项目产融对接会举行 世界百事通
- 向日葵真正的花语 当前报道
- 邮储银行赣州市分行:青春践行二十大 砥砺奋进新征程
- 天天热点!武汉真金白银支持智能建造领域核心技术攻关
- 瓷器
- 固生堂(02273):蒋晓冬辞任非执行董事 全球快播
- 每日快报!病人被遗忘核磁共振舱3小时,最该担心的是什么?
- 事发萍乡!国家二级保护动物误闯水果店!-全球热消息
- 环球头条:2023海口秀英区荔枝采摘路线
- 火箭制导与控制系统_关于火箭制导与控制系统介绍_当前观点
- godblessyou怎么回应 godblessyou-速递
- 热门看点:纺织企业将迎来重大商机!珲春-海参崴-南部国内港口实现多式联运!
- 世界微动态丨赵乃吉个人资料_赵乃吉
- 南宁慧泊停车有点贵,电动车、自行车也要收费引发争议_今日看点
- 开普检测:目前珠海基地各项业务还在开展之中,订单总量尚不能覆盖成本费用
- 濮阳退休工资多少钱一个月 濮阳工龄35年退休金多少
- 江苏海洋大学2023年硕士研究生调剂复试报到时间和地点汇总
- 当前头条:电广传媒:国泰君安证券、申万菱信基金等多家机构于5月17日调研我司
- Universal Display Corporation与PPG庆祝位于爱尔兰香农的先进OLED发光材料生产工厂的正式启用 天天看点
- 天水玉米变性淀粉实现首次出口
- 赍的读音和意思(赍)-全球今热点
- 世界观点:装修后室内空气甲醛和TVOC超标问题突出