Home > Net >  Why I am not able to use mobile authentication with firebase in jetpack compose?
Why I am not able to use mobile authentication with firebase in jetpack compose?

Time:05-07

I am try to learning android jetpack compose, I have simple app, and I want to use mobile authentication with firebase for my project. I am using MVVM in the project, so when I debug the project, it throw an error like

You must specify an Activity on your PhoneAuthOptions. Please call #setActivity()

for the .build() in the view model, how can I arrange my viewmodel, I did not find any solution on internet, any idea?

viewmodel:

@HiltViewModel
class AuthenticationViewModel @Inject constructor(


    ) : ViewModel() {

    private val mAuth = FirebaseAuth.getInstance()

    var verificationOtp = ""
    var popNotification = mutableStateOf<Event<String>?>(null)

    fun send(mobileNum: String) {
        val options = PhoneAuthOptions.newBuilder(mAuth)
            .setPhoneNumber(" 91$mobileNum")
            .setTimeout(60L, TimeUnit.SECONDS)
            .setCallbacks(object :
                PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
                override fun onVerificationCompleted(p0: PhoneAuthCredential) {
                    handledException(customMessage = "Verification Completed")

                }

                override fun onVerificationFailed(p0: FirebaseException) {
                    handledException(customMessage = "Verification Failed")

                }

                override fun onCodeSent(otp: String, p1: PhoneAuthProvider.ForceResendingToken) {
                    super.onCodeSent(otp, p1)
                    verificationOtp = otp
                    handledException(customMessage = "Otp Send Successfully")

                }
            }).build()
        PhoneAuthProvider.verifyPhoneNumber(options)
    }

     fun otpVerification(otp: String) {
        val credential = PhoneAuthProvider.getCredential(verificationOtp, otp)
        FirebaseAuth.getInstance().signInWithCredential(credential)
            .addOnCompleteListener { task ->
                if (task.isSuccessful) {
                    handledException(customMessage = "Verification Successful")

                } else {
                    handledException(customMessage =  "Wrong Otp")

                }
            }
    }


    private fun handledException(exception: Exception? = null, customMessage: String = "") {
        exception?.printStackTrace()
        val errorMsg = exception?.message ?: ""
        val message = if (customMessage.isEmpty()) {
            errorMsg
        } else {
            "$customMessage: $errorMsg"
        }
        popNotification.value = Event(message)
    }


    }

screen1:

@Composable
fun PhoneScreen(
    navController: NavController,
    modelAuthentication: AuthenticationViewModel,
    onClick: (mobileNum: String, otp: String) -> Unit
) {

    val phoneNumber = remember { mutableStateOf("") }

   OutlinedTextField(
            value = phoneNumber.value,
            colors = TextFieldDefaults.textFieldColors(
                backgroundColor = white,
                focusedIndicatorColor = Grey,
                unfocusedIndicatorColor = Grey,
                focusedLabelColor = Grey,
                unfocusedLabelColor = Grey,
            

                ),
            onValueChange = { phoneNumber.value = it },
            label = { Text(text = "Phone Number") },
            placeholder = { Text(text = "Phone Number") },
            singleLine = true,
            modifier = Modifier.fillMaxWidth(0.8f)

        )

    Button(
                modifier = Modifier
                    .width(285.dp)
                    .height(55.dp),
                onClick = {

                    modelAuthentication.send(phoneNumber.value)
                    navController.navigate("phoneVerify")

                },
                colors = ButtonDefaults.buttonColors(
                    backgroundColor = Color.Custom
                ),
                shape = RoundedCornerShape(60)
            ) {
                Text(
                    text = "Next",
                    style = TextStyle(
                        fontSize = 18.sp,
                        color = white,


                        )

                )
            }
}

screen2:

@Composable
fun PhoneVerifyScreen(
navController: NavController,
modelAuthentication: AuthenticationViewModel,
onClick: (mobileNum: String, otp: String) -> Unit
 ) {

 val phoneNumberOtp = remember { mutableStateOf("") }

   OutlinedTextField(
            value = phoneNumberOtp.value,
            colors = TextFieldDefaults.textFieldColors(
                backgroundColor = white,
                focusedIndicatorColor = Grey,
                unfocusedIndicatorColor = Grey,
                focusedLabelColor = Grey,
                unfocusedLabelColor = Grey,
            

                ),
            onValueChange = { phoneNumberOtp.value = it },
            label = { Text(text = "code") },
            placeholder = { Text(text = "code") },
            singleLine = true,
            modifier = Modifier.fillMaxWidth(0.8f)

        )

    Button(
                modifier = Modifier
                    .width(285.dp)
                    .height(55.dp),
                onClick = {

                modelAuthentication.otpVerification(phoneNumberOtp.value)

                navController.navigate("home")

                },
                colors = ButtonDefaults.buttonColors(
                    backgroundColor = Color.Custom
                ),
                shape = RoundedCornerShape(60)
            ) {
                Text(
                    text = "Next",
                    style = TextStyle(
                        fontSize = 18.sp,
                        color = white,


                        )

                )
            }
}

CodePudding user response:

You need to specify Activity since it is a required parameter of the builder.

You will have to move the code of the builder to your Activity 'cause you're not allowed to have a link to Activity in a ViewModel.

Inside the verification result callback you can call ViewModel's methods to pass the result or exception.

CodePudding user response:

With hilt you can inject context using @ApplicationContext:

@HiltViewModel
class AuthenticationViewModel @Inject constructor(
    @ApplicationContext context: Context,
): ViewModel() {
    // pass context to PhoneAuthOptions
}
  • Related