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

Jetpack Compose下通过SmsRetriever短信广播获取OTP失败抛出空指针异常

问题根因

  1. SystemBroadcastReceiver 实现错误:你将 SmsRetriever.SEND_PERMISSION 这个权限值错误当成广播 Action 注册了第二个无效的广播接收器,接收到非法广播 Intent 后触发了 Firebase Auth 内部的空指针异常
  2. 注册广播接收器时没有传入对应的权限校验,导致第三方恶意广播也能触发你的接收器逻辑
  3. 代码中存在多处未做空安全校验的强转逻辑
  4. OTP提取函数没有做边界校验,短信内数字不足指定长度时会触发下标越界异常

修复方案

1. 重写 SystemBroadcastReceiver 函数

删除无效的第二个广播注册逻辑,注册时正确传入权限参数:

@Composable
fun SystemBroadcastReceiver(
    systemAction: String,
    broadCastPermission: String,
    onSystemEvent: (intent: Intent?) -> Unit
) {
    val context = LocalContext.current
    val currentOnSystemEvent by rememberUpdatedState(onSystemEvent)

    DisposableEffect(context, systemAction, broadCastPermission) {
        val intentFilter = IntentFilter(systemAction)
        val broadcast = object : BroadcastReceiver() {
            override fun onReceive(context: Context?, intent: Intent?) {
                currentOnSystemEvent(intent)
            }
        }
        // 注册时正确传入权限参数
        context.registerReceiver(broadcast, intentFilter, broadCastPermission, null)

        onDispose {
            context.unregisterReceiver(broadcast)
        }
    }
}

2. 修复 SmsRetrieverUserConsentBroadcast 中的强转空安全问题

对 Status 提取逻辑增加空判断:

if (shouldRegisterReceiver) {
    SystemBroadcastReceiver(
        systemAction = SmsRetriever.SMS_RETRIEVED_ACTION,
        broadCastPermission = SmsRetriever.SEND_PERMISSION,
    ) { intent ->
        if (intent != null && SmsRetriever.SMS_RETRIEVED_ACTION == intent.action) {
            val extras = intent.extras
            // 增加空判断避免强转空指针
            val smsRetrieverStatus = extras?.get(SmsRetriever.EXTRA_STATUS) as? Status ?: return@SystemBroadcastReceiver
            when (smsRetrieverStatus.statusCode) {
                CommonStatusCodes.SUCCESS -> {
                    val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
                    consentIntent?.let {
                        try {
                            launcher.launch(it)
                        } catch (e: ActivityNotFoundException) {
                            // 可添加异常上报逻辑
                        }
                    }
                }
                CommonStatusCodes.TIMEOUT -> {
                    shouldRegisterReceiver = false
                }
            }
        }
    }
}

3. 修复 OTP 提取函数的边界校验

internal fun getVerificationCodeFromSms(sms: String, smsCodeLength: Int): String {
    val digits = sms.filter { it.isDigit() }
    return if (digits.length >= smsCodeLength) {
        digits.substring(0, smsCodeLength)
    } else {
        ""
    }
}

额外校验项

  • 检查应用是否已经申请了android.permission.RECEIVE_SMS权限,Android 13及以上版本需要动态申请该权限
  • 确认服务端发送的OTP短信格式符合Google SMS Retriever要求:长度不超过140字节,包含<#>前缀和你的应用11位哈希后缀

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 19:06:01