【问题标题】:4 days error is here, Smart cast to 'Button!' is impossible, because 'generateOTPBtn' is a mutable property that could have been changed by this time4 天错误在这里,智能投射到“按钮!”是不可能的,因为 'generateOTPBtn' 是一个可变属性,此时可能已更改
【发布时间】:2021-10-16 16:24:51
【问题描述】:

已尝试查看过去的参考资料,以获得此解决方案,但似乎没有得到它。 下面有问题的代码最初是用 Java 编写的,所以 Android Studio Arctic 帮助我将其转换为 Kotlin。 这是为了为我要构建的应用程序实现或拥有真正有效的电话身份验证方法。或者,任何教程链接都会有很大帮助。 提取的链接在这里https://www.geeksforgeeks.org/firebase-authentication-with-phone-number-otp-in-android/ 有错误的行是 48、50、59、65、67 和 72。 我的工作环境在这里

Android Studio 北极狐 | 2020.3.1 构建 #AI-203.7717.56.2031.7583922,于 2021 年 7 月 26 日构建 运行时版本:11.0.10+0-b96-7249189 amd64 VM:OpenJDK 64-Bit Server VM by Oracle Corporation Windows 8 6.2 GC:G1 Young Generation,G1 Old一代 内存:1280M 内核:4 注册表: external.system.auto.import.disabled=true 非捆绑插件: org.jetbrains.kotlin

package net.nyange.busiro

import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.android.gms.tasks.TaskExecutors
import com.google.firebase.FirebaseException
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.PhoneAuthCredential
import com.google.firebase.auth.PhoneAuthProvider
import java.util.concurrent.TimeUnit


class MainActivity : AppCompatActivity() {
    //variable for FirebaseAuth class
    private var mAuth: FirebaseAuth? = null

    //variable for our text input field for phone and OTP.
    private var edtPhone: EditText? = null
    private var edtOTP: EditText? = null

    //buttons for generating OTP and verifying OTP
    private var verifyOTPBtn: Button? = null
    private var generateOTPBtn: Button? = null

    //string for storing our verification ID
    private var verificationId: String? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //below line is for getting instance of our FirebaseAuth.
        mAuth = FirebaseAuth.getInstance()
        //initializing variables for button and Edittext.
        edtPhone = findViewById(R.id.idEdtPhoneNumber)
        edtOTP = findViewById(R.id.idEdtOtp)
        verifyOTPBtn = findViewById(R.id.idBtnVerify)
        generateOTPBtn = findViewById(R.id.idBtnGetOtp)



        //setting onclick listener for generate OTP button.

        generateOTPBtn.setOnClickListener(View.OnClickListener {
            //below line is for checking weather the user has entered his mobile number or not.
            if (TextUtils.isEmpty(edtPhone.getText().toString())) {
                //when mobile number text field is empty displaying a toast message.
                Toast.makeText(
                    this@MainActivity,
                    "Please enter a valid phone number.",
                    Toast.LENGTH_SHORT
                ).show()
            } else {
                //if the text field is not empty we are calling our send OTP method for getting OTP from Firebase.
                val phone = "+256" + edtPhone.getText().toString()
                sendVerificationCode(phone)
            }
        })

