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

Kotlin Firebase骑手端手机号验证后应用崩溃问题求助

骑手端Firebase手机号验证后崩溃及验证提示问题排查与修复

问题描述

我正在开发基于Kotlin与Firebase的骑手端应用,期望完成手机号验证后跳转至HomeActivity,但应用出现崩溃,无法定位原因。已在Firebase中关联司机端与骑手端两个应用,司机端运行正常,骑手端却提示“手机号需要验证”,且已在Firebase中手动添加相关手机号。

修复后完整代码

package com.example.driveeaserider

import android.app.Activity
import android.app.AlertDialog
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.TextUtils
import android.view.LayoutInflater
import android.view.View
import android.widget.Button
import android.widget.ProgressBar
import android.widget.Toast
import com.example.driveeaserider.Common.Common
import com.example.driveeaserider.Model.RiderModel
import com.firebase.ui.auth.AuthMethodPickerLayout
import com.firebase.ui.auth.AuthUI
import com.firebase.ui.auth.IdpResponse
import com.google.android.material.textfield.TextInputEditText
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.FirebaseDatabase
import com.google.firebase.database.ValueEventListener
import io.reactivex.Completable
import io.reactivex.android.schedulers.AndroidSchedulers
import java.util.Arrays
import java.util.concurrent.TimeUnit

class SplashScreenActivity : AppCompatActivity() {

    companion object {
        private val LOGIN_REQUEST_CODE = 7171
    }

    lateinit var provider: List<AuthUI.IdpConfig>
    lateinit var firebaseAuth: FirebaseAuth
    lateinit var listener: FirebaseAuth.AuthStateListener

    private lateinit var database: FirebaseDatabase
    private lateinit var riderInfoRef: DatabaseReference
    private lateinit var progressBar: ProgressBar

    override fun onStart() {
        super.onStart()
        delaySplashScreen()
    }

    private fun delaySplashScreen() {
        Completable.timer(3,TimeUnit.SECONDS,AndroidSchedulers.mainThread())
            .subscribe({
                val currentUser = firebaseAuth.currentUser
                if(currentUser != null) {
                    checkUserFromFirebase()
                } else {
                    firebaseAuth.addAuthStateListener(listener)
                }
            })
    }

