我正在尝试使用以下代码来验证已登录用户提供的手机号码。这是通过 Firebase 电话身份验证完成的,最后一步是在未执行收到的凭据的情况下登录 Firebase。但是没有发送/接收短信……应用程序不断崩溃?
initView()
startVerfiy()
verifyOTPBtn.setOnClickListener {
// try to enter the code by yourself to handle the case
// if user enter another sim card used in another phone ...
var code = enterOTPNo.text
Log.e("code is --- ", code.toString())
if (code != null && !code.isEmpty() && mVerificationId != null && !mVerificationId!!.isEmpty()) {
showProgressDialog(this, "please wait...", false)
val credential = PhoneAuthProvider.getCredential(mVerificationId!!, code.toString())
showMessagesActivity()
// signInWithPhoneAuthCredential(credential)
}
}
//Resend OTP
resendOTP.setOnClickListener {
if (mResendToken != null && !isTimerActive) {
resendVerificationCode(phoneNumber.toString(), mResendToken)
showTimer(60000)
showProgressDialog(this, "Sending a verification code", false)
} else {
toast("Sorry, You Can't request new code now, Please wait ...")
}
}
//Reset no option
// wrong_tv.setOnClickListener {
// showLoginActivity()
// }
}
private fun resendVerificationCode(
phoneNumber: String,
token: PhoneAuthProvider.ForceResendingToken?
) {
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phoneNumber, // Phone number to verify
60, // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
this, // Activity (for callback binding)
callbacks, // OnVerificationStateChangedCallbacks
token
) // ForceResendingToken from callbacks
}
private fun initView() {
// init vars from bundle
phoneNumber = intent.getStringExtra("phoneNumber")
// init fire base verfiyPhone number callback
callbacks = object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
override fun onCodeAutoRetrievalTimeOut(verificationId: String) {
if (progressDialog != null) {
dismissProgressDialog(progressDialog)
}
notifyUserAndRetry("Time Out :( failed.Retry again!")
}
override fun onVerificationCompleted(credential: PhoneAuthCredential) {
// This callback will be invoked in two situations:
// 1 - Instant verification. In some cases the phone number can be instantly
// verified without needing to send or enter a verification code.
// 2 - Auto-retrieval. On some devices Google Play services can automatically
// detect the incoming verification SMS and perform verification without
// user action.
Log.e("onVerificationCompleted", "onVerificationCompleted:$credential")
if (progressDialog != null) {
dismissProgressDialog(progressDialog)
}
val smsMessageSent: String = credential.smsCode.toString()
Log.e("the message is ----- ", smsMessageSent)
if (smsMessageSent != null){
enterOTPNo.setText(smsMessageSent)
}
//Saving access setting in Shared Preferences
val preferences = getSharedPreferences("MessagesAccess", Context.MODE_PRIVATE)
val editor = preferences.edit()
editor.putString("noVerified","1")
editor.apply()
//Display Messages Activity
showMessagesActivity()
// signInWithPhoneAuthCredential(credential)
}
override fun onVerificationFailed(e: FirebaseException) {
// This callback is invoked in an invalid request for verification is made,
// for instance if the the phone number format is not valid.
Log.e("+++2", "onVerificationFailed", e)
if (progressDialog != null) {
dismissProgressDialog(progressDialog)
}
if (e is FirebaseAuthInvalidCredentialsException) {
// Invalid request
Log.e("Exception:", "FirebaseAuthInvalidCredentialsException", e)
Log.e("=========:", "FirebaseAuthInvalidCredentialsException " + e.message)
} else if (e is FirebaseTooManyRequestsException) {
// The SMS quota for the project has been exceeded
Log.e("Exception:", "FirebaseTooManyRequestsException", e)
}
// Show a message and update the UI
notifyUserAndRetry("Your Phone Number might be wrong or connection error.Retry again!")
}
// override fun onCodeSent(verificationId: String?, token: PhoneAuthProvider.ForceResendingToken) {
// //for low level version which doesn't do auto verification save the verification code and the token
//
// dismissProgressDialog(progressDialog)
// timeRemaining.visibility = View.GONE
// // Save verification ID and resending token so we can use them later
// Log.e("onCodeSent===", "onCodeSent:$verificationId")
//
// mVerificationId = verificationId
// mResendToken = token
//
// }
}
}
private fun startVerfiy() {
Log.e("User Phone Number === ", phoneNumber!!)
if (phoneNumber != null && !phoneNumber!!.isEmpty()) {
startPhoneNumberVerification(phoneNumber!!)
showTimer(60000)
showProgressDialog(this, "Sending a verification code", false)
} else {
toast("Please enter a valid number to continue!")
}
}
// private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) {
// val mAuth = FirebaseAuth.getInstance()
// mAuth.signInWithCredential(credential)
// .addOnCompleteListener(this) { task ->
// if (task.isSuccessful) {
//
// if (progressDialog != null) {
// dismissProgressDialog(progressDialog)
// }
//
// val user = task.result.user
// Log.e("Sign in with phone auth", "Success $user")
// showMessagesActivity()
// } else {
//
// if (progressDialog != null) {
// dismissProgressDialog(progressDialog)
// }
//
// notifyUserAndRetry("Your Phone Number Verification is failed.Retry again!")
// }
// }
// }
// This method will send a code to a given phone number as an SMS
private fun startPhoneNumberVerification(phoneNumber: String) {
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phoneNumber, // Phone number to verify
60, // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
this, // Activity (for callback binding)
callbacks
) // OnVerificationStateChangedCallbacks
}
private fun notifyUserAndRetry(message: String) {
val alertDialogBuilder = AlertDialog.Builder(this)
alertDialogBuilder.setMessage(message)
alertDialogBuilder.setPositiveButton("Ok",
DialogInterface.OnClickListener { arg0, arg1 -> showLoginActivity() })
alertDialogBuilder.setNegativeButton("Cancel",
DialogInterface.OnClickListener { dialog, which -> showLoginActivity() })
val alertDialog = alertDialogBuilder.create()
alertDialog.show()
}
// helpers methods :)
private fun toast(message: String) {
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
}
private fun showTimer(milliesInFuture: Long) {
isTimerActive = true
mCounterDown = object : CountDownTimer(milliesInFuture, 1000) {
override fun onTick(millisUntilFinished: Long) {
timeLeft = millisUntilFinished
timeRemaining.visibility = View.VISIBLE
timeRemaining.text = "seconds remaining: " + millisUntilFinished / 1000
//here you can have your logic to set text to edittext
}
override fun onFinish() {
timeRemaining.visibility = View.GONE
isTimerActive = false
}
}.start()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putLong("timeLeft", timeLeft)
outState.putString("phoneNumber", phoneNumber)
}
private fun showProgressDialog(
mActivity: Context,
message: String,
isCancelable: Boolean
): ProgressDialog {
progressDialog = ProgressDialog(mActivity)
progressDialog!!.show()
progressDialog!!.setCancelable(isCancelable)
progressDialog!!.setCanceledOnTouchOutside(false)
progressDialog!!.setMessage(message)
return progressDialog as ProgressDialog
}
private fun dismissProgressDialog(progressDialog: ProgressDialog?) {
if (progressDialog != null && progressDialog.isShowing) {
progressDialog.dismiss()
}
}
private fun showLoginActivity() {
startActivity(
Intent(this, LoginPhoneScreen::class.java)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
)
}
private fun showMessagesActivity() {
//first save phone number to data base and then call TODO worker to sync phone numbers for contacts
firebaseUser = FirebaseAuth.getInstance().currentUser
refUsers = FirebaseDatabase.getInstance().reference.child("Users").child(firebaseUser!!.uid)
phoneRefUsers = FirebaseDatabase.getInstance().reference.child("PhoneDirectory").child(phoneNumber!!)
//to save message on Firebase - Users Node
val usersHashMap = HashMap<String, Any?>()
usersHashMap["verPhone"] = phoneNumber
val phoneDirectoryHashMap = HashMap<String, Any?>()
phoneDirectoryHashMap["userId"] = firebaseUser!!.uid
//to save message on Firebase - Users Phone Directory Node
phoneRefUsers!!.updateChildren(phoneDirectoryHashMap).addOnCompleteListener {
refUsers!!.updateChildren(usersHashMap)
.addOnCompleteListener { task ->
if (task.isSuccessful) {
val intent = Intent(this, Messages::class.java)
startActivity(intent)
finish()
}
}
}
}
override fun onBackPressed() {
finish()
}
override fun onDestroy() {
super.onDestroy()
if (mCounterDown != null) {
mCounterDown!!.cancel()
}
}