Want to update profile, started with email to get the hang off. Whenever I click on it to update the email, it adds a new UID for that email alone instead of adding it to the user profile with that UID. Really stuck now. I did have it working but cant seem to get back to it so must be an error here somewhere, thanks,
updateProfile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final String updateEmail = emailTextView.getText().toString();
user.updateEmail(updateEmail).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
firebaseDatabase.getReference("Users").child(user.getUid()).child("email").setValue(updateEmail);
Toast.makeText(getApplicationContext(), "Email update", Toast.LENGTH_LONG).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
});
}
UPDATE
firebaseAuth = FirebaseAuth.getInstance();
firebaseDatabase = FirebaseDatabase.getInstance();
FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
final String uid = firebaseUser.getUid();
Log.d(TAG, "USERID="+uid);
Doin this got me a UID from a completely different user! It did let me change the email for them when I did this but thats no use. Having similar issues deleting users. Is it an issue with a UID does it create a new one everytime they log in?
Related
So basically when a user comes to the "premium" activity in my app he sees a button which says "Purchase premium". When he clicks on it a document in Firestore gets updated (a boolean from false to true) and the button disappears and instead of the button a TextView appears. When the user navigates back to the MainActivity and from there again to the "premium" activity he sees the "Purchase premium" button again which I don't want because he already "bought" it. The question is how can I achieve that when the user clicks on the button, the view of the layout changes for good, so when the user navigates back to the activity he will not be able to make the purchase again. I don't want him to see the button.
Should I use the boolean (premium member: true) that got changed in the document in Firestore after he clicked on it to do this? Like: If document says "premium membership: true" set button visibility gone etc. This would make a "read" to Firestore every time the user navigates to the Activity, is there a better way?
Here is my onClickListener of the purchase button:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_premium_purchase);
purchase = findViewById(R.id.card_view_premium_purchase);
premiumTextView = findViewById(R.id.premium_purchase_success);
premiumTextView.setVisibility(View.GONE);
purchase.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String username = user.getDisplayName();
DocumentReference userRef = db.collection("User").document(username);
// Set the "pro membership" to true
userRef
.update("pro membership", true).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "DocumentSnapshot successfully updated!");
Toast.makeText(PremiumPurchaseActivity.this, "Guess Premium successfully bought", Toast.LENGTH_SHORT).show();
premiumTextView.setVisibility(View.VISIBLE);
purchase.setVisibility(View.GONE);
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error updating document", e);
}
});
}
});
}
Actually, its very simple all you have to do is get the current value of "pro membership" field from DocumentRefernce and handle UI accordingly in your activity onResume Method.
#Override
public void onResume(){
super.onResume();
String username = user.getDisplayName();
DocumentReference userRef = db.collection("User").document(username);
userRef.get().addOnCompleteListener(new
OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
DocumentSnapshot document = task.getResult();
if (document != null) {
boolean membership = document.getBoolean("pro membership");
if(membership){
premiumTextView.setVisibility(View.VISIBLE);
purchase.setVisibility(View.GONE);
}
} else {
Log.d("LOGGER", "No such document");
}
} else {
Log.d("LOGGER", "get failed with ",
task.getException());
}
}
});
}
I want to give the user in my app the possibility to delete his account so when he clicks on the delete button a document gets deleted which contains all his informations. The name of the document is his displayName so I get this as a string but when I run the code you are seeing below I get a NullpointerException in this line:
String currentUsername = user.getDisplayName();
even though the displayName is not null.
Edit:
I found the solution on my own, see the answer below.
Here is my method:
btn_delete_account.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
user.delete()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
deleteDocument();
}
}
});
}
});
...
public void deleteDocument (){
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String currentUsername = user.getDisplayName();
db.collection("User").document(currentUsername)
.delete()
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "DocumentSnapshot successfully deleted!");
Toast.makeText(PersonalSettings.this, "Your account was successfully deleted.", Toast.LENGTH_SHORT).show();
Intent i = new Intent(PersonalSettings.this, SignInActivity.class);
startActivity(i);
finish();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error deleting document", e);
}
});
}
First thing you have to check that current user is not null
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if(user==null)
{
return;
}
if current user is not null then get its name and further check that it's name is not null.
String currentUsername = user.getDisplayName();
if(TextUtils.isEmpty(currentUsername))
{
return;
}
if name is not null then go for delete document as follows :
public void deleteDocument (){
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if(user==null)
{
return;
}
String currentUsername = user.getDisplayName();
if(TextUtils.isEmpty(currentUsername))
{
return;
}
db.collection("User").document(currentUsername)
.delete()
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Log.d(TAG, "DocumentSnapshot successfully deleted!");
Toast.makeText(PersonalSettings.this, "Dein Account wurde erfolgreich gelöscht.", Toast.LENGTH_SHORT).show();
Intent i = new Intent(PersonalSettings.this, SignInActivity.class);
startActivity(i);
finish();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.w(TAG, "Error deleting document", e);
}
});
}
I think you're misunderstanding the error. It's saying that user is null, not the display name. This means there is currently no user signed into the app. You will have to write some code to check for this case.
I also strongly suggest not using a display name as the ID for a document in Cloud Firestore. Since you're using Firebase Authentication, the user already has a unique ID assigned to their account. This is the preferred way to store per-user data.
I found the error:
I called my delete method after I used the user.delete() method which deletes the signed in user, so logically the displayName was also deleted.
I'm creating an application with which the student will scan the QR code of a class created by a teacher.
After the student scans it, her/his details will store in the class list data. My problem is when I try to change the first name, middle name, and last name, only the first box is updating, while the 2nd and 3rd box are not.
Can someone here please help me?
Here's the code that updates the first box:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String uid = user.getUid();
ref = FirebaseDatabase.getInstance().getReference();
ref.child("users").child("student").child(uid).addListenerForSingleValueEvent(new ValueEventListener() {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String uid = user.getUid();
String newFirstName = oldEmail.getText().toString().trim();
String newMiddleName = middlename.getText().toString().trim();
String newLastName = lastname.getText().toString().trim();
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
ref.child("users").child("student").child(uid).child("firstname").setValue(newFirstName);
ref.child("users").child("student").child(uid).child("middlename").setValue(newMiddleName);
ref.child("users").child("student").child(uid).child("lastname").setValue(newLastName);
progressBar.setVisibility(View.GONE);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(AccountSettingsActivity.this, "Failed to update name!", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
});
Here's the code that updates the second and third boxes:
ref.child("users").child("teacher").child("class").child("Listofstudents").child(user.getUid().toString().trim()).addListenerForSingleValueEvent(new ValueEventListener() {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String uid = user.getUid();
String newFirstName = oldEmail.getText().toString().trim();
String newMiddleName = middlename.getText().toString().trim();
String newLastName = lastname.getText().toString().trim();
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
ref.child("users").child("teacher").child(ref.child("teacher").getKey()).child("class").child(ref.child("class").getKey()).child("Listofstudents").child(user.getUid().toString().trim()).child("firstname").setValue(newFirstName);
ref.child("users").child("teacher").child(ref.child("teacher").getKey()).child("class").child(ref.child("class").getKey()).child("Listofstudents").child(user.getUid().toString().trim()).child("middlename").setValue(newMiddleName);
ref.child("users").child("teacher").child(ref.child("teacher").getKey()).child("class").child(ref.child("class").getKey()).child("Listofstudents").child(user.getUid().toString().trim()).child("lastname").setValue(newLastName);
// TODO: handle the case where the data already exists
}
else {
// TODO: handle the case where the data does not yet exist
}
}
#Override
public void onCancelled(DatabaseError firebaseError) {
Toast.makeText(AccountSettingsActivity.this, "Failed to update name!", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
});
You don't need to add a listener in order to make an update in a Firebase database.
Please see my answer at this post.
Hope it helps.
I have created an app with the database maintaining in Firebase. I have completed the user registration part and here is the coding I used,
if(edtUsrNameS.length() >0 && edtPassS.length() >0 &&edtEmailS.length() >0) {
strUsrS = edtUsrNameS.getText().toString().trim();
strPassS = edtPassS.getText().toString().trim();
strEmailS = edtEmailS.getText().toString().trim();
if(Constant.isValidEmail(strEmailS)){
edtEmailS.setError(null);
Map<String, String> parameters = new HashMap<>();
parameters.put(Constant.TAG_USER, strUsrS.trim());
parameters.put(Constant.TAG_PASS, strPassS.trim());
parameters.put(Constant.TAG_EMAIL, strEmailS.trim());
String pushId = mFirebaseInstance.getReference(Constant.FIREBASE_LOGIN).getRef().push().getKey();
parameters.put(Constant.TAG_KEY, pushId.trim());
mFirebaseInstance.getReference(Constant.FIREBASE_LOGIN).getRef().child(strUsrS.trim()).setValue(parameters);
Toast.makeText(Login_Reg_Activity.this, "Registered Successfully", Toast.LENGTH_SHORT).show();
finish();
Intent inMain = new Intent(Login_Reg_Activity.this, Login_Reg_Activity.class);
startActivity(inMain);
}else{
edtEmailS.setError("Enter a valid Email");
}
}else{
Toast.makeText(Login_Reg_Activity.this, "Fill all detail", Toast.LENGTH_SHORT).show();
}
After the successful registration, the data are stored in the users table in Firebase like this:
My doubt is that how to login using the credential username and mobile. I have tried by the reference link, but I couldn't succeeded. So, my kind request is to direct me to do this. Also, how to restrict the duplication on user registration?
Thanks in advance.
Step 1:
make sure you have enabled the password login in firebase console as shwon below in the picture
Use Below Code For Login with email and Pwd
FirebaseAuth mAuth = FirebaseAuth.getInstance(); // same auth as you used for regestration process
mAuth.signInWithEmailAndPassword("abc#abc.com","pwd")
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful()){
}
}})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(LoginActivity.this, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
}
});
when you get successfully login than auth change listner will be invoke
Auth Change Listner
private FirebaseAuth.AuthStateListener mAuthListener;
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if(user !=null){
}
}
};
mAuth.addAuthStateListener(mAuthListener);
I'm trying to create an profile activity, where users can change those Profile picture and Display name, I'm trying to update user photo or user name, CompleteListener called, task.isSuccessful = true but nathing done, why?
Function to update name:
FirebaseUser mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();
final String newName;
newName = input.getText().toString();
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setDisplayName(newName)
.build();
mFirebaseUser.updateProfile(profileUpdates)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
DatabaseReference mFirebaseDatabaseReference = FirebaseDatabase.getInstance().getReference().child("users");
mFirebaseDatabaseReference.child(mFirebaseUser.getUid()).child("DisplayName").setValue(newName);
updateUI();
Toast.makeText(ProfileActivity.this, "User display name updated.", Toast.LENGTH_SHORT).show();
} else
Toast.makeText(ProfileActivity.this, "Error while updating display name.", Toast.LENGTH_SHORT).show();
}
});
Same when i'm trying to update Profile picture that I just uploaded to Firebase Storage...
And idea?
EDIT:
Sometimes the username really get updated, I think it's take like more then 10 minutes to update, why?
I have had a similar problem where the User information was not updating until the User re-authenticated. I resolved it by also saving this information in my firebase database. For me this made sense, as I wanted Users to be able to get basic information about other Users anyway.
My code ended up looking something like this. When the account is created, or modified, I made a call to the "users/{uid}" endpoint and updated the object there. From here I used the GreenRobot EventBus to send my new User object to whoever was subscribed so that it would be updated on the screen.
private FirebaseUser firebaseUser;
public void createUser(String email, String password, final User user, Activity activity, final View view) {
FirebaseAuth.getInstance().createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(activity, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d(TAG, "createUserWithEmail:onComplete:" + task.isSuccessful());
// If sign in fails, display a messsage to the user. If sign in successful
// the auth state listener will be notified and logic to handle
// signed in user can be handled in the listener
if (!task.isSuccessful()) {
Snackbar.make(view, task.getException().getLocalizedMessage(), Snackbar.LENGTH_SHORT).show();
} else {
firebaseUser = task.getResult().getUser();
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setDisplayName(user.displayName)
.build();
firebaseUser.updateProfile(profileUpdates);
updateDatabase(user);
EventBus.getDefault().post(new LoginEvent());
}
}
});
}
public boolean updateDatabase(User user) {
if (firebaseUser == null) {
Log.e(TAG, "updateDatabase:no currentUser");
return false;
}
return userReference.setValue(user).isSuccessful();
}
The setup of the database watcher was done something like this. Note that you need to make sure that you remove the listener when the User logs out and add a new one when the User logs in.
protected void setupDatabaseWatcher() {
String uid = firebaseUser.getUid();
userReference = FirebaseDatabase.getInstance().getReference("users/" + uid);
userReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
User user = dataSnapshot.getValue(User.class);
Log.d(TAG, "Value is: " + user);
EventBus.getDefault().post(new UserUpdateEvent(user));
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
}
});
}
Use this simple code:
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setDisplayName(newName)
.build();