测试的系统为MIUI10和模拟器(Pixel 2 API 26)

应用场景:短信验证码自动填写等

方法1为监听系统短信数据库,但是存在一个问题,就是收到短信之后需要点击短信进入短信详情页面,才会触发广播

方法2通过监听通知栏,根据发通知的应用包名锁定对应的短信应用,从而可以在收到短信的同时获取短信内容

两种方法在获取短信的时候都是只获取收到回调时最新的一条短信,因此不推荐方法1。


首先需要获取对应的权限,高版本的系统需要写代码动态获取权限

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

  1. 使用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!!)
    
  2. 使用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)手机监听短信的两种解决方案相关推荐

  1. Android实时监听短信并上传服务器

    短信监听 Android监听手机短信的方法有两种,分别为: 1.接受系统的短信广播:当手机收到新消息时,会发送一条广播,通过该广播就可以获取短信内容: 2.监听短信数据库:利用观察者模式监听短信数据库 ...

  2. Android实战简易教程-第三十六枪(监听短信-实现短信验证码自动填入)

    一般用户喜欢用手机号作为用户名注册APP账号,这时一般都是通过手机验证码的方式进行验证,下面我们就研究一个非常实用的方法,通过监听短信-实现短信验证码的自动填入,提高用户体验. 首先我们看一下如何监听 ...

  3. Android 监听短信数据库过滤获取短信内容上传至服务器

    前言 Android 监听短信的方式有两种 1.监听短信数据库,数据库发生改变时回调. 2.监听短信广播 其中第二种方式由于国内各厂家的定制Android 可能导致无响应 目前测试 魅族 无法监听到短 ...

  4. android 监听短信并发送到服务器

    1. 接受系统的短信广播,操作短信内容. 优点:操作方便,适合简单的短信应用. 缺点:来信会在状态栏显示通知信息. 2. 应用观察者模式,监听短信数据库,操作短信内容.   实例如下: SystemE ...

  5. android 发送彩信监听,在Android中发送短信和彩信,监听短信并显示

    发送短信: String body="this is sms demo"; Intent mmsintent = new Intent(Intent.ACTION_SENDTO, ...

  6. android 监听短信并获取验证码

    最近想给 app 添加自动获取短信验证码的功能,让注册流程更加友好,在网上搜索了一些资料,主要的实现方法有两种. 第一:实现广播 BroadCastReceiver 来监听收件箱,在需要监听的地方注册 ...

  7. android发送短信的两种方式,发送长短信的两种方式,群发短信

    android 发送短信的方法 方法一:调用系统的短信APP,发送短信. Intent smsIntent = new Intent(Intent.ACTION_VIEW);smsIntent.set ...

  8. android 监听 短信,Android短信验证码监听解决onChange多次调用的方法

    先说一句:MIUI请放弃治疗!这里给个传送门: 识别短信验证码并提取还是挺常见的一个需求.所要解决的问题主要有: 1.如何监听 2.如何提取短信中的验证码 3.监听多次调用问题 直接看下面代码吧,很明 ...

  9. Android使用Google SMSRetrieverAPI监听短信

    写在开头 google官方介绍 如果在没有读写短信权限的情况下获取用户的短信验证码呢?google为我们提供了SMSRetrieverAPI这个Api.解决了我们在用户收到短信后自动回填界面的需求.但 ...

最新文章

  1. 研究生第一篇科研论文常犯问题总结
  2. Java架构师必知必会,带走不谢
  3. Cuckoo hash算法分析——其根本思想和bloom filter一致 增加hash函数来解决碰撞 节省了空间但代价是查找次数增加...
  4. 怎样查看was的服务器信息,WAS 查看服务状态
  5. python画统计图怎么在右上角表示哪条线代表什么_Python-matplotlib统计图之箱线图漫谈...
  6. Swap Letters CodeForces - 1215C(贪心)
  7. java joda_java-Jodatime的开始时间和结束时间
  8. java sql merge_sql merge用法
  9. windows10程序员计算机,Win10计算器程序员模式如何移位?
  10. 怎么上传本地项目或文件到SVN服务器
  11. 船讯网|爬虫COOKIE重定向反爬处理
  12. 新计算机的word无法输入文字,word打字后面的字消失怎么办
  13. geoserver配置SQL图层 cql_filter模糊查询
  14. [转载]以xilinx为例的低功耗设计
  15. 类 ApplicationInfo详解
  16. Dns与httpDNS的区别
  17. 使用Lumberjack进行日志切割归档
  18. bas64图片加密解密
  19. Java基础练习:用户在控制台输入一个年份,判断该年份是平年还是闰年
  20. 解决主机前面板耳机孔无声问题以华硕主板为例

热门文章

  1. 离职原因该怎么说才比较好 ?
  2. Chrome浏览器的crash问题
  3. 倍福--授权文件拷贝
  4. 2019规划:放下所有,轻松上阵,大胆尝试,勇于实践,经商赚钱,考证提高,随时煅炼
  5. 汽车软件开发相关词汇
  6. 自我激励的有效方法20个(推荐)
  7. python ppt自动生成_实战 | Python自动生成PPT调研报告
  8. 创建Hive外部表,关联HDFS文件
  9. 双18期|CSS揭秘之简写属性
  10. truelicense实现用于JAVA工程license