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?