Search code examples
androidandroid-studiosms-verification

Cannot send sms verification code using with the SMS User Consent API on android


I am trying to make a phone number verification on android studio using java. I followed the instructions from the documentation here https://developers.google.com/identity/sms-retriever/user-consent/overview but sadly it isn't sending me an SMS code, and I am not getting any error. Below is my code:

public class OTPSMSActivity extends AppCompatActivity {
    private ImageView blur;
    private TextView resend;
    private CustomEditText editText;
    private FirebaseFirestore db = FirebaseFirestore.getInstance();
    private KProgressHUD loadingBar;
    private static final int SMS_CONSENT_REQUEST = 2;

    // Set to an unused request code
    private final BroadcastReceiver smsVerificationReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (SmsRetriever.SMS_RETRIEVED_ACTION.equals(intent.getAction())) {
                Bundle extras = intent.getExtras();
                Status smsRetrieverStatus = (Status) extras.get(SmsRetriever.EXTRA_STATUS);

                switch (smsRetrieverStatus.getStatusCode()) {
                    case CommonStatusCodes.SUCCESS:
                        // Get consent intent
                        Intent consentIntent = extras.getParcelable(SmsRetriever.EXTRA_CONSENT_INTENT);
                        try {
                            /*Start activity to show consent dialog to user within
                             *5 minutes, otherwise you'll receive another TIMEOUT intent
                             */
                            startActivityForResult(consentIntent, SMS_CONSENT_REQUEST);
                            Log.d("life", "Intent to send image");
                        } catch (ActivityNotFoundException e) {
                            Log.e("life", "Exception: " + e.toString());
                        }
                        break;
                    case CommonStatusCodes.TIMEOUT:
                        Log.d("life", "Timeout!");
                        break;
                }
            } else {
                Log.d("life", "SmsRetriever don't matched");
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_otpsms);

        blur = findViewById(R.id.blur);
        editText = findViewById(R.id.number);
        Button verify = findViewById(R.id.verify);
        TextView change = findViewById(R.id.textView42);
        resend = findViewById(R.id.resend);

        Paper.init(this);

        getBackgroundImage();

        change.setOnClickListener(view -> {
            finish();
        });


        String phoneNumber = getIntent().getStringExtra("phone");

        loadingBar = KProgressHUD.create(OTPSMSActivity.this)
                .setStyle(KProgressHUD.Style.SPIN_INDETERMINATE)
                .setLabel("Please wait")
                .setDetailsLabel("Sending sms code to your phone number.")
                .setCancellable(true)
                .setAnimationSpeed(2)
                .setDimAmount(0.5f)
                .show();

        verify.setOnClickListener(view -> {
            loadingBar = KProgressHUD.create(OTPSMSActivity.this)
                    .setStyle(KProgressHUD.Style.SPIN_INDETERMINATE)
                    .setLabel("Loading")
                    .setDetailsLabel("Verifying code")
                    .setCancellable(true)
                    .setAnimationSpeed(2)
                    .setDimAmount(0.5f)
                    .show();
            String theCode = editText.getText().toString();
            if (theCode.length() != 6){
                new StyleableToast
                        .Builder(OTPSMSActivity.this)
                        .text("Invalid code.")
                        .iconStart(R.drawable.error)
                        .textColor(Color.WHITE)
                        .backgroundColor(getResources().getColor(R.color.error))
                        .show();
                editText.setError("Invalid phone number.");
                editText.requestFocus();
                loadingBar.dismiss();
                return;
            }
            verifyCode(theCode);
        });

        resend.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

            }
        });

        String phone = "+63" + phoneNumber.substring(1);
        Log.d("life", phone);
        Task<Void> task = SmsRetriever.getClient(this).startSmsUserConsent(phone);

        task.addOnCompleteListener(listener -> {
            if (listener.isSuccessful()) {
                Log.d("life", "Success");
                loadingBar.dismiss();

                IntentFilter intentFilter = new IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION);
                registerReceiver(smsVerificationReceiver, intentFilter);
            } else {
                Exception exception = listener.getException();
                exception.printStackTrace();
            }
        });
    }

    private void verifyCode(String code) {
        if (code.equals(editText.getText().toString())) {
            String phoneNumber = getIntent().getStringExtra("phone");
            String userID = Paper.book().read("userID");

            loadingBar.setDetailsLabel("Uploading number to database");
            db.collection("Buyers").document(userID)
                    .update("phone", "+63" + phoneNumber.substring(1))
                    .addOnCompleteListener(task11 -> {
                        if (task11.isSuccessful()){
                            loadingBar.dismiss();
                            StyleableToast.makeText(OTPSMSActivity.this, "Success! Phone number updated.", Toast.LENGTH_LONG, R.style.successtoast).show();
                            finish();
                        }
                    });
        } else {
            new StyleableToast
                    .Builder(OTPSMSActivity.this)
                    .text("Code does not matched.")
                    .iconStart(R.drawable.error)
                    .textColor(Color.WHITE)
                    .backgroundColor(getResources().getColor(R.color.error))
                    .show();
            loadingBar.dismiss();
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == SMS_CONSENT_REQUEST) {
            if (resultCode == RESULT_OK) {
                // Get SMS message content
                String message = data.getStringExtra(SmsRetriever.EXTRA_SMS_MESSAGE);
                // Extract one-time code from the message and complete verification
                String oneTimeCode = parseOneTimeCode(message);
                Log.d("life", "oneTimeCode: " + oneTimeCode);
                //for this demo we will display it instead
                editText.setText(oneTimeCode);
            } else {
                Log.d("life", "Error2");
            }
        } else {
            Log.d("life", "Error1");
        }
    }


    private String parseOneTimeCode(String message) {
        //simple number extractor
        return message.replaceAll("[^0-9]", "");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //to prevent IntentReceiver leakage unregister
        unregisterReceiver(smsVerificationReceiver);
    }

I want to know what am I doing wrong here.


Solution

  • Calling this API won't be sending you an SMS. This API listens to the SMS that you will receive on your device, ask for your permission and then retrieve it.

    You should not wait for the task to complete. It is there to listen to the SMS you receive. So the first thing that you need to correct in your onCreate function:

     @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_otpsms);
            ...
            
            Task<Void> task = SmsRetriever.getClient(this).startSmsUserConsent(null);
    
            IntentFilter intentFilter = new IntentFilter(SmsRetriever.SMS_RETRIEVED_ACTION);
            registerReceiver(smsVerificationReceiver, intentFilter);
    
            ...
       }
    

    The phone number you are passing to SmsRetriever.getClient(this).startSmsUserConsent is the phone number of the sender. So if you know which number will send you an SMS, then pass it to this function. But if you don't know the number of the sender, keep it null.

    And note that the sender phone number should not be in the phone's contacts list as mentioned in the documentation: https://developers.google.com/identity/sms-retriever/choose-an-api

    documentation of google user Consent API

    So first call create this task instruction above, have it wait for your sms and then request an SMS. You could use third party platforms to send SMS messages. To test that you can send an SMS using your emulator to the emulator device.

    sending sms to android emulator