You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 14:05:57