FIrebase sign in and out options are not working - android

Can someone explain to me why this simple code is not working properly?
In the beginning I created an object with auth and currentUser
object FirebaseUtils {
val auth: FirebaseAuth = FirebaseAuth.getInstance()
val currentUser: FirebaseUser? = auth.currentUser
}
My login activity function
fun login(){
val email = binding.loginInput.text.toString()
val password = binding.passwordInput.text.toString()
auth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener {
task ->
if (task.isSuccessful){
task.result
Log.d("login_status", "Logged: ${currentUser?.uid}")
startActivity(Intent(this, MainActivity::class.java))
finish()
} else {
Log.d("login_status", task.exception.toString())
}
}
}
Start activity:
lifecycleScope.launch {
delay(2000)
if(currentUser?.uid != null){
Log.d("login_status", "Logged: ${currentUser.uid}")
startActivity(Intent(applicationContext, MainActivity::class.java))
}else{
startActivity(Intent(applicationContext, LoginMainActivity::class.java))
}
finish()
}
And sign out
fun signOut(){
auth.signOut()
startActivity(Intent(this, LoginMainActivity::class.java))
Log.d("login_status", "Signed out: ${currentUser?.uid}")
finish()
}
The problem is that after the first login I can see that logged user is null so my app is crashing (no data for the user). However, after restarting I am logged in as this user. I cant also sign out - activity changes to the login screen but even if I pass different credentials the user remains the same.
EDIT
When I log in and restart the app it works - the correct user is logged.
When I log out and restart the app it also works - the user is signed out.
So why is there a problem between activities

Your result is null because you are getting the result object out of the task object but you aren't doing anything with it. Simply calling:
task.result
Doesn't provide any benefit. However, you can save that result into a variable and call AuthResult#getUser() like this:
val user = task.result.getUser()
Log.d("login_status", "Logged: ${user?.uid}")
So right after you authenticate the user successfully, you'll be able to log the UID correctly.

Related

Firebase Auth emailVerified doesn't updated

hi guys i'm trying to do auto login in my app but before login done i wonder if the user verified his email or no.
the problem : even if i verified my account the code doesn't see this and said false.
and here is my code.
class SignInActivity : BaseActivity<SignInViewModel, ActivitySignInBinding>(), Navigator {
private lateinit var preferenceManger: PreferenceManger
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
preferenceManger = PreferenceManger(applicationContext)
autoLogin()
binding.vm = viewModel
viewModel.navigator = this
addPrefManger()
}
private fun autoLogin() {
DataUtils.firebaseUser = Firebase.auth.currentUser
if (preferenceManger.getBoolean(Constants.KEY_IS_SIGNED_IN)) {
when {
DataUtils.firebaseUser!!.isEmailVerified -> {
startActivity(Intent(this, HomeActivity::class.java))
finish()
}
else -> {
startActivity(Intent(this, VerificationActivity::class.java))
finish()
}
}
}
}
this line is always false even if i verified my account.
DataUtils.firebaseUser!!.isEmailVerified
While the verification status of the user profile is updated on the server as soon as they've clicked the link, it may take up to an hour before that information is synchronized to the Android app.
If you want to detect the email verification in the app before it is automatically synchronized, you can:
Sign the user out and in again.
Force reloading of the user profile (after the user has clicked the link) by calling reload on the user object. You can put a button in your UI to do this, or automatically call that, for example in the onResume of the activity.
Also see:
How to verify email without the need of signing in again while using FirebaseUI-auth?
Verification email activity not refreshing

email is not verified

