三星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
相关产品推荐
相关产品推荐

