Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/187.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何侦听失败的登录尝试-Kotlin MVVM_Android_Kotlin_Mvvm_Firebase Authentication - Fatal编程技术网

Android 如何侦听失败的登录尝试-Kotlin MVVM

Android 如何侦听失败的登录尝试-Kotlin MVVM,android,kotlin,mvvm,firebase-authentication,Android,Kotlin,Mvvm,Firebase Authentication,因此,我遵循了“yoursTruly”的建议,在我的活动中创建了一个AuthStateListener(如下所述:) 这非常有效,因为活动只是在侦听身份验证,如果有人登录并且片段只是通过ViewModel调用signIn(电子邮件、密码),则会转移到下一个活动 但是,无法找到查找失败的登录尝试的方法(因此UI看起来好像没有响应) 我的结构如下:活动->片段->视图模型->存储库 我正在使用数据绑定和导航 活动 class LoginActivity : AppCompatActivity(),

因此,我遵循了“yoursTruly”的建议,在我的活动中创建了一个AuthStateListener(如下所述:)

这非常有效,因为活动只是在侦听身份验证,如果有人登录并且片段只是通过ViewModel调用signIn(电子邮件、密码),则会转移到下一个活动

但是,无法找到查找失败的登录尝试的方法(因此UI看起来好像没有响应)

我的结构如下:活动->片段->视图模型->存储库

我正在使用数据绑定和导航

活动

class LoginActivity : AppCompatActivity(), FirebaseAuth.AuthStateListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.login_activity)
    }

    override fun onStart() {
        super.onStart()
        FirebaseAuth.getInstance().addAuthStateListener(this)
    }

    override fun onStop() {
        super.onStop()
        FirebaseAuth.getInstance().removeAuthStateListener(this)
    }

    override fun onAuthStateChanged(firebaseAuth: FirebaseAuth) {

        // Will only fire if state has changed!

        if (FirebaseAuth.getInstance().currentUser == null) {
            Toast.makeText(this,"Welcome to the Locators App!\n\nPlease login to continue", Toast.LENGTH_LONG).show()
            return
        }

        firebaseAuth.currentUser?.getIdToken(true)
            ?.addOnSuccessListener { result ->
                val idToken = result.token
                Toast.makeText(this,"User Signed In", Toast.LENGTH_LONG).show()
                Log.d(TAG, "GetTokenResult result (check this at https://jwt.io/ = $idToken")
                goToSiteActivity()
            }
    }

    private fun goToSiteActivity() {
        val intent = Intent(this, SiteActivity::class.java)
        startActivity(intent)
        finish()
    }
}
class FirestoreRepository {

        var firebaseAuth = FirebaseAuth.getInstance()
        var firebaseUser = firebaseAuth.currentUser
        var failedLogin: Boolean = false

        fun loginUser(email: String, password: String) {
                failedLogin = false

                firebaseAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener {
                        if (it.isSuccessful) {
                                // Sign in success, update UI with the signed-in user's information
                                Log.d(TAG, "signInWithEmail:success")

                        } else {
                                // If sign in fails, display a message to the user.
                                Log.d(TAG, "signInWithEmail:failure", it.exception)
                                failedLogin = true
                        }
                }
        }
}
片段

class LoginFragment : Fragment() {

    private lateinit var loginViewModel: LoginViewModel

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        val binding: LoginFragmentBinding = DataBindingUtil.inflate(
            inflater, R.layout.login_fragment, container, false)

