Java – Firebase authentication using SMS authentication does not work

Firebase authentication using SMS authentication does not work… here is a solution to the problem.

Firebase authentication using SMS authentication does not work

I use Firebase authentication with a phone number in my android app.

Authentication works fine when you enter the number for the first time, and it can automatically detect the OTP if the app is opened on the same Android device that provided the provided phone number.

But when I enter the mobile number again, it does not send a verification SMS containing the OTP.

This is the class that provides the phone number.

public class LoginActivity extends AppCompatActivity {

private EditText LoginPhone;
    private Button LoginConfirmButton;

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

LoginPhone = (EditText) findViewById(R.id.PhoneNumberLogin);
        LoginConfirmButton = (Button) findViewById(R.id.Loginbutton);
        Button registerbutton=(Button)findViewById(R.id.RegisterButton);

LoginConfirmButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String number=LoginPhone.getText().toString();
                if(number.isEmpty() || number.length()<11)
                {
                    LoginPhone.setError("Valied Number Required");
                    LoginPhone.requestFocus();
                }

String PhoneNumber="+88"+number;
                Intent firstintent=new Intent(LoginActivity.this,CodeConfirm.class);
                firstintent.putExtra("PhoneNumber",PhoneNumber);
                startActivity(firstintent);
            }
        });

registerbutton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(LoginActivity.this,User_Registration.class));
            }
        });
    }
}

This is the class where the user can manually place OTPs.

public class CodeConfirm extends AppCompatActivity {

EditText Otpverify;
    int s;
    private String VerificationCode;
    Button confirmbutton;
    private FirebaseAuth mAuth;

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

Otpverify = (EditText) findViewById(R.id.ConfirmCode);
        mAuth= FirebaseAuth.getInstance();
        String PhoneNumber = getIntent().getStringExtra("PhoneNumber");

SendVerificationCode(PhoneNumber);

confirmbutton=(Button)findViewById(R.id.ConfirmButton);

confirmbutton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String code=Otpverify.getText().toString().trim();

if(code.isEmpty() || code.length()<6)
                {
                    Otpverify.setError("Enter the OTP properly");
                    Otpverify.requestFocus();
                    return;
                }
                Verifycode(code);
            }
        });
    }

private void Verifycode(String code) {
        PhoneAuthCredential credential=PhoneAuthProvider.getCredential(VerificationCode,code);
        Signin(credential);

}

private void Signin(PhoneAuthCredential credential) {

mAuth.signInWithCredential(credential).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
            @Override
            public void onComplete(@NonNull Task<AuthResult> task) {

if(task.isSuccessful())
                {
                    Intent WorkingSwitch=new Intent(CodeConfirm.this,Current_Location.class);
                    WorkingSwitch.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    startActivity(WorkingSwitch);
                }
            }
        });
    }

private void SendVerificationCode(String Number) {

PhoneAuthProvider.getInstance().verifyPhoneNumber(
                Number,
                60,
                TimeUnit.SECONDS,
                TaskExecutors.MAIN_THREAD,
                mCallBack
        );
    }

private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallBack = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {

@Override
        public void onVerificationCompleted(PhoneAuthCredential phoneAuthCredential) {

String code=phoneAuthCredential.getSmsCode();
            if(code!=null)
            {
                Verifycode(code);
            }
        }

@Override
        public void onVerificationFailed(FirebaseException e) {

Toast.makeText(CodeConfirm.this,e.getMessage(),Toast.LENGTH_LONG).show();

}

@Override
        public void onCodeSent(String s, PhoneAuthProvider.ForceResendingToken forceResendingToken) {
            super.onCodeSent(s, forceResendingToken);
            VerificationCode=s;
        }
    };
}

I

want to send OTP to the phone number every time I provide a number, even if I provide the same number multiple times.

Solution

The verifyPhoneNumber method does not send OTP if the number has recently been verified, if validation of the number is already in progress, or if too many validation requests have recently been sent to the number.

Also note that documentation :

To prevent abuse, Firebase enforces a limit on the number of SMS messages that can be sent to a single phone number within a period of time. If you exceed this limit, phone number verification requests might be throttled. If you encounter this issue during development, use a different phone number for testing, or try the request again later.

If you want to force it to send a new OTP, use verifyPhoneNumber overload that takes a forceResendingToken parameter you got from the previous onCodeSent.

If you want to send a test with the same number, whitelisting the Number is a better choice.

Related Problems and Solutions