近期开发了一个短信自动填充的功能,原本以为只要简单地动态注册一个广播接收器监听短信消息就能顺利完成任务,但实际上却遭遇了多个手机品牌在权限管理和适配上的种种挑战。主要集中在小米、荣耀和OPPO这三大手机品牌的短信权限获取和监听机制上。
首先,在Android 6.0之后,短信相关的READ_SMS和RECEIVE_SMS权限被归类为隐私权限,需要在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};
然而,小米手机的短信权限管理与众不同,其将短信权限划归至通知类权限范畴。常规的权限检查可能会导致误判,即虽然表面上权限已经获得,但实际上在使用广播接收器监听之前并未真正获取。为解决这一问题,采取了一种特殊策略:通过尝试读取短信内容来判断是否已取得权限。
Uri uri = Uri.parse("content://sms/inbox");
// ... 省略部分代码
接下来,编写了SmsReceiver
作为广播接收器,能够成功处理小米手机上的短信监听。但在荣耀手机上,尽管同样使用了此代码,却发现有时只能收到一次短信,后续的短信便无法被正确接收。经过排查,确定这是由于荣耀手机的特定适配问题。
以下是SmsReceiver
的核心代码片段:
public class SmsReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// ... 省略具体处理逻辑
}
}
使用时,需要动态注册和注销广播接收器:
IntentFilter smsFilter = new IntentFilter();
smsFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
smsFilter.addAction("android.provider.Telephony.SMS_DELIVER");
// ... 注册和注销相关代码
面对OPPO手机无法接收到短信广播的问题,研究发现OPPO以及华为、荣耀等品牌手机为了保护短信验证码安全,会限制后台应用读取短信。此时,可以通过ContentObserver的方式监听短信数据库的变化,但需要注意的是,即便触发了onChange事件,也可能因为权限限制无法获取最新短信内容。
为此,设计了一个ReadSmsObserver
类,利用ContentResolver监听短信收件箱的更新。并在荣耀手机无法连续监听短信的问题上,采用了结合广播和ContentObserver双管齐下的策略,一旦ContentObserver的onChange触发,延时等待一段时间看是否能接收到短信广播,从而确保无论何种情况下都能尽可能捕捉到新短信的到来。
总之,短信自动填充功能在跨手机平台适配上确实存在不少“坑”,针对不同的手机品牌需要针对性地解决权限管理、监听机制等方面的问题。文中提出的解决方案仅供参考,并建议开发者在实际项目中灵活运用,并结合特定手机系统的特性优化代码,以应对可能出现的其他适配问题。