        binding.apply {
            loginPasswordResetText.setOnClickListener{
                findNavController().navigate(R.id.action_loginFragment_to_loginPasswordResetFragment)
            }
            loginButton.setOnClickListener{
                loginProgressBar.visibility = View.VISIBLE
                val email = loginEmailEditText.text.toString()
                val password = loginPasswordEditText.text.toString()
                if(validateForm(email, password)) {
                    loginViewModel.loginUser(email, password)

                }
                loginProgressBar.visibility = View.GONE

            }
            loginNewUserText.setOnClickListener{
                findNavController().navigate(R.id.action_loginFragment_to_loginUserRegisterFragment)
            }
        }
        return binding.root

    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)

        loginViewModel = ViewModelProviders.of(requireActivity()).get(LoginViewModel::class.java)
    }


    private fun validateForm(email: String, password: String): Boolean {

        var validForm = true

        if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
            loginEmailEditText.error = "Please enter valid email address!"
            validForm = false
        } else loginEmailEditText.error = null

        if (password.isEmpty()) {
            loginPasswordEditText.error = "Please enter password!"
            validForm = false
        } else loginPasswordEditText.error = null

        Log.d(TAG,"validateForm: (email = $email, password =  $password, validateForm = $validForm)")

        return validForm
    }

}
视图模型

class LoginViewModel : ViewModel() {

    fun loginUser (email: String, password: String) {
        firestoreRepository.loginUser(email, password)
    }
}
存储库

class LoginActivity : AppCompatActivity(), FirebaseAuth.AuthStateListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.login_activity)
    }

    override fun onStart() {
        super.onStart()
        FirebaseAuth.getInstance().addAuthStateListener(this)
    }

    override fun onStop() {
        super.onStop()
        FirebaseAuth.getInstance().removeAuthStateListener(this)
    }

    override fun onAuthStateChanged(firebaseAuth: FirebaseAuth) {

        // Will only fire if state has changed!

        if (FirebaseAuth.getInstance().currentUser == null) {
            Toast.makeText(this,"Welcome to the Locators App!\n\nPlease login to continue", Toast.LENGTH_LONG).show()
            return
        }

        firebaseAuth.currentUser?.getIdToken(true)
            ?.addOnSuccessListener { result ->
                val idToken = result.token
                Toast.makeText(this,"User Signed In", Toast.LENGTH_LONG).show()
                Log.d(TAG, "GetTokenResult result (check this at https://jwt.io/ = $idToken")
                goToSiteActivity()
            }
    }

    private fun goToSiteActivity() {
        val intent = Intent(this, SiteActivity::class.java)
        startActivity(intent)
        finish()
    }
}
class FirestoreRepository {

        var firebaseAuth = FirebaseAuth.getInstance()
        var firebaseUser = firebaseAuth.currentUser
        var failedLogin: Boolean = false

        fun loginUser(email: String, password: String) {
                failedLogin = false

                firebaseAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener {
                        if (it.isSuccessful) {
                                // Sign in success, update UI with the signed-in user's information
                                Log.d(TAG, "signInWithEmail:success")

                        } else {
                                // If sign in fails, display a message to the user.
                                Log.d(TAG, "signInWithEmail:failure", it.exception)
                                failedLogin = true
                        }
                }
        }
}

这个问题与一个更大的查询有关,如果您在Repo中创建LiveData,您如何从ViewModel中观察(即,您使用什么作为LifeCycleOwner?),但我将另外问一个问题。

AuthStateListener不足以确定登录何时失败。它只会在用户状态在登录和注销之间发生变化时通知您

您必须使用firebaseAuth.Signin with Email和Password的结果来确定登录是否失败。看起来您已经有了一些代码来处理这种情况,但是除了设置属性之外,您并没有对错误进行太多处理


您应该做的是让您的
logiuser
ViewModel方法返回一个LiveData,当登录成功或失败时会收到通知。您必须使用Email和Password将呼叫连接到登录,以更改该LiveData的状态,并且您的视图必须观察该LiveData,以便在必要时向用户显示消息。

此问题看起来像是特定于android的。如果理解正确,请添加“android”标记。android添加..嗨,道格,再次感谢你的回复-我已经尝试过了,但我正在努力处理ViewModel中的代码。具体而言,观察者的生命周期所有者。。当虚拟机被销毁时,我是否应该使用ObserveForver并手动删除observer?如果这对您有效的话。如果您有新问题,我建议发布一个新问题来解释问题是什么,以及哪些问题没有按照您预期的方式工作。我的帖子已经过审核(希望此评论可以!),但为了完整性,我在这里更新了我的问题,并提供了解决方案: