SmsRetrieverClient广播接收器不触发onReceive仅超时触发问题咨询
看起来你遇到的是SmsRetriever最常见的问题之一——短信到达时onReceive不执行,只触发超时回调。这大概率是短信格式不符合要求,或者接收器注册/配置有问题,我帮你梳理几个关键排查点:
1. 短信格式必须严格匹配Google的规范
这是最容易踩坑的地方,SmsRetriever只会识别符合特定格式的短信,缺一不可:
- 短信内容必须包含应用签名哈希字符串(长度11-13位,由你的应用签名生成)
- 可以包含明确的验证码(你的代码里匹配4位数字,没问题)
- 哈希字符串通常放在短信末尾,前面可以加
#(不是必须,但建议加上)
示例合规短信:
Your verification code is 1234.
#ABCDEFGHIJKL
怎么生成正确的签名哈希?
用Google官方提供的命令行工具生成,注意区分debug和release签名:
# 替换YOUR_KEY_ALIAS、YOUR_KEYSTORE_PATH、YOUR_PACKAGE_NAME为你的实际信息 keytool -exportcert -alias YOUR_KEY_ALIAS -keystore YOUR_KEYSTORE_PATH | xxd -p | tr -d "[:space:]" | echo -n YOUR_PACKAGE_NAME `cat` | sha256sum | tr -d "[:space:]-" | xxd -r -p | base64 | cut -c1-11
如果用debug keystore,默认路径是~/.android/debug.keystore,alias是androiddebugkey,密码android。
2. 调整广播接收器的注册时机
你当前是在startSmsRetriever成功后才注册接收器,这会导致如果短信在onSuccess回调之前到达,接收器还没注册,直接错过广播。
建议先注册接收器,再启动SmsRetriever,调整代码如下:
private void startSMSListener() { // 1. 先初始化并注册广播接收器 SMSBroadcastReceiver.OTPListener otpListener = new SMSBroadcastReceiver.OTPListener() { @Override public void onOTPReceived(String otpData) { inputOTP.setText(otpData); } @Override public void onOTPTimeOut() { inputOTP.setText(""); Toast.makeText(ctx, "TimeOut", Toast.LENGTH_SHORT).show(); } }; smsBroadcastReceiver.injectOTPListener(otpListener); registerReceiver(smsBroadcastReceiver, new IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION)); // 2. 再启动SmsRetriever监听 SmsRetrieverClient smsRetrieverClient = SmsRetriever.getClient(this); Task<Void> retriever = smsRetrieverClient.startSmsRetriever(); retriever.addOnSuccessListener(aVoid -> Toast.makeText(ctx, "SMS listener started", Toast.LENGTH_SHORT).show() ); retriever.addOnFailureListener(e -> Toast.makeText(ctx, "Failed to start listener", Toast.LENGTH_SHORT).show() ); }
另外,记得在Activity销毁时注销接收器,避免内存泄漏:
@Override protected void onDestroy() { super.onDestroy(); if (smsBroadcastReceiver != null) { unregisterReceiver(smsBroadcastReceiver); } }
3. 检查Manifest的接收器配置
你的Manifest里接收器的android:name是\.SMSBroadcastReceiver,如果接收器在根包下,应该写成.SMSBroadcastReceiver或者全类名(比如com.yourcompany.SMSBroadcastReceiver),确保系统能找到这个类。
另外,android:exported="true"是正确的,因为SmsRetriever是系统级广播,需要接收器对外可见。
4. 测试环境的注意事项
- 不要用模拟器测试:部分模拟器不支持SmsRetriever服务,务必用真实设备测试。
- 用真实短信网关发送测试短信:模拟器自带的短信发送功能不会触发SmsRetriever,必须从实际的短信服务商发送。
- 匹配签名哈希:测试时用的APK签名(debug/release)必须和生成哈希时用的签名一致,不然哈希不匹配,系统不会识别短信。
5. 日志排查
打开Logcat,搜索SmsRetriever关键词:
- 如果看到
SMS retriever found matching message,说明系统识别到了短信,问题出在你的接收器逻辑; - 如果没有这条日志,说明短信格式或哈希有问题,系统没识别到。
内容的提问来源于stack exchange,提问作者yashraj sharma

