当前位置: 首页 > news >正文

安卓短信自动填充踩坑

安卓短信自动填充踩坑

前言

最近弄了个短信自动填充功能,一开始觉得很简单,不就是动态注册个广播接收器去监听短信消息不就可以了吗?结果没这么简单,问题就出在机型的适配上。小米的短信权限、荣耀的短信监听都是坑,暂时就用这两个手机测了,其他的遇到了再补充。

下面简单讲讲:

权限

申请权限

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

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

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

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

小米短信权限问题

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

在 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 {@Overridepublic 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();
}
context.registerReceiver(smsReceiver, smsFilter);

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

context.unregisterReceiver(smsReceiver);

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

既然上面的方法没用了,只能找新的办法喽,网上很多提供了两种办法,第二种就是通过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};@Overridepublic 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);}context.getContentResolver().registerContentObserver(Uri.parse("content://sms/"), true, smsObserver);
}

取消注册:

context.getContentResolver().unregisterContentObserver(smsObserver);

结语

这些机型的兼容性搞起来真头疼,上面两种方法可以兼容起来使用,收到一条短信后直接取消注册就行了。

相关文章:

安卓短信自动填充踩坑

安卓短信自动填充踩坑 前言 最近弄了个短信自动填充功能&#xff0c;一开始觉得很简单&#xff0c;不就是动态注册个广播接收器去监听短信消息不就可以了吗&#xff1f;结果没这么简单&#xff0c;问题就出在机型的适配上。小米的短信权限、荣耀的短信监听都是坑&#xff0c;…...

【抽象类和接口的区别】

抽象类和接口都是Java中实现多态的机制&#xff0c;它们都是用来约束子类必须要实现的方法。但是它们有以下区别&#xff1a; 实现方式 实现方式&#xff1a;抽象类是一个类&#xff0c;而接口是一个接口。一个类只能继承一个抽象类&#xff0c;但可以实现多个接口。 构造方…...

接口导出文件功能

1.写接口 export function getExport(params) { return fetch({ url: ******.export, method: post, data: params, responseType:blob, }) } 2.编写前端页面 <el-button :loading"exportDisable" :disabled&quo…...

深圳大学计软《面向对象的程序设计》实验9 期中复习

A. 机器人变身&#xff08;类与对象&#xff09;【期中模拟】 题目描述 编写一个机器人类&#xff0c;包含属性有机器名、血量、伤害值、防御值、类型和等级。其中血量、伤害和防御和等级、类型相关&#xff1a; 普通型机器人&#xff0c;类型为N&#xff0c;血量、伤害、防…...

python之异步编程

一、异步编程概述 异步编程是一种并发编程的模式&#xff0c;其关注点是通过调度不同任务之间的执行和等待时间&#xff0c;通过减少处理器的闲置时间来达到减少整个程序的执行时间&#xff1b;异步编程跟同步编程模型最大的不同就是其任务的切换&#xff0c;当遇到一个需要等…...

为什么很多计算机专业大学生毕业后还会参加培训?

基于IT互联网行业越来越卷的现状&#xff0c;就算是科班出身&#xff0c;很多也是达不到用人单位的要求。面对这样的现实情况&#xff0c;有的同学会选择继续深造&#xff0c;比如考个研&#xff0c;去年考研人数457万人次&#xff0c;可见越来越的同学是倾向考研提升学历来达到…...

JUC并发编程之JMM_synchronized_volatile

目录 JUC并发编程之JMM_synchronized_volatile 什么是JMM模型&#xff1f; JMM和JVM的区别 JMM不同于JVM内存区域模型 主内存 工作内存 Java内存模型与硬件内存架构的关系 JMM存在的必要性 数据同步八大原子操作 同步规则分析 并发编程的可见性&#xff0c;原子性与有序…...

hashCode 和 equals 的处理

文章目录hashCode 和 equals 的处理1. 阿里巴巴编程规范要求2. equals和hashcode的分析2.1 Object方法2.2 只覆写&#xff08;Override&#xff09;equals带来的问题问题演示问题分析问题处理hashCode 和 equals 的处理 1. 阿里巴巴编程规范要求 2. equals和hashcode的分析 2…...

17. OPenGL实现旋转移动物体

1. 说明&#xff1a; 整体思路&#xff1a;如果想实现动态&#xff0c;可以使用一个矩阵和我们给定的坐标值进行相乘&#xff0c;实时的改变坐标值 类似于坐标的齐次变换&#xff0c;然后使用一个定时器&#xff0c;在规定时间内触发重新绘制的函数。 实际效果&#xff1a; OP…...

