小米(MIUI)手机监听短信的两种解决方案
测试的系统为MIUI10和模拟器(Pixel 2 API 26)
应用场景:短信验证码自动填写等
方法1为监听系统短信数据库,但是存在一个问题,就是收到短信之后需要
点击短信进入短信详情页面,才会触发广播
。
方法2通过监听通知栏,根据发通知的应用包名锁定对应的短信应用,从而可以在收到短信的同时获取短信内容
两种方法在获取短信的时候都是只获取收到回调时最新的一条短信,因此不推荐方法1。
首先需要获取对应的权限,高版本的系统需要写代码动态获取权限
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
使用ContentObserver监听系统短信数据库更新
1.1 实现代码- 监听短信数据库变化
class SmsObserver extends ContentObserver {private Context context;public SmsObserver(Context context, Handler handler) {super(handler);this.context = context;}@Overridepublic void onChange(boolean selfChange) {super.onChange(selfChange);//每当有新短信到来时,获取短消息的方法getSmsFromPhone();}private void getSmsFromPhone() {ContentResolver cr = context.getContentResolver();String[] projection = new String[]{"_id", "body", "address"};//"_id", "address", "person",, "date", "typeString where = " date > "+ (System.currentTimeMillis() - 10 * 60 * 1000);//10分钟之内的短信Cursor cur = cr.query(Uri.parse("content://sms/inbox"), projection, where, null, "date desc");if (null == cur)return;try {if (cur.moveToFirst()) {String number = cur.getString(cur.getColumnIndex("address"));//手机号String body = cur.getString(cur.getColumnIndex("body"));//内容}} finally {cur.close();}} }
- 初始化监听
val smsHandler: Handler = @SuppressLint("HandlerLeak")object : Handler() { //这里可以进行回调的操作//TODO}smsObserver = SmsObserver(this, smsHandler)//监听短信applicationContext.contentResolver.registerContentObserver(Uri.parse("content://sms/inbox"), true,smsObserver!!)
- 监听短信数据库变化
使用NotificationListenerService监听系统通知栏数据更新
2.1 实现代码继承NotificationListenerService(高版本的安卓系统需要在Service里面调用函数
startForeground
设置通知栏,否则会报错)class NotificationMonitor : NotificationListenerService() {private val match = arrayOf("com.android.mms", "com.google.android.apps.messaging") //暂时只有小米短信和谷歌短信的包名// 有新的通知override fun onNotificationPosted(sbn: StatusBarNotification) {super.onNotificationPosted(sbn)Log.i(getString(R.string.app_name), sbn.packageName)if (sbn.packageName in match) {Log.i(getString(R.string.app_name), "有新的短信")getSmsFromPhone()}}private fun getSmsFromPhone() {val cr: ContentResolver = contentResolverval projection =arrayOf("_id", "body", "address") //"_id", "address", "person",, "date", "typeval where = (" date > "+ (System.currentTimeMillis() - 10 * 60 * 1000))val cur =cr.query(Uri.parse("content://sms"), projection, where, null, "date desc") ?: returncur.use { cur ->if (cur.moveToFirst()) {val number = cur.getString(cur.getColumnIndex("address")) //手机号val body = cur.getString(cur.getColumnIndex("body")) //内容}}}override fun onCreate() {super.onCreate()//设置通知栏if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {val channelId =if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {createNotificationChannel("message_deliver_notification_service","MessageDeliver Background Service")} else {// If earlier version channel ID is not used// https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder.html#NotificationCompat.Builder(android.content.Context)""}val notificationBuilder = NotificationCompat.Builder(this, channelId)val notification = notificationBuilder.setOngoing(true).setSmallIcon(R.mipmap.ic_launcher).setPriority(NotificationCompat.PRIORITY_MIN).setCategory(Notification.CATEGORY_SERVICE).build()startForeground(1, notification)}}@RequiresApi(Build.VERSION_CODES.O)private fun createNotificationChannel(channelId: String, channelName: String): String {val chan = NotificationChannel(channelId,channelName, NotificationManager.IMPORTANCE_NONE)chan.lightColor = Color.BLUEchan.lockscreenVisibility = Notification.VISIBILITY_PRIVATEval service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManagerservice.createNotificationChannel(chan)return channelId}}
在AndroidManifest.xml的
application
标签里面注册Service<serviceandroid:name=".NotificationMonitor"android:label="@string/app_name"android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"><intent-filter><action android:name="android.service.notification.NotificationListenerService" /></intent-filter></service>
启动Service(这里由于安卓版本的不同,启动后台服务可以选择调用不同的函数)
val notification = Intent(this, NotificationMonitor::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {this.startForegroundService(notification) } else {this.startService(notification) }
小米(MIUI)手机监听短信的两种解决方案相关推荐
- Android实时监听短信并上传服务器
短信监听 Android监听手机短信的方法有两种,分别为: 1.接受系统的短信广播:当手机收到新消息时,会发送一条广播,通过该广播就可以获取短信内容: 2.监听短信数据库:利用观察者模式监听短信数据库 ...
- Android实战简易教程-第三十六枪(监听短信-实现短信验证码自动填入)
一般用户喜欢用手机号作为用户名注册APP账号,这时一般都是通过手机验证码的方式进行验证,下面我们就研究一个非常实用的方法,通过监听短信-实现短信验证码的自动填入,提高用户体验. 首先我们看一下如何监听 ...
- Android 监听短信数据库过滤获取短信内容上传至服务器
前言 Android 监听短信的方式有两种 1.监听短信数据库,数据库发生改变时回调. 2.监听短信广播 其中第二种方式由于国内各厂家的定制Android 可能导致无响应 目前测试 魅族 无法监听到短 ...
- android 监听短信并发送到服务器
1. 接受系统的短信广播,操作短信内容. 优点:操作方便,适合简单的短信应用. 缺点:来信会在状态栏显示通知信息. 2. 应用观察者模式,监听短信数据库,操作短信内容. 实例如下: SystemE ...
- android 发送彩信监听,在Android中发送短信和彩信,监听短信并显示
发送短信: String body="this is sms demo"; Intent mmsintent = new Intent(Intent.ACTION_SENDTO, ...
- android 监听短信并获取验证码
最近想给 app 添加自动获取短信验证码的功能,让注册流程更加友好,在网上搜索了一些资料,主要的实现方法有两种. 第一:实现广播 BroadCastReceiver 来监听收件箱,在需要监听的地方注册 ...
- android发送短信的两种方式,发送长短信的两种方式,群发短信
android 发送短信的方法 方法一:调用系统的短信APP,发送短信. Intent smsIntent = new Intent(Intent.ACTION_VIEW);smsIntent.set ...
- android 监听 短信,Android短信验证码监听解决onChange多次调用的方法
先说一句:MIUI请放弃治疗!这里给个传送门: 识别短信验证码并提取还是挺常见的一个需求.所要解决的问题主要有: 1.如何监听 2.如何提取短信中的验证码 3.监听多次调用问题 直接看下面代码吧,很明 ...
- Android使用Google SMSRetrieverAPI监听短信
写在开头 google官方介绍 如果在没有读写短信权限的情况下获取用户的短信验证码呢?google为我们提供了SMSRetrieverAPI这个Api.解决了我们在用户收到短信后自动回填界面的需求.但 ...
最新文章
- 研究生第一篇科研论文常犯问题总结
- Java架构师必知必会,带走不谢
- Cuckoo hash算法分析——其根本思想和bloom filter一致 增加hash函数来解决碰撞 节省了空间但代价是查找次数增加...
- 怎样查看was的服务器信息,WAS 查看服务状态
- python画统计图怎么在右上角表示哪条线代表什么_Python-matplotlib统计图之箱线图漫谈...
- Swap Letters CodeForces - 1215C(贪心)
- java joda_java-Jodatime的开始时间和结束时间
- java sql merge_sql merge用法
- windows10程序员计算机,Win10计算器程序员模式如何移位?
- 怎么上传本地项目或文件到SVN服务器
- 船讯网|爬虫COOKIE重定向反爬处理
- 新计算机的word无法输入文字,word打字后面的字消失怎么办
- geoserver配置SQL图层 cql_filter模糊查询
- [转载]以xilinx为例的低功耗设计
- 类 ApplicationInfo详解
- Dns与httpDNS的区别
- 使用Lumberjack进行日志切割归档
- bas64图片加密解密
- Java基础练习:用户在控制台输入一个年份,判断该年份是平年还是闰年
- 解决主机前面板耳机孔无声问题以华硕主板为例