in my application first i authenticate user email and then i am verifying user email i have set dialog activity to inform user to check email and verify email i have close button in dialog activity if user click on it dialog will be dismissed
i have implemented override fun onResume() method first activity and in this method i check user have verified email or not by auth.getInstance().currentUser.isEmailVerified
i ran this app i got email and successfully verify but in onResume() method auth.getInstance().currentUser.isEmailVerified returns false
auth.createUserWithEmailAndPassword(binding.email.text.toString(),binding.password.text.toString()).addOnCompleteListener { task->
Log.d("userAuthenticated","yes")
if(task.isSuccessful)
{
val currUser=auth.currentUser
Log.d("TaskIsSuccessful","Yes")
currUser!!.sendEmailVerification().addOnSuccessListener {
Log.d("Emailissent","yes")
uniqueFirebaseAuthId=task.result!!.user!!.uid.toString()
val sentEmailbinding=ActivityEmailVarificationSignUpBinding.inflate(layoutInflater)
val dialog = Dialog(this#SignUp)
dialog.setContentView(sentEmailbinding.root)
dialog.setCanceledOnTouchOutside(true)
dialog.setCancelable(false)
sentEmailbinding.closebtn.setOnClickListener{
dialog.dismiss()
Log.d("Iamback","Yes")
}
dialog.show()
Log.d("verified",currUser.isEmailVerified.toString())
Log.d("Dialogshown","yes")
Log.d("uniqueFirebaseAuthValue","${uniqueFirebaseAuthId} ")
}.addOnFailureListener {
Log.d("emailauthverification",it.toString())
}
}
task.addOnFailureListener {
Log.d("TaskFail",it.toString())
}
onResume() function
override fun onResume() {
super.onResume()
val userEnterdName=binding.uiqueusername.toString()
val currUser=FirebaseAuth.getInstance().currentUser
if(currUser!!.isEmailVerified) {
val verifiedUser=UseratFirebase(userEnterdName,binding.email.toString(),binding.password.toString())
val uniqueAuthId=uniqueFirebaseAuthId.toString()
database.reference.child("users").child(uniqueAuthId).setValue(verifiedUser).addOnSuccessListener {
val intent=Intent(this#SignUp,SignIn::class.java)
intent.putExtra("Email",binding.email.text.toString())
intent.putExtra("password",binding.email.toString())
}.addOnFailureListener {
Toast.makeText(this#SignUp,"Error occured while stroting data",Toast.LENGTH_LONG).show()
}
}
else
{
Log.d("Curruser", "${currUser.toString() } -> ${currUser.isEmailVerified}")
Toast.makeText(this#SignUp,"Please verify Your Account",Toast.LENGTH_LONG).show()
}
}
Verifying the user's email address happens in another application (you click the link in your mail app, and then it verifies that action in the browser), so you app is not aware of it right away.
The information is encoded in the user's ID token, which is refreshed automatically every hour, or when the user signs in again. So you can either wait/force the user to sign in again, or you can tell the SDK to refresh the token by calling user.getIdToken(true) or user.reload().

The Firebase value keeps regenerating even after i delete them

I've been struggling with this problem for more than a week help me out if you know the fix.
enter image description here
I am trying to delete the data from a child node in the Realtime Firebase but it keeps regenerating even when I delete the token data.
This is my code:
when a user logs in an FCM token is generated automatically (onCreate).
when I try to log him out of his account I want the token to be deleted from the token list but it keeps regenerating even when I logout
this is the User fragment is redirected to after login:
val currentUser : String = firebaseAuth.currentUser?.uid.toString()
val databaseReference = FirebaseDatabase.getInstance("https://trial-38785-default-rtdb.firebaseio.com/")
.getReference("AppUsers").child("Doctor").child(currentUser)
FirebaseMessaging.getInstance().token.addOnCompleteListener {
if (it.isComplete) {
val firebaseToken = it.result.toString()
val myRef =
FirebaseDatabase.getInstance("https://trial-38785-default-rtdb.firebaseio.com/")
.getReference("AppUsers").child("Doctor").child(currentUser)
myRef.child("Token").orderByChild("token").equalTo(firebaseToken)
.addValueEventListener(object : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
val token : Token = Token(firebaseToken)
if (snapshot.exists()) {
return
} else {
databaseReference.child("Token")
.child(currentdate.toString()).setValue(token)
}
}
override fun onCancelled(error: DatabaseError) {
Toast.makeText(context, error.message, Toast.LENGTH_LONG).show()
}
})
}
}.addOnFailureListener {
Toast.makeText(context, it.message, Toast.LENGTH_LONG).show()
}
This is another fragment where the doctor logout.
pressing logout button this is the code i ran
val delRef = FirebaseDatabase.getInstance().getReference("AppUsers")
.child("Doctor").child(currentId.toString())
.child("Token").child(key.toString()).removeValue()
delRef.addOnSuccessListener {
println("Removed.")
}.addOnFailureListener {
println("Not Removed.")
}
When using the Query#addValueEventListener() method, it means that you are trying to listen for real-time updates. That being said, every change that takes place in the database and corresponds to your query, always triggers your onDataChange() method. Since when you are logging out, you remove a value from the query you are listening to, your token gets written again, hence that behavior. This is happening over and over again.
To solve this, simply change the above method call to Query#addListenerForSingleValueEvent(). This means that it listen for changes only once.
I finally figured out what I was doing wrong, I just had to move my code (myRef) outside of FirebaseMessaging.

Why isn't the variable being updated and returned correctly in this function?

So I've been following a video and Google's documentation trying to implement user sign in with Firebase on an android app. Which is working, so to try and tidy up (and help me reuse the code in another project) I have alot of the sign in code moved to a seperate .kt file and used the below funcion to create a new user.
//in LoginActivity.kt
fun createNewUser(email:String, password:String) :Boolean{
var success:Boolean = false
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
success = true
// Sign in success, update UI with the signed-in user's information
Log.d(null, "createUserWithEmail:success")
val user = auth.currentUser
//updateUI(user)
} else {
// If sign in fails, display a message to the user.
Log.w(null, "createUserWithEmail:failure", task.exception)
//Toast.makeText(baseContext, "Authentication failed.",Toast.LENGTH_SHORT).show()
//updateUI(null)
success = false
}
}
return success
}
The issue I am having is that the "success" boolean isn't being updated when the account is created, the Log saying "success" appears to run fine. I tried changing the inital state of success from false to true and that returned true as expected and my code looking at the result of this ran fine.
Here is where its being called from, as I said the toasts run fine but the value of success returned is always what it was initialised as.
//in MainActivity.kt
var login = LoginActivity()
if(login.createNewUser(email,password)) {
Toast.makeText(this,"I got this far",Toast.LENGTH_SHORT).show()
uploadImageToFirebase()
}
else{
Toast.makeText(this,"I didnt get this far",Toast.LENGTH_SHORT).show()
}
Thanks for any help :)
I'll start at the end, because this is a huge mistake:
var login = LoginActivity()
Never instantiate an Activity. Activity instantiation is handled by the operating system. If createNewUser relies on any functions of LoginActivity, then it will fail when called on your own instantiated instance. And if it doesn't rely on them, then don't define it inside LoginActivity.
Regarding your main question:
When you pass a callback to a function, that means it runs asynchronously. The callback will be called some time in the future, after this function has already returned. So createNewUser can't return the result of the callback.
Instead, you can create your own callback for your function like this. I'm treating auth.currentUser as type User, but you should put whatever class it actually is.
fun createNewUser(email:String, password:String, onComplete: (User?) -> Unit) {
auth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this) { task ->
if (task.isSuccessful) {
// Sign in success, update UI with the signed-in user's information
Log.d(null, "createUserWithEmail:success")
onComplete(auth.currentUser)
} else {
// If sign in fails, display a message to the user.
Log.w(null, "createUserWithEmail:failure", task.exception)
onComplete(null)
}
}
}
Then to use it, you can call the function and in your lambda callback you can react based on whether the user is null or not, which indicates failure or success:
createNewUser(email, password) { user ->
if (user != null) {
// success. Do something with the smart-casted non-null user variable
} else {
// failure. Show error message to the user, etc.
}
}