    override fun onStop() {
        if (firebaseAuth != null && listener != null) firebaseAuth.removeAuthStateListener(listener)
        super.onStop()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_splash_screen)
        progressBar = findViewById(R.id.progress_bar)
        init()
    }

    private fun init() {
        database = FirebaseDatabase.getInstance()
        riderInfoRef = database.getReference(Common.RIDER_INFO_REFERENCE)
        provider = Arrays.asList(
            AuthUI.IdpConfig.PhoneBuilder().build(),
            AuthUI.IdpConfig.GoogleBuilder().build()
        )
        firebaseAuth = FirebaseAuth.getInstance()
        listener = FirebaseAuth.AuthStateListener { myFirebaseAuth ->
            val user = myFirebaseAuth.currentUser
            if(user != null)
            {
                checkUserFromFirebase()
            }
            else
            {
                showLoginLayout()
            }
        }
    }

    private fun showLoginLayout() {
        val authMethodPickerLayout = AuthMethodPickerLayout.Builder(R.layout.activity_sign_in)
            .setPhoneButtonId(R.id.btn_phone_sign_in)
            .setGoogleButtonId(R.id.btn_google_sign_in)
            .build()

        startActivityForResult(AuthUI.getInstance()
            .createSignInIntentBuilder()
            .setAuthMethodPickerLayout(authMethodPickerLayout)
            .setTheme(R.style.SignInTheme)
            .setAvailableProviders(provider)
            .setIsSmartLockEnabled(false)
            .build(), LOGIN_REQUEST_CODE
        )
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if(requestCode == LOGIN_REQUEST_CODE)
        {
            val response = IdpResponse.fromResultIntent(data)
            if(resultCode == Activity.RESULT_OK)
            {
                val user = FirebaseAuth.getInstance().currentUser
                user?.let { checkUserFromFirebase() }
            }
            else
            {
                val errorMsg = response?.error?.message ?: "登录失败"
                Toast.makeText(this@SplashScreenActivity, errorMsg, Toast.LENGTH_LONG).show()
            }
        }
    }

    private fun checkUserFromFirebase() {
        riderInfoRef.child(FirebaseAuth.getInstance().currentUser!!.uid)
            .addListenerForSingleValueEvent(object:ValueEventListener{
                override fun onDataChange(p0: DataSnapshot) {
                    if(p0.exists())
                    {
                        val model = p0.getValue(RiderModel::class.java)
                        goToHomeActivity(model)
                    }
                    else
                    {
                        showRegisterLayout()
                    }
                }

                override fun onCancelled(p0: DatabaseError) {
                    Toast.makeText(this@SplashScreenActivity,p0.message,Toast.LENGTH_LONG).show()
                }
            })
    }

    private fun showRegisterLayout() {
        val builder = AlertDialog.Builder(this,R.style.DialogTheme)
        val itemView = LayoutInflater.from(this).inflate(R.layout.layout_register,null)

        val edt_first_name = itemView.findViewById<View>(R.id.edt_first_name) as TextInputEditText
        val edt_last_name = itemView.findViewById<View>(R.id.edt_last_name) as TextInputEditText
        val edt_phone_number = itemView.findViewById<View>(R.id.edt_phone_number) as TextInputEditText

        val btn_continue = itemView.findViewById<View>(R.id.btn_register) as Button

        // 修复手机号预填逻辑
        FirebaseAuth.getInstance().currentUser?.phoneNumber?.let { phone ->
            if(TextUtils.isDigitsOnly(phone)) {
                edt_phone_number.setText(phone)
            }
        }

        builder.setView(itemView)
        val dialog = builder.create()
        dialog.show()

        // 修复输入验证逻辑
        btn_continue.setOnClickListener{
            val firstName = edt_first_name.text.toString().trim()
            val lastName = edt_last_name.text.toString().trim()
            val phoneNumber = edt_phone_number.text.toString().trim()

            when {
                TextUtils.isEmpty(firstName) -> {
                    Toast.makeText(this@SplashScreenActivity,"请输入名字",Toast.LENGTH_SHORT).show()
                    return@setOnClickListener
                }
                TextUtils.isDigitsOnly(firstName) -> {
                    Toast.makeText(this@SplashScreenActivity,"名字不能全是数字",Toast.LENGTH_SHORT).show()
                    return@setOnClickListener
                }
                TextUtils.isEmpty(lastName) -> {
                    Toast.makeText(this@SplashScreenActivity,"请输入姓氏",Toast.LENGTH_SHORT).show()
                    return@setOnClickListener
                }
                TextUtils.isDigitsOnly(lastName) -> {
                    Toast.makeText(this@SplashScreenActivity,"姓氏不能全是数字",Toast.LENGTH_SHORT).show()
                    return@setOnClickListener
                }
                TextUtils.isEmpty(phoneNumber) -> {
                    Toast.makeText(this@SplashScreenActivity,"请输入手机号",Toast.LENGTH_SHORT).show()
                    return@setOnClickListener
                }
                !TextUtils.isDigitsOnly(phoneNumber) -> {
                    Toast.makeText(this@SplashScreenActivity,"手机号必须全是数字",Toast.LENGTH_SHORT).show()
                    return@setOnClickListener
                }
                else -> {
                    val model = RiderModel()
                    model.firstName = firstName
                    model.lastName = lastName
                    model.phoneNumber = phoneNumber

                    progressBar.visibility = View.VISIBLE

                    riderInfoRef.child(FirebaseAuth.getInstance().currentUser!!.uid)
                        .setValue(model)
                        .addOnFailureListener{ e ->
                            Toast.makeText(this@SplashScreenActivity,"${e.message}",Toast.LENGTH_SHORT).show()
                            dialog.dismiss()
                            progressBar.visibility = View.GONE
                        }
                        .addOnSuccessListener {
                            Toast.makeText(this@SplashScreenActivity,"注册成功!",Toast.LENGTH_SHORT).show()
                            dialog.dismiss()
                            goToHomeActivity(model)
                            progressBar.visibility = View.GONE
                        }
                }
            }
        }
    }

    private fun goToHomeActivity(model: RiderModel?) {
        Common.currentRider = model
        startActivity(Intent(this,HomeActivity::class.java))
        finish()
    }
}

核心问题与修复说明

1. 空指针异常修复

  • onActivityResult错误处理:原代码直接强制解包response!!.error!!,空值时触发崩溃,改为空安全判断并提供默认提示;登录成功后手动调用checkUserFromFirebase,避免AuthStateListener未触发导致流程停滞。
  • ProgressBar绑定:原代码在弹窗中临时获取ProgressBar,可能因布局层级问题返回null,改为在Activity初始化时绑定成员变量,确保非空。

2. 输入验证逻辑修复

  • 修正姓名验证逻辑:优先检查是否为空,再判断是否全为数字;
  • 修正手机号验证逻辑:检查是否为空且是否为纯数字;
  • 修复手机号预填判断条件,确保只有合法手机号才会自动填充。

3. “手机号需要验证”提示解决

  • 确认骑手端google-services.json是从Firebase控制台对应应用下载的,与司机端配置区分开;
  • 检查Firebase控制台中骑手应用的登录方法,确保手机号登录已启用,并添加正确的SHA-1证书指纹(含调试、发布版本);
  • 手动添加的Firebase Auth用户需完成手机号验证流程,仅添加账号未验证会触发验证提示。

4. AuthStateListener逻辑优化

延迟启动后先检查当前用户状态,若已登录则直接进入用户信息检查流程,无需等待AuthStateListener触发,提升启动效率。

内容的提问来源于stack exchange,提问作者Irakli Gvelesiani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 17:02:37