1、ContentObserver 监听:通过注册 ContentObserver 来监听短信内容的变化,当有新的短信到来时,ContentObserver 的 onChange 方法会被触发。
2、读取短信内容:在 onChange 方法中,查询短信数据库(通常是 content://sms/inbox),获取最新的短信内容。
3、解析短信内容:使用正则表达式等方法从短信内容中提取出验证码或其他需要的信息。
4、自动填充:将提取到的信息自动填充到指定的输入框中,如验证码输入框。
1、添加权限:在 AndroidManifest.xml 文件中添加接收短信和读取短信的权限。
<uses-permission android:name="android.permission.RECEIVE_SMS" /> <uses-permission android:name="android.permission.READ_SMS" />
2、创建 ContentObserver:创建一个继承自 ContentObserver 的类,用于监听短信内容的变化。
public class SMSContentObserver extends ContentObserver { private Context mContext; private Handler mHandler; private String code; public SMSContentObserver(Context context, Handler handler) { super(handler); mContext = context; mHandler = handler; } @Override public void onChange(boolean selfChange, Uri uri) { Log.e("XXXXXXXXXXXXXXXX", uri.toString()); if (uri.toString().equals("content://sms/raw")) { return; } Uri inboxUri = Uri.parse("content://sms/inbox"); Cursor c = mContext.getContentResolver().query(inboxUri, null, null, null, "date desc"); if (c != null) { if (c.moveToFirst()) { String address = c.getString(c.getColumnIndex("address")); String body = c.getString(c.getColumnIndex("body")); if (!address.equals("你的目标号码")) { return; } Pattern pattern = Pattern.compile("(\d{6})"); Matcher matcher = pattern.matcher(body); if (matcher.find()) { code = matcher.group(0); mHandler.obtainMessage(1, code).sendToTarget(); } } c.close(); } } }
3、注册 ContentObserver:在 Activity 或 Service 中注册 ContentObserver。
Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 1) { String code = (String) msg.obj; // 在这里将验证码填充到输入框中 EditText editText = findViewById(R.id.smsCode); editText.setText(code); } } }; SMSContentObserver observer = new SMSContentObserver(this, handler); getContentResolver().registerContentObserver(Uri.parse("content://sms/"), true, observer);
4、动态申请权限:在运行时动态申请接收短信和读取短信的权限。
if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_SMS}, 1); }
1、小米手机:小米手机对短信权限的管理较为严格,可能会将短信归类到通知类权限中,在动态申请权限时,需要先尝试读取短信,然后再进行监听。
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(); flag = true; } } catch (Exception e) { flag = false; } if (!flag) { // 提示用户去设置中打开短信权限 } else { // 注册广播接收器进行监听 }
2、华为手机:华为手机有自己的获取短信方式,可以通过调用华为的 SmsServiceUtils 类的静态方法来获取短信验证码,需要注意的是,这种方式不需要添加任何短信权限,但需要在项目根目录的 build.gradle 文件中添加相关依赖,并在应用的 manifest 文件中注册广播接收器。
dependencies { implementation 'com.huawei.agconnect:agconnect-core:1.6.1.300' implementation 'com.huawei.agconnect:agconnect-auth:1.6.1.300' }
<receiver android:name=".MySMSBroadcastReceiver" android:exported="true"> <intent-filter> <action android:name="com.huawei.android.app.smsinject.intent.action.SMS_INJECTED" /> </intent-filter> </receiver>
public class MySMSBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("com.huawei.android.app.smsinject.intent.action.SMS_INJECTED")) { Bundle bundle = intent.getExtras(); Object[] pdus = (Object[]) bundle.get("pdus"); StringBuilder message = new StringBuilder(); for (Object pdu : pdus) { SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu); message.append(smsMessage.getMessageBody()); } // 在这里处理短信内容,如提取验证码并填充到输入框中 } } }
1、问题:为什么在某些手机上短信自动填充功能无法正常工作?
解答:可能是由于不同品牌手机对短信权限的管理方式不同,导致无法正常读取短信内容,小米手机可能会将短信归类到通知类权限中,而华为手机有自己的获取短信方式,针对这种情况,需要根据不同的手机品牌进行适配,确保能够正常读取短信内容并进行自动填充。
2、问题:如何提高短信自动填充的准确性?
解答:可以通过优化正则表达式的匹配规则,确保能够准确地从短信内容中提取出验证码或其他需要的信息,可以增加对短信内容的预处理,如去除特殊字符、空格等,以提高匹配的准确性,还可以结合其他信息,如发送方号码、短信时间等,来进一步筛选和验证短信内容,提高自动填充的准确性。