Google SMS Retriever API not retreiving SMS messages
Asked Answered
L

9

12

I'm trying to use Google's SMS Retriever API for Automatic SMS Verification. I have followed the directions here but my app is not receiving any SMS messages. Here is what I've done:

I've added the code in my activity to start the SMS retriever client:

    val client = SmsRetriever.getClient(this)
    val retriever = client.startSmsRetriever()
    retriever.addOnSuccessListener {
        Log.i("loginActivity", "started smsretriever")
    }

    retriever.addOnFailureListener {
        //Problem to start listener
    }

From the logs, I see this starts successfully. Then I add my broadcast receiver with this onReceive:

override fun onReceive(context: Context, intent: Intent) {
    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 -> {

            }
            CommonStatusCodes.TIMEOUT -> {

            }
    }
}

This only triggers when a TIMEOUT event is sent 5 minutes after the SMS retriever client starts. It never triggers for SMS messages.

Finally, I've registered the receiver in the Manifest:

<receiver android:name=".receiver.SMSReceiver" android:exported="true">
        <intent-filter>
            <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
        </intent-filter>
    </receiver>

In terms of the text message, I am sending myself this SMS message: "<#> Your code is: 123456 verification hash: "

Any idea what I'm doing wrong?

Landrum answered 24/12, 2018 at 0:51 Comment(6)
Have you set up your server properly ? Check github.com/googlesamples/android-credentials/tree/master/… this for full exampleBingo
I don't have a server setup. I am manually sending the message to my device from a different device. I didn't read anything that said having a server was necessary for testing. I didn't read anything that said it mattered where the text originates from.Landrum
I followed all the steps in the link you gave. I added the google-services.json file, added my app to firebase, and made sure my hash code was right. Still no luckLandrum
You definitely need a server .If you don't have one try setting up with firebase. Try this firebase.google.com/docs/auth/android/phone-auth . This is the 2nd point from the link you shared "Your app makes a request to your server to verify the user's phone number".Bingo
@Landrum Have you solved this problem?Subsonic
Check this working example: #53487581Evite
G
10

Maybe your message has wrong construction, please check this link: SMS Retriever API. At the first point, your text message must be begin with <#> or [#]. And at the 4th point, Your text message must be-"End with an 11-character hash string that identifies your app"

I have the same issue and that points is my awareness, solve by adding <#> in begining and hash string at the end.

Gamboa answered 6/3, 2019 at 7:4 Comment(0)
I
7

Register the BroadcastReceiver inside SmsRetrievers addOnSuccessListener callback method, don't register in Manifest file.

val client = SmsRetriever.getClient(this)
        val retriever = client.startSmsRetriever()
        retriever.addOnSuccessListener {
            val listener = object : SMSBroadcastReceiver.Listener {
                override fun onSMSReceived(otp: String) {
                    Log.d("AppSignatureHelper",otp)
                    Toast.makeText(context, otp, Toast.LENGTH_SHORT).show()
                }

                override fun onTimeOut() {
                    Log.d("AppSignatureHelper","Timed Out.")
                }
            }
            smsBroadcastReceiver.injectListener(listener)
            registerReceiver(smsBroadcastReceiver, IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION))
        }
        retriever.addOnFailureListener {
            Log.d("AppSignatureHelper","Problem to start listener")
            //Problem to start listener
        }

Listener Interface is.

 interface Listener {
        fun onSMSReceived(otp: String)
        fun onTimeOut()
    }
Iconostasis answered 27/3, 2019 at 10:18 Comment(0)
S
5

I faced the same problem recently.

I figured out the problem was that I was using the production Keystore hash for testing in debug mode.

If you're running in debug mode, make sure to use the default keystore used to sign the debug apk.

The default debug keystore location is $HOME/.android/debug.keystore

As per the app-sign documentation:

When running or debugging your project from the IDE, Android Studio automatically signs your app with a debug certificate generated by the Android SDK tools. The first time you run or debug your project in Android Studio, the IDE automatically creates the debug keystore and certificate in $HOME/.android/debug.keystore, and sets the keystore and key passwords.

I recently wrote a blog post about this, check it out for more details.

Soften answered 13/2, 2019 at 23:17 Comment(0)
A
3