《SQL基础》14. 存储过程 · 存储函数

存储过程 存储函数存储过程基本语法变量系统变量用户定义变量局部变量if判断参数case判断while循环repeat循环loop循环游标条件处理程序存储函数存储过程 存储过程是事先经过编译并存储在数据库中的一段SQL语句的集合。调用存储过程可以简化应用开发人员的工作&#xff0c;减…...

NFT Insider #87:The Sandbox 收购游戏开发工作室 Sviper,GHST 大迁徙即将拉开帷幕

引言&#xff1a;NFT Insider由NFT收藏组织WHALE Members(https://twitter.com/WHALEMembers)、BeepCrypto&#xff08;https://twitter.com/beep_crypto&#xff09;联合出品&#xff0c;浓缩每周NFT新闻&#xff0c;为大家带来关于NFT最全面、最新鲜、最有价值的讯息。每期周…...

html部分codewhy网课学习笔记

day1 网页显示的过程和服务器 浏览器内核,也称为渲染引擎 head标签描述网页的原数据&#xff0c;如title shifttab是向前缩进 div>ul>li可以快速生成 <div> <ul> <li></li> </ul> </div> 在早期,单标签如<input>也可写为&l…...

电脑出问题了怎么重装系统修好

电脑在使用过程中经常会出现各种各样的问题&#xff0c;如系统崩溃、蓝屏、病毒感染等。这些问题如果不能及时得到解决&#xff0c;将会给用户带来很多麻烦和损失。小白一键重装系统是一个功能强大的工具&#xff0c;可以帮助用户快速解决电脑常见问题。下面我们就来详细介绍如…...

Nginx国密支持问题记录

文章目录添加国密支持可能出现的问题国密不生效&#xff0c;查看 Nginx 可执行文件路径是否正确证书无法解析Nginx无法启动添加国密支持 NGINX添加国密支持 添加国密支持可以直接按照官网的操作顺序操作即可 参考网址&#xff1a;https://www.gmssl.cn/gmssl/index.jsp 可能出…...

基于ensp的小型局域网网络搭建及需求分析

一 需求分析本实验的目的在于建立小型局域网。由于公司由财政部、人事部、科技部三个部门组成&#xff0c;分布在同一个交换机下。设计以下网络&#xff1a;三个个部门使用两台交换机连接&#xff0c;然后连接到汇聚交换机&#xff0c;再通过路由器与外网以及其他部门网络相连。…...

Kubernetes学习(二)Pod

创建Pod kubectl创建nginx pod 编写 nginx pod的yaml文件 apiVersion: v1 kind: Pod metadata:name: my-nginxlabels:name: my-nginx spec:containers:- image: nginxname: my-nginxresources:limits:memory: "128Mi"cpu: "500m"ports:- name: nginx-po…...

【Docker】docker | 迁移docker目录

一、场景说明1、物理机磁盘空间不够用了2、docker的镜像、容器、卷等资料的默认路径为&#xff1a; /var/lib/docker3、增加了数据盘挂在&#xff0c;需要将docker的全部资料更换个目录二、操作确认是否满足切换条件1&#xff09;服务是否能够暂停&#xff0c;如果可以就OK2&am…...

day24_多线程进阶

今日内容 上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili 同步笔记沐沐霸的博客_CSDN博客-Java2301 零、 复习昨日 一、作业 二、线程安全的集合 三、死锁 四、线程通信 五、生产者消费者 六、线程池 零、 复习昨日 创建线程的几种方式 1) 继承 2) 实现Runnable 3) calla…...

Qt实现系统桌面目录下文件搜索的GUI:功能一:文件查找与现实

⭐️我叫恒心&#xff0c;一名喜欢书写博客的研究生在读生。 原创不易~转载麻烦注明出处&#xff0c;并告知作者&#xff0c;谢谢&#xff01;&#xff01;&#xff01; 这是一篇近期会不断更新的博客欧~~~ 有什么问题的小伙伴 欢迎留言提问欧。 功能点一&#xff1a;文件查找与…...

有关数据库的一级、二级、三级封锁协议

