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

三星S23 Ultra上Flutter应用OTP自动检测异常求助

解决三星S23 Ultra上SMS Retriever API的系统错误弹窗问题

问题根源

三星S23 Ultra的Android系统对广播接收器的权限校验逻辑更严格,原代码中注册接收器时错误使用了SmsRetriever.SEND_PERMISSION(该权限用于发送短信而非接收广播),且注销时机不当,导致系统触发"连接出现问题,请重试"的错误弹窗。

修复方案

1. 调整广播接收器注册逻辑

移除不必要的权限参数,保留Android 13+的接收器导出状态限制,避免系统权限校验异常。

2. 优化接收器注销时机

将接收器注销操作移到OTP处理完成、超时或异常发生后,避免系统后续回调找不到接收器引发错误。

3. 完善错误回调处理

确保Flutter端能接收所有状态的回调,避免未处理的异常触发系统提示。

修改后的代码

依赖项(保持不变)

implementation("com.google.android.gms:play-services-ads-identifier:18.0.1")
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation("com.moengage:rich-notification:5.0.1")
implementation("com.moengage:push-amp:4.6.1")
implementation("com.github.bumptech.glide:glide:4.9.0")
annotationProcessor("com.github.bumptech.glide:compiler:4.9.0")
implementation("com.google.android.gms:play-services-tagmanager:18.0.4")
implementation "androidx.core:core-ktx:1.13.1"
implementation 'com.google.android.gms:play-services-auth-api-phone:18.0.1'

修改后的Method Channel代码

MethodChannel(flutterEngine.dartExecutor.binaryMessenger, SmsChannel)
    .setMethodCallHandler { call, result ->
        when (call.method) {
            "listenForCode" -> try {
                pendingResult = result
                receiver = MySMSBroadcastReceiver()
                val intentFilter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                    context.registerReceiver(
                        receiver,
                        intentFilter,
                        ContextCompat.RECEIVER_NOT_EXPORTED
                    )
                } else {
                    context.registerReceiver(
                        receiver,
                        intentFilter
                    )
                }
                startListening()

            } catch (e: Exception) {
                Log.e(Tag, "listenForCode exception: ${e}")
                result.error("INIT_FAILED", "Failed to start listening for OTP", e.message)
            }

            "stopListeningForOTPCode" -> {
                unregister(receiver)
                pendingResult?.error("STOPPED", "Listening stopped manually", null)
                pendingResult = null
                result.success(null)
            }

            "getAppSignature" -> {
                Log.i(Tag, "getAppSignature: started")
                val signature = AppSignatureHelper(context).getAppSignature()
                Log.i(Tag, "getAppSignature: $signature")
                result.success(signature);
            }
            else -> {
                result.notImplemented()
            }
        }
    }

修改后的广播接收器类代码

class MySMSBroadcastReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        try {
            if (intent.action != SmsRetriever.SMS_RETRIEVED_ACTION) return
            
            val extras = intent.extras ?: run {
                pendingResult?.error("NO_EXTRAS", "No data received from SMS Retriever", null)
                unregister(receiver)
                pendingResult = null
                return
            }
            
            val status = extras.get(SmsRetriever.EXTRA_STATUS) as? Status ?: run {
                pendingResult?.error("NO_STATUS", "No status received", null)
                unregister(receiver)
                pendingResult = null
                return
            }

            when (status.statusCode) {
                CommonStatusCodes.SUCCESS -> {
                    val sms = extras.getString(SmsRetriever.EXTRA_SMS_MESSAGE) ?: run {
                        pendingResult?.error("NO_SMS", "No SMS content received", null)
                        unregister(receiver)
                        pendingResult = null
                        return
                    }
                    ignoreIllegalState {
                        val regex = Regex("\\b\\d{4,6}\\b")
                        regex.find(sms)?.let { matchResult ->
                            pendingResult?.success(matchResult.value)
                        } ?: run {
                            pendingResult?.error("NO_OTP", "No valid OTP found in SMS", null)
                        }
                    }
                }
                CommonStatusCodes.TIMEOUT -> {
                    Log.e(Tag, "onReceive Timeout ")
                    pendingResult?.error("TIMEOUT", "OTP retrieval timed out", null)
                }
                else -> {
                    pendingResult?.error("RETRIEVE_FAILED", "OTP retrieval failed with code: ${status.statusCode}", null)
                }
            }
            // 统一处理完后注销接收器
            unregister(receiver)
            pendingResult = null
        } catch (e : Exception) {
            Log.e(Tag, "onReceive Exception ${e}")
            pendingResult?.error("EXCEPTION", "Error retrieving OTP: ${e.message}", null)
            unregister(receiver)
            pendingResult = null
        }
    }
}

补充说明

  • 移除SmsRetriever.SEND_PERMISSION是因为该权限与接收广播无关,三星系统对权限的额外校验会触发错误提示;
  • 延迟注销接收器确保系统完成所有广播回调流程,避免系统找不到接收器引发异常;
  • 完善的错误回调能让Flutter端及时处理各种异常情况,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 15:53:19