Two problems I faced when I was trying to get this to work:

1) The SMS message needs to be well-formatted. You might think 'ok, I got it' but in my case I had more than one line break between the first line of the SMS and the signature hash key. Make sure you strictly follow this pattern:

<#> Your xy verification code is 123456
FA+9qCX9VSu

2) Make sure you're using the right hash key. Android will not call the onReceive method unless your signature hash in the SMS message matches the one from the running app. Why I say this? You will have different hashes on your local debug version and the version deployed in the store. One point to mention here is that google can take over the signing part for you once you upload the apk to google console.

Hope this helps... my two days are wasted now.

Agatha answered 17/12, 2019 at 9:31 Comment(1)
in my case sms retrieval api is not working on few devices likes Vivo 17 ProHollands
C
2

Now "<#>" at the beginning of the SMS is not required!

Counsel answered 2/12, 2021 at 9:43 Comment(1)
This does not provide an answer to the question. Once you have sufficient reputation you will be able to comment on any post; instead, provide answers that don't require clarification from the asker. - From ReviewLeesen
S
0

If you don't want to include the special symbol (<#>) or the app signature hash when sending an SMS, you can use the SmsRetriever#startSmsUserConsent(String) and the BroadcastReceiver that listens for the SMS_RETRIEVED_ACTION. Using this approach, the user will be prompted to either Allow or Deny the sms read.

Create your BroadcastReceiver:

class SmsBroadcastReceiver : BroadcastReceiver() {

    var onReceive: ((Intent) -> Unit)? = null

    override fun onReceive(context: Context, intent: Intent) {
        if (intent.action != SmsRetriever.SMS_RETRIEVED_ACTION) return
        val extras = intent.extras ?: return
        val status: Status? = extras.parcelable(SmsRetriever.EXTRA_STATUS)

        if (status?.statusCode != CommonStatusCodes.SUCCESS) return

        extras.parcelable<Intent>(SmsRetriever.EXTRA_CONSENT_INTENT)?.let {
            onReceive?.invoke(it)
        }
    }
}

Then register it in onResume:

private val smsReceiver = SmsBroadcastReceiver()

private fun registerSmsReceiver() {
    ContextCompat.registerReceiver(
        requireActivity(),
        smsReceiver,
        IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION),
        SmsRetriever.SEND_PERMISSION,
        /* scheduler = */null,
        ContextCompat.RECEIVER_EXPORTED
    )
}

Unregister in onPause: requireActivity().unregisterReceiver(smsReceiver)

Start the SmsRetriever: SmsRetriever.getClient(requireContext()).startSmsUserConsent(null)

SmsRetriever will listen for the SMS for the next 5 minutes after the startSmsUserConsent call. If no SMS will be received, you will get the TIMEOUT status in EXTRA_STATUS.

When the onReceive is called and you receive your intent, launch it using the Activity Result API:

private val smsUserConsentLauncher =
    registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
        try {
            result.data?.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE)?.let { sms ->
                // Your app have successfully read the sms
            }
        } catch(e: Exception) {
            // Handle exception
        }
    }

// ...

smsUserConsentLauncher.launch(/* Intent received from the broadcast receiver */)

Stairhead answered 31/8, 2023 at 11:39 Comment(0)
L
0

For me, it was due to google messages sending a RCS Chat message instead of regular SMS, as I was sending SMS myself from google messages. Disabling RCS Chats helped.

Largeminded answered 23/8, 2024 at 12:52 Comment(0)
C
-1

What have you done as far now is perfect, just small thing add the below in your activity also, it worked for me...........

IntentFilter intentFilter = new IntentFilter();

intentFilter.addAction(SmsRetriever.SMS_RETRIEVED_ACTION);

getApplicationContext().registerReceiver(smsBroadcast, intentFilter);

Cardio answered 24/12, 2018 at 9:54 Comment(1)
Then, there is a possibility for issue in configuration, use onConnected method in GoogleApiClient.ConnectionCallbacks. And also ensure that you have generated proper hash message. Ex : <#> Your code is: 123ABC78 FA+9qCX9VSuCardio
N
-1

I did the same way and it was perfectly working for me. Most likely that your application hash is wrong.

Neuromuscular answered 22/1, 2019 at 8:48 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.