How to Properly SignOut Firebase auth after call DocumentSnapshot Firestore?

So I try to create Sign-out button in a fragment Home but, everytime user SignOut, the app will crash and it caused by document snapshot.
this is my document snapshot code.
private fun loadProfile() {
val user = mAuth!!.currentUser
if (user != null) {
...//loading profile code
}
val uid = user.uid
documentReference = db!!.collection("users").document(uid)
documentReference!!.addSnapshotListener { documentSnapshot, e ->
//this if returning null after user signout
if (documentSnapshot!!.exists()) {
if (documentSnapshot.get(KEY_HP) != null) {
...//loading profile code
}else {
val intent = Intent(this#Home.activity, LoginActivity::class.java)
startActivity(intent)
}
}
} else {
val intent = Intent(this#Home.activity, LoginActivity::class.java)
startActivity(intent)
}
}
as you can see I desperately add else everywhere but that does not help.
this is my Sign-out method
private fun signOut() {
mAuth!!.signOut()
val intent = Intent(this#Home.activity, LoginActivity::class.java)
startActivity(intent)
}
So, I need to properly signout without the app being crash
FirebaseAuth.getInstance().signOut();
Use this to signout from Firebase. And then, if you try to perform any action of a logged in user, you won't be able to, you will have to login again.
FUTURE REFERENCE
After fighting with the "sign-out" method for a couple days, I realized that if you have snapshot listeners attached within the activity, make sure you handle and return the error, as stated here, or else you may run into some Permission Errors and crashes.

Categories

Resources