        //initializing on click listener for verify otp button
        verifyOTPBtn.setOnClickListener(View.OnClickListener {
            //validating if the OTP text field is empty or not.
            if (TextUtils.isEmpty(edtOTP.getText().toString())) {
                //if the OTP text field is empty display a message to user to enter OTP
                Toast.makeText(this@MainActivity, "Please enter OTP", Toast.LENGTH_SHORT).show()
            } else {
                //if OTP field is not empty calling method to verify the OTP.
                verifyCode(edtOTP.getText().toString())
            }
        })
    }

    private fun signInWithCredential(credential: PhoneAuthCredential) {
        //inside this method we are checking if the code entered is correct or not.
        mAuth?.signInWithCredential(credential)
            ?.addOnCompleteListener { task ->
                if (task.isSuccessful) {
                    //if the code is correct and the task is successful we are sending our user to new activity.
                    val i = Intent(this@MainActivity, HomeActivity::class.java)
                    startActivity(i)
                    finish()
                } else {
                    //if the code is not correct then we are displaying an error message to the user.
                    Toast.makeText(
                        this@MainActivity,
                        task.exception.getMessage(),
                        Toast.LENGTH_LONG
                    ).show()
                }
            }
    }

    private fun sendVerificationCode(number: String) {
        //this method is used for getting OTP on user phone number.
        PhoneAuthProvider.getInstance().verifyPhoneNumber(
            number,  //first parameter is user's mobile number
            60,  //second parameter is time limit for OTP verification which is 60 seconds in our case.
            TimeUnit.SECONDS,  // third parameter is for initializing units for time period which is in seconds in our case.
            TaskExecutors.MAIN_THREAD,  //this task will be executed on Main thread.
            mCallBack //we are calling callback method when we receive OTP for auto verification of user.
        )
    }

    //callback method is called on Phone auth provider.
    private val   //initializing our callbacks for on verification callback method.
            mCallBack: PhoneAuthProvider.OnVerificationStateChangedCallbacks =
        object : PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
            //below method is used when OTP is sent from Firebase
            fun onCodeSent(
                s: String?,
                forceResendingToken: PhoneAuthProvider.ForceResendingToken?
            ) {
                if (forceResendingToken != null) {
                    if (s != null) {
                        super.onCodeSent(s, forceResendingToken)
                    }
                }
                //when we receive the OTP it contains a unique id which we are storing in our string which we have already created.
                verificationId = s
            }

            //this method is called when user receive OTP from Firebase.
            override fun onVerificationCompleted(phoneAuthCredential: PhoneAuthCredential) {
                //below line is used for getting OTP code which is sent in phone auth credentials.
                val code: String? = phoneAuthCredential.smsCode
                //checking if the code is null or not.
                if (code != null) {
                    //if the code is not null then we are setting that code to our OTP edittext field.
                    edtOTP!!.setText(code)
                    //after setting this code to OTP edittext field we are calling our verified method.
                    verifyCode(code)
                }
            }

            //this method is called when firebase doesn't sends our OTP code due to any error or issue.
            override fun onVerificationFailed(e: FirebaseException) {
                //displaying error message with firebase exception.
                Toast.makeText(this@MainActivity, e.getMessage(), Toast.LENGTH_LONG).show()
                //Toast.makeText(this@MainActivity, e.message, Toast.LENGTH_LONG).show()
            }
        }

    //below method is use to verify code from Firebase.
    private fun verifyCode(code: String) {
        //below line is used for getting getting credentials from our verification id and code.
        val credential: PhoneAuthCredential = PhoneAuthProvider.getCredential(verificationId.toString(), code)
        //after getting credential we are calling sign in method.
        signInWithCredential(credential)
    }
}

【问题讨论】:

  • 您忘记提及错误指的是哪一行。不过有一个猜测,如果是verifyOTPBtn.setOnClickListener,那是因为verifyOTPBtn 可以为空。您必须要么断言它不是,使用 ? 运算符,要么首先将其声明为 lateinit

标签: android kotlin one-time-password


【解决方案1】:

错误非常清楚地解释了问题:由于generateOTPBtn 的类型为Button?,当您调用generateOTPBtn.setOnClickListener() 时,Kotlin 编译器不能保证它不会为空。这里最简单的解决方法是替换

private var generateOTPBtn: Button? = null

private lateinit var generateOTPBtn: Button

【讨论】:

  • 嗨,这确实有效。但其他人似乎也有这个问题,只是他们在同一个街区内。
  • 您可以使用相同的策略来处理它们。你现在有什么问题?
猜你喜欢
  • 2021-10-18
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 1970-01-01
  • 2017-11-19
  • 2018-03-23
  • 1970-01-01
相关资源
最近更新 更多