You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SmsRetrieverClient广播接收器不触发onReceive仅超时触发问题咨询

解决SmsRetrieverClient广播接收器不触发的问题

看起来你遇到的是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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:22:54