0

I am trying to detect one-time password through SMS Retrieve API, followed all steps correctly as per docs, but my broadcast receiver not detecting OTP.

My SMSBroadcastReceiver

class SMSBroadcastReceiver : BroadcastReceiver() {
    private var otpReceiver: OTPReceiveListener? = null

    fun initOTPListener(receiver: OTPReceiveListener) {
        this.otpReceiver = receiver
    }

    override fun onReceive(context: Context, intent: Intent) {
        println("SMSBroadcastReceiver#onReceive()")
        intent.extras?.let {
            for (key in it.keySet()) {
                println("$key => ${it.get(key)}")
            }
        }

        if (SmsRetriever.SMS_RETRIEVED_ACTION == intent.action) {
            val extras = intent.extras
            val status = extras?.get(SmsRetriever.EXTRA_STATUS) as Status

            when (status.statusCode) {
                CommonStatusCodes.SUCCESS -> {
                    // Get SMS message contents
                    var otp: String = extras.get(SmsRetriever.EXTRA_SMS_MESSAGE) as String
                    Log.d("OTP_Message", otp)
                    // Extract one-time code from the message and complete verification
                    // by sending the code back to your server for SMS authenticity.
                    // But here we are just passing it to MainActivity
                    val pattern = Pattern.compile("(\\d{6})")
                    val matcher = pattern.matcher(otp)

                    // Extract one-time code from the message and complete verification
                    if (matcher.find()) {
                        println("matcher OTP::" + matcher.group(0))
                        val digit = matcher.group(0) ?: matcher.group(1) ?: ""
                        otpReceiver?.onOTPReceived(digit)
                    }
                   
                }

                CommonStatusCodes.TIMEOUT ->
                    // Waiting for SMS timed out (5 minutes)
                    // Handle the error ...
                    if (otpReceiver != null)
                        otpReceiver!!.onOTPTimeOut()
            }
        }
    }

    fun register(activity: AppCompatActivity) {
        val intentFilter = IntentFilter()
        intentFilter.addAction(SmsRetriever.SMS_RETRIEVED_ACTION)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            activity.registerReceiver(
                this,
                intentFilter,
                SmsRetriever.SEND_PERMISSION,
                null,
                Context.RECEIVER_VISIBLE_TO_INSTANT_APPS
            )
        } else {
            activity.registerReceiver(this, intentFilter)
        }
    }

    fun unregister(activity: AppCompatActivity) {
        activity.unregisterReceiver(this)
    }
}

LoginActivity where i register broadcast receiver and SmsRetrieve client.

class LoginActivity : BaseActivity<ActivityLoginBinding>(R.layout.activity_login),
    OTPReceiveListener {
    private val loginOtpViewModel by viewModels<LoginOtpViewModel>()

    private var smsReceiver: SMSBroadcastReceiver? = SMSBroadcastReceiver()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        startSMSRetrieveService()
    }
    
    fun startSMSRetrieveService() {
        Timber.d("startSMSRetrieveService")
        try {
            val client = SmsRetriever.getClient(this)
            val task = client.startSmsRetriever()
            task.addOnSuccessListener {
                registerBroadcast()
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    override fun onOTPReceived(otp: String) {
        loginOtpViewModel.updateAutofillOtp(otp)
        smsReceiver?.unregister(this)
    }

    override fun onOTPTimeOut() {
        Timber.d("OTP receive timeout")
    }

    private fun registerBroadcast() {
        smsReceiver?.initOTPListener(this)
        smsReceiver?.register(this)
    }

}

OTP Message

<#> Hello! Your one-time code is 650626 and is valid for 5 minutes.
11-degit hash key

When I trying with local sending message through SmsManager it working fine.

fun send(number: String, context: Context, message: String = MSG) {
        val smsManager: SmsManager = getSmsManager(context)
        smsManager.sendTextMessage(number, null, message, null, null)
    }

    private fun getSmsManager(context: Context) =
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            context.getSystemService(SmsManager::class.java)
        } else {
            SmsManager.getDefault()
        }

With locally it working very well, same message format received from server, but not detecting.

Can anyone help me to find out, how i can solve this?

Android Leo
  • 666
  • 1
  • 8
  • 24

0 Answers0