Android Studio中Firebase短信OTP无法发送问题求助
Firebase手机号认证无法发送短信OTP问题排查与修复
在Android Studio中集成Firebase手机号认证功能时,遇到短信OTP无法发送到手机的问题,以下是Login.class和OTP_verification.class的代码,需排查修复以完成认证功能。
Login.class代码
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks; private String mVerificationId; private PhoneAuthProvider.ForceResendingToken mResendToken; private boolean otpSent = false; // 补充初始化 private static final String TAG = "LoginActivity"; // 补充TAG定义 private String countryCode = "+63"; // 补充国家码定义,根据实际情况调整 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_login); signup_btn = findViewById(R.id.btn_signup); signup_btn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { Intent intent = new Intent(getApplicationContext(), Sign_Up.class); startActivity(intent); finish(); } }); back_btn = findViewById(R.id.backbutton); back_btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(getApplicationContext(), MainActivity.class); startActivity(intent); finish(); } }); final EditText editphone = findViewById(R.id.editContact); final ProgressBar progressBar = findViewById(R.id.progressbar); FirebaseApp.initializeApp(this); FirebaseAuth mAuth = FirebaseAuth.getInstance(); final Button lgn_btn = findViewById(R.id.lgn_btn); lgn_btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (editphone.getText().toString().trim().isEmpty()) { Toast.makeText(Login.this, "Enter Mobile Number", Toast.LENGTH_SHORT).show(); return; } else { if (editphone.getText().toString().trim().length() < 10) { Toast.makeText(Login.this, "Enter Valid Mobile Number", Toast.LENGTH_SHORT).show(); } else { progressBar.setVisibility(View.VISIBLE); lgn_btn.setVisibility(View.INVISIBLE); if (otpSent) { Toast.makeText(Login.this, "TEST OTP Sent Successfully", Toast.LENGTH_SHORT).show(); if (mVerificationId.isEmpty()) { Toast.makeText(Login.this, "TEST OTP Unverified", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(Login.this, "TEST", Toast.LENGTH_SHORT).show(); } } else { final String getMobile = editphone.getText().toString(); PhoneAuthOptions options = PhoneAuthOptions.newBuilder(mAuth) .setPhoneNumber(countryCode + "" + editphone.getText().toString()) // Phone number to verify .setTimeout(60L, TimeUnit.SECONDS) // Timeout duration .setActivity(Login.this) // Activity (for callback binding) .setCallbacks(new PhoneAuthProvider.OnVerificationStateChangedCallbacks() { @Override public void onVerificationCompleted(@NonNull PhoneAuthCredential phoneAuthCredential) { progressBar.setVisibility(View.GONE); lgn_btn.setVisibility(View.VISIBLE); Log.d(TAG, "onVerificationCompleted:" + phoneAuthCredential); } @Override public void onVerificationFailed(@NonNull FirebaseException e) { progressBar.setVisibility(View.GONE); lgn_btn.setVisibility(View.VISIBLE); Log.w(TAG, "onVerificationFailed", e); if (e instanceof FirebaseAuthInvalidCredentialsException) { Toast.makeText(Login.this, "无效的请求格式", Toast.LENGTH_SHORT).show(); } else if (e instanceof FirebaseTooManyRequestsException) { Toast.makeText(Login.this, "项目短信配额已耗尽", Toast.LENGTH_SHORT).show(); } else if (e instanceof FirebaseAuthMissingActivityForRecaptchaException) { Toast.makeText(Login.this, "reCAPTCHA验证缺少Activity绑定", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(Login.this, "验证失败:" + e.getMessage(), Toast.LENGTH_SHORT).show(); } } @Override public void onCodeSent(@NonNull String verificationId, @NonNull PhoneAuthProvider.ForceResendingToken forceResendingToken) { super.onCodeSent(verificationId, forceResendingToken); progressBar.setVisibility(View.GONE); lgn_btn.setVisibility(View.VISIBLE); mVerificationId = verificationId; otpSent = true; // 传递verificationId到OTP页面 Intent intent = new Intent(getApplicationContext(), OTP_verification.class); intent.putExtra("mobile", editphone.getText().toString()); intent.putExtra("verificationId", mVerificationId); // 补充传递验证ID startActivity(intent); finish(); } }).build(); PhoneAuthProvider.verifyPhoneNumber(options); } } } } }); }
OTP_verification.class代码
private EditText inpudecode1, inpudecode2,inpudecode3,inpudecode4,inpudecode5,inpudecode6; private FirebaseAuth mAuth = FirebaseAuth.getInstance(); private static final String TAG = "OTPVerification"; // 补充TAG定义 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_otp_verification); TextView mobileText = findViewById(R.id.mobileText); mobileText.setText(String.format( "+63%s", getIntent().getStringExtra("mobile") )); inpudecode1 = findViewById(R.id.code1); inpudecode2 = findViewById(R.id.code2); inpudecode3 = findViewById(R.id.code3); inpudecode4 = findViewById(R.id.code4); inpudecode5 = findViewById(R.id.code5); inpudecode6 = findViewById(R.id.code6); setupOTPinputs(); } private void setupOTPinputs(){ inpudecode1.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if(!s.toString().trim().isEmpty()){ inpudecode2.requestFocus(); } } @Override public void afterTextChanged(Editable s) {} }); inpudecode2.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if(!s.toString().trim().isEmpty()){ inpudecode3.requestFocus(); } } @Override public void afterTextChanged(Editable s) {} }); inpudecode3.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if(!s.toString().trim().isEmpty()){ inpudecode4.requestFocus(); } } @Override public void afterTextChanged(Editable s) {} }); inpudecode4.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if(!s.toString().trim().isEmpty()){ inpudecode5.requestFocus(); } } @Override public void afterTextChanged(Editable s) {} }); inpudecode5.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if(!s.toString().trim().isEmpty()){ inpudecode6.requestFocus(); } } @Override public void afterTextChanged(Editable s) {} }); inpudecode6.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { if (!s.toString().trim().isEmpty()) { String otp = inpudecode1.getText().toString() + inpudecode2.getText().toString() + inpudecode3.getText().toString() + inpudecode4.getText().toString() + inpudecode5.getText().toString() + inpudecode6.getText().toString(); verifyOTP(otp); } } @Override public void afterTextChanged(Editable s) {} }); } private void verifyOTP(String otp) { String mVerificationId = getIntent().getStringExtra("verificationId"); // 增加空判断 if (mVerificationId == null || mVerificationId.isEmpty()) { Toast.makeText(OTP_verification.this, "验证ID无效,请重新获取OTP", Toast.LENGTH_SHORT).show(); return; } PhoneAuthCredential credential = PhoneAuthProvider.getCredential(mVerificationId, otp); signInWithCredential(credential); } private void signInWithCredential(PhoneAuthCredential credential) { mAuth.signInWithCredential(credential) .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isSuccessful()) { Toast.makeText(OTP_verification.this, "验证成功", Toast.LENGTH_SHORT).show(); FirebaseUser user = task.getResult().getUser(); // 这里可以跳转到首页或其他页面 Intent intent = new Intent(getApplicationContext(), MainActivity.class); startActivity(intent); finish(); } else { Toast.makeText(OTP_verification.this, "验证失败", Toast.LENGTH_SHORT).show(); if (task.getException() instanceof FirebaseAuthInvalidCredentialsException) { Toast.makeText(OTP_verification.this, "输入的OTP无效", Toast.LENGTH_SHORT).show(); } Log.w(TAG, "signInWithCredential failed", task.getException()); } } }); }
关键排查与修复点
1. Firebase控制台配置检查
- 确认手机号认证已启用:Firebase控制台 -> Authentication -> 登录方法 -> 手机号,确保状态为启用
- 检查短信配额:Firebase控制台 -> 使用情况 -> 配额,查看SMS发送额度是否耗尽
- 确认应用指纹:项目设置 -> 应用 -> 添加SHA-1和SHA-256指纹,确保与本地签名配置一致
2. 代码核心修复
- Login.class:
- 补充
countryCode、otpSent、TAG的定义与初始化 - 在跳转OTP页面时传递
mVerificationId,否则OTP验证时会因缺少验证ID失败 - 在
onVerificationFailed中增加具体错误提示,方便排查问题
- 补充
- OTP_verification.class:
- 在
verifyOTP方法中增加mVerificationId的空判断,避免空指针异常 - 补充
TAG定义,增加失败日志输出,便于定位问题
- 在
3. 设备与权限检查
- 确保测试设备能正常接收短信,排除运营商或短信拦截软件的影响
- 在
AndroidManifest.xml中添加短信权限:<uses-permission android:name="android.permission.SEND_SMS"/> <uses-permission android:name="android.permission.RECEIVE_SMS"/> <uses-permission android:name="android.permission.READ_SMS"/> - 针对Android 6.0+设备,动态申请短信权限
内容的提问来源于stack exchange,提问作者Biancent Pacatang
相关产品推荐
相关产品推荐

