Why SMS Retriever API don't work in release mode?

11,040

Solution 1

First download your app signing certificate .der file then convert to .jks file by this command

keytool -import -alias your_alias -keystore file_name_created -file certificate.der

then new .jks file created

then use this command for generate hash for your release

keytool -exportcert -alias your_alias -keystore certificate.jks | xxd -p | tr -d "[:space:]" | echo -n  app_package_name `cat` | sha256sum | tr -d "[:space:]-" | xxd -r -p | base64 | cut -c1-11

then create hash string and it will work on play store app.

Solution 2

Follow these steps to get the key for production:

  1. Go to the Build option.
  2. In the options, choose Select Build Variant.
  3. Then in the left corner, a dialog will open, from there Change Build Variant from debug to release.
  4. Click on run, then this dialog will open: Then this dialog will open(point 4 pic.)
  5. Click on Run, next click on Continue Anyway, then click on Yes then in the dialog In this dialog Click on the **+** in left bottom.
  6. Then fill these details: Then fill these details
  7. Now go to Build Types and follow this image: Then go to build types and follow the image
  8. And click ok.

Now when you run the commands to get the hash through AppSignatureHelper Class, that key will be your production key.

Solution 3

Few days ago, I had the same problem. Actually there is nothing wrong in your code. When you run your app and create hash, it create hash only for device specific. When your generate signed apk and create hash ( using log ), then this hash is only for release but not for production. In case of production, you have to install app from play store and check hash ( using logs ) and that hash will use for all users.

Hope it will help you

You can use this link to create hashkey:

https://github.com/arsalankhan994/AppSignatureHelper/tree/main

Solution 4

You must add release app string hash to message sent from server because release hash different from debug hash SMS retriever verify

Solution 5

  1. First download app signed certificate der from your play console account.
  2. Then convert it to yourkeystore.keystore with keystore extension using this command:

    keytool -import -alias your_alias -keystore file_name_created.keystore -file certificate.der

  3. Then create string hash using the created keystore.
    Use this file bash to create hash string:
    https://github.com/googlesamples/android-credentials/tree/master/sms-verification/bin

Share:
11,040
S.P.
Author by

S.P.

Updated on June 05, 2022

Comments

  • S.P.
    S.P. almost 2 years

    I've implemented the SMS Retriever API like in the google tutorials and in my debug Build Variant work fine. I can read the sms and get the code to the user can do the login.

    My problem is when I run the app in release Build Variant the sms it doesn't work. I receive the sms but I can't read the code to do the login.

    I change the hash generated with AppSignatureHelper in release mode that is differente than in the debug mode. In debug work and in release no.

    Some help will be appreciate

    The code:

    Manifest:

       <receiver android:name=".app.receivers.SmsReceiver">
            <intent-filter>
                <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED"/>
            </intent-filter>
        </receiver>
    

    In my class: (In release and in debug mode the code go throw the onSucess method) This method is called in onCreate.

    private void startSMSListening(){
        SmsRetrieverClient client = SmsRetriever.getClient(this);
        Task<Void> task = client.startSmsRetriever();
    
        task.addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                // Successfully started retriever, expect broadcast intent
                Log.e("startSMSListening", "listening sms");
                sendCode();
                showHideLoadingView(false);
            }
        });
    
        task.addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                // Failed to start retriever, inspect Exception for more details
                Log.e("startSMSListening", "failure listening sms");
                showHideLoadingView(false);
            }
        });
    }
    

    My receiver:

    public class SmsReceiver extends BroadcastReceiver {
        //interface
        private static SmsListener mListener;
    
        @Override
        public void onReceive(Context context, Intent intent) {
            if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {
                Bundle extras = intent.getExtras();
                if(extras != null) {
                    Status status = (Status) extras.get(SmsRetriever.EXTRA_STATUS);
    
                    if(status != null) {
                        switch (status.getStatusCode()) {
                            case CommonStatusCodes.SUCCESS:
                                // Get SMS message contents
                                String message = (String) extras.get(SmsRetriever.EXTRA_SMS_MESSAGE);
                                //Pass the message text to interface
                                if (mListener != null && !StringUtil.isNull(message)) {
                                    mListener.messageReceived(message);
                                }
                                break;
                            case CommonStatusCodes.TIMEOUT:
                                Log.d("SMSReceiver", "timed out (5 minutes)");
                                break;
                        }
                    }
                }
            }
        }
    
        public static void bindListener(SmsListener listener) {
            mListener = listener;
        }
    }
    

    My smsReceiver method:

    private void smsReceiver(){
            SmsReceiver.bindListener(new SmsListener() {
                @Override
                public void messageReceived(String messageText) {
                    //From the received text string you may do string operations to get the required OTP
                    //It depends on your SMS format
                    Log.e("Message",messageText);
    
                    // If your OTP is six digits number, you may use the below code
                    Pattern pattern = Pattern.compile(OTP_REGEX);
                    Matcher matcher = pattern.matcher(messageText);
                    String otp = null;
    
                    while (matcher.find()) {
                        otp = matcher.group();
                    }
    
                    if(otp != null && et_code != null) {
                        et_code.setText(otp);
                    }
                }
            });
        }