一级封锁协议 一级封锁协议是指&#xff0c;事务T在修改数据R之前必须先对其加X锁&#xff0c;直到事务结束才释放。事务结束包括正常结束&#xff08;COMMIT&#xff09;和非正常结束&#xff08;ROLLBACK).一级封锁协议可防止丢失修改&#xff0c;并保证事务T是可恢复的。在…...

GPU硬件操作强度与LLM推理效率优化实践

1. 硬件操作强度&#xff08;HOI&#xff09;与LLM推理效率的深度解析在GPU加速的大型语言模型推理场景中&#xff0c;我们常常遇到一个看似矛盾的现象&#xff1a;计算单元利用率不足的同时&#xff0c;显存带宽却成为瓶颈。这种现象的根源在于硬件操作强度&#xff08;Hardwa…...

别再死记硬背截止、放大、饱和了!用Arduino+面包板,5分钟直观演示三极管三种工作状态

用Arduino实战破解三极管工作状态的秘密 记得第一次学三极管时&#xff0c;盯着课本上那些截止区、放大区、饱和区的曲线图&#xff0c;我完全无法理解这些抽象概念和实际电路有什么关系。直到有一天&#xff0c;我在实验室里用Arduino和几个简单元件搭建了一个测试电路&#x…...

AI技能学习路径全解析:从数学基础到RAG实战与项目构建

1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“HieuNghi-AI-Skills”。光看这个名字&#xff0c;你可能会有点摸不着头脑&#xff0c;这到底是做什么的&#xff1f;是教AI新技能&#xff0c;还是整理AI工具的使用技巧&#xff1f;点进去之后&…...

NVIDIA aicr:AI容器运行时核心原理与生产部署指南

1. 项目概述&#xff1a;当AI遇见容器运行时如果你在AI开发或者高性能计算领域摸爬滚打过一段时间&#xff0c;大概率会遇到一个让人头疼的问题&#xff1a;如何高效、稳定地管理那些“胃口”巨大、依赖复杂的AI工作负载&#xff1f;从训练一个大型语言模型到运行一个实时的计算…...

信发系统-排版/发布 配置操作教程-智慧大屏幕—东方仙盟

政务大屏幕节目管理-选择系统模板选择对应行业选择适合的模板选中你的节目点击设计设计节目直接管理/上传 资源&#xff1a;图片/视频/网页/文字/文档手指/鼠标选中显示区域上传资源&#xff0c;在右侧点击上传从资源库选择图片选择历史素材上传网站选中网页区域点击上传配置文…...

5分钟彻底解决Windows软件DLL缺失问题:VisualCppRedist AIO完整修复方案

5分钟彻底解决Windows软件DLL缺失问题&#xff1a;VisualCppRedist AIO完整修复方案 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过新安装的软…...

NotebookLM深度绑定Google Drive的终极方案(含OAuth2作用域最小化清单+服务账号部署模板)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;NotebookLM深度绑定Google Drive的终极方案&#xff08;含OAuth2作用域最小化清单服务账号部署模板&#xff09; NotebookLM 本地知识增强能力依赖于安全、稳定且权限精确的 Google Drive 数据接入。直…...

Abaqus 6.12 保姆级教程:手把手教你搞定悬臂梁的动力学仿真(附阻尼设置与结果动画)

Abaqus 6.12 悬臂梁动力学仿真全流程实战&#xff1a;从阻尼优化到动画渲染 悬臂梁作为结构动力学分析的经典案例&#xff0c;在机械振动、建筑抗震等领域具有广泛的应用价值。本文将基于Abaqus 6.12平台&#xff0c;通过一个完整的动力学仿真案例&#xff0c;深入解析从模型建…...

【Leona】BoxId 是什么-设备指纹参数

BoxId 是什么&#xff1f;从 Leona.sense() 到 /v1/verdict 的可落地闭环&#xff1a;签名、落库、错误处理与回归验证&#xff08;基于公开示例&#xff09; TL;DR BoxId 不是“风险结论”&#xff0c;而是一次“证据报告兑换券”&#xff1a;端上拿 BoxId&#xff0c;后端换证…...

航模老鸟的‘省钱’秘籍:一块BB响如何守护你的多块锂电池(附设置误区避坑)

航模电池管理的低成本智慧&#xff1a;BB响的进阶使用策略 在航模和无人机领域&#xff0c;电池管理一直是玩家们关注的焦点。对于拥有多块电池的资深爱好者或小型工作室来说&#xff0c;如何在保证安全的前提下优化成本&#xff0c;是一个值得深入探讨的话题。传统做法是为每块…...