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

咨询:SmsRetriever能否在Android模拟器运行?回调未触发问题

解决SMS Retriever API模拟器测试时BroadcastReceiver不回调的问题

我之前也碰到过一模一样的问题,折腾了好半天才找到原因,给你几个核心的排查和解决方向:

1. 先确认短信格式完全符合要求

这是最容易踩坑的点!SMS Retriever API只会拦截包含应用签名哈希值的短信,格式必须满足:

  • 短信内容可以包含任意文本,但末尾必须跟上你的应用的11位哈希值(比如FA+9qCX9VSu)
  • 哈希值要单独放在一行,或者跟在文本最后,不能被其他内容截断

怎么获取这个哈希值?可以用Google官方提供的AppSignatureHelper类生成,代码大概是这样:

public class AppSignatureHelper extends ContextWrapper {
    private static final String TAG = "AppSignatureHelper";
    private static final int NUM_HASHED_BYTES = 9;
    private static final int NUM_BASE64_CHAR = 11;

    public AppSignatureHelper(Context context) {
        super(context);
    }

    public ArrayList<String> getAppSignatures() {
        ArrayList<String> appCodes = new ArrayList<>();
        try {
            String packageName = getPackageName();
            PackageManager packageManager = getPackageManager();
            Signature[] signatures = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures;
            for (Signature signature : signatures) {
                String hash = hash(packageName, signature.toByteArray());
                if (hash != null) {
                    appCodes.add(String.format("%s", hash));
                }
            }
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "Unable to find package to obtain signature", e);
        }
        return appCodes;
    }

    private String hash(String packageName, byte[] signature) {
        String appInfo = packageName + " " + Base64.encodeToString(signature, Base64.NO_WRAP);
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(appInfo.getBytes(StandardCharsets.UTF_8));
            byte[] hashSignature = messageDigest.digest();
            hashSignature = Arrays.copyOfRange(hashSignature, 0, NUM_HASHED_BYTES);
            String base64Hash = Base64.encodeToString(hashSignature, Base64.NO_PADDING | Base64.NO_WRAP);
            base64Hash = base64Hash.substring(0, NUM_BASE64_CHAR);
            return base64Hash;
        } catch (NoSuchAlgorithmException e) {
            Log.e(TAG, "Unable to compute hash: " + e);
        }
        return null;
    }
}

调用这个类的getAppSignatures()就能拿到你的应用的哈希值,注意debug和release签名的哈希是不一样的,模拟器用的是debug签名的哈希。

2. 检查BroadcastReceiver的注册是否正确

  • 如果是动态注册:要确保在调用SmsRetrieverClient.startSmsRetriever()之前完成注册,而且不要提前调用unregisterReceiver()
  • 如果是静态注册(推荐),必须在AndroidManifest.xml里正确声明:
<receiver
    android:name=".YourSmsRetrieverReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED" />
    </intent-filter>
</receiver>

这里android:exported="true"必须加,因为是系统给你的广播接收器发消息,必须允许外部访问。

3. 模拟器手动发短信的局限性

很多Android模拟器(比如默认的AVD)手动发送短信的时候,并不会触发SMS Retriever的广播——因为这个API是监听运营商下发的短信通道,而手动发的短信不走这个流程。

解决方法是用adb命令模拟真实短信,比如:

adb shell am broadcast -a com.google.android.gms.auth.api.phone.SMS_RETRIEVED --es sms "你的验证码是123456。FA+9qCX9VSu"

或者用更贴近真实场景的短信发送命令:

adb shell service call isms 5 s16 "com.android.mms.service" s16 "+1234567890" s16 "【你的应用名】你的验证码是123456。FA+9qCX9VSu" s16 null s16 null

用adb发的短信会触发系统的短信接收流程,就能正常触发你的BroadcastReceiver了。

4. 其他排查点

  • 检查模拟器的Google Play Services版本:必须是10.2以上的版本,建议更新到最新版
  • 确认你的onReceive()方法里的逻辑没有问题:比如有没有正确判断SmsRetriever.SMS_RETRIEVED_ACTION,有没有处理Status的不同状态(比如超时、成功)
  • 不需要申请READ_SMS权限:SMS Retriever API不需要这个权限,别画蛇添足加了反而出问题

内容的提问来源于stack exchange,提问作者esilver

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:40:32