使用 SmsRetriever 时接收广播 Intent 时出错
Posted
技术标签:
【中文标题】使用 SmsRetriever 时接收广播 Intent 时出错【英文标题】:Error receiving broadcast Intent when using SmsRetriever 【发布时间】:2021-04-24 11:18:45 【问题描述】:使用 Firebase Auth 进行身份验证时,我想自动输入通过 SMS 接收的代码。我能够接收短信并手动完成身份验证过程,但是当我使用 SmsRetriever 时,应用程序崩溃,然后显示底部工作表对话框。这就是出现在 Logcat 中的所有内容:
java.lang.RuntimeException: Error receiving broadcast Intent act=com.google.android.gms.auth.api.phone.SMS_RETRIEVED flg=0x200010 pkg=com.finca.bank (has extras) in com.google.android.gms.internal.firebase-auth-api.zzvb@45fb8c5
at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0$LoadedApk$ReceiverDispatcher$Args(LoadedApk.java:1566)
at android.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7562)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'int java.lang.CharSequence.length()' on a null object reference
at java.util.regex.Matcher.reset(Matcher.java:280)
at java.util.regex.Matcher.<init>(Matcher.java:186)
at java.util.regex.Pattern.matcher(Pattern.java:1034)
at com.google.android.gms.internal.firebase-auth-api.zzvd.zzf(com.google.firebase:firebase-auth@@20.0.1:1)
at com.google.android.gms.internal.firebase-auth-api.zzvb.onReceive(com.google.firebase:firebase-auth@@20.0.1:8)
at android.app.LoadedApk$ReceiverDispatcher$Args.lambda$getRunnable$0$LoadedApk$ReceiverDispatcher$Args(LoadedApk.java:1556)
at android.app.-$$Lambda$LoadedApk$ReceiverDispatcher$Args$_BumDX2UKsnxLVrE6UJsJZkotuA.run(Unknown Source:2)
这是我的 Fragment 中接收 SMS 的代码:
private val SMS_CONSENT_REQUEST = 2 // Set to an unused request code
private val smsVerificationReceiver = object : BroadcastReceiver()
override fun onReceive(context: Context, intent: Intent)
try
if (SmsRetriever.SMS_RETRIEVED_ACTION == intent.action)
val extras = intent.extras
val smsRetrieverStatus = extras?.get(SmsRetriever.EXTRA_STATUS) as Status
when (smsRetrieverStatus.statusCode)
CommonStatusCodes.SUCCESS ->
// Get consent intent
val consentIntent = extras.getParcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)
try
// Start activity to show consent dialog to user, activity must be started in
// 5 minutes, otherwise you'll receive another TIMEOUT intent
startActivityForResult(consentIntent, SMS_CONSENT_REQUEST)
catch (e: ActivityNotFoundException)
// Handle the exception ...
CommonStatusCodes.TIMEOUT ->
// Time out occurred, handle the error.
catch (e: Exception)
Timber.e(e, "onReceive: ")
override fun onResume()
super.onResume()
val task = SmsRetriever.getClient(requireActivity()).startSmsUserConsent(null)
val intentFilter = IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION)
requireActivity().registerReceiver(smsVerificationReceiver, intentFilter)
override fun onPause()
super.onPause()
requireActivity().unregisterReceiver(smsVerificationReceiver)
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?)
super.onActivityResult(requestCode, resultCode, data)
when (requestCode)
// ...
SMS_CONSENT_REQUEST ->
// Obtain the phone number from the result
if (resultCode == Activity.RESULT_OK && data != null)
// Get SMS message content
val message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)
// Extract one-time code from the message and complete verification
// `message` contains the entire text of the SMS message, so you will need
// to parse the string.
message?.let presenter.parseSms(it)
// send one time code to the server
else
// Consent denied. User can type OTC manually.
有趣的是,在极少数情况下进展顺利,我不知道这取决于什么。此外,如果在onReceive
中设置断点,则在调试模式下一切顺利
【问题讨论】:
您找到解决方法了吗?因为我遇到了同样的问题,我不知道如何解决这个问题,因为我从“com.google.android.gms.internal.firebase-auth-api”获得内部错误 @AlexD。可悲的是没有。现在我决定不使用 SmsRetriever。 我也面临同样的问题。 firebase 电话身份验证的默认 sms-retreval 不起作用。这就是为什么我尝试放置一个自定义短信检索器并遇到同样的崩溃。 您是否尝试将注册广播接收器移动到 onCreate 并在 onStop 中取消注册?我认为主要问题来自生命周期状态 我想看看你的短信格式 【参考方案1】:经过多次调查,这次崩溃的根本原因似乎与 Firebase Auth Instant Verification 功能和 SMS consent API 之间的冲突有关。
要修复它,您有两种选择:
-
删除 SMS 同意 API 并仅依赖即时验证
使用 SMS Consent API 并通过将超时设置为 0 来禁用即时验证。https://firebase.google.com/docs/reference/android/com/google/firebase/auth/PhoneAuthOptions.Builder#setTimeout(java.lang.Long,%20java.util.concurrent.TimeUnit))
希望这可以为这个奇怪的问题提供一些清晰的信息。
【讨论】:
在将超时时间设置为 0 后对我有用【参考方案2】:要自动验证电话号码,您必须同时实现验证流程的客户端和服务器部分。您刚刚实现了客户端部分。要收听 SMS 并自动输入 OTP 代码,您还必须实现服务器端。在这里可以找到完整的指南Perform SMS Verification on a Server
【讨论】:
@Muhammedshamshadp 很抱歉。我已经编辑了我的答案并添加了正确的链接。以上是关于使用 SmsRetriever 时接收广播 Intent 时出错的主要内容,如果未能解决你的问题,请参考以下文章