I'm using Firebase's custom authentication.
I'm trying to set a user's username with:
UserProfileChangeRequest userProfileChangeRequest = new UserProfileChangeRequest.Builder()
.setDisplayName("Hello")
.build();
assert currentUser != null;
currentUser.updateProfile(userProfileChangeRequest).addOnCompleteListener(new OnCompleteListener<Void>() {
#SuppressWarnings("ConstantConditions")
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()){
Toast.makeText(UsernameAndProfilePictureChooserActivity.this, "Success. Username: " + getUsername(), Toast.LENGTH_SHORT).show();
}
else {
throw new Error(task.getException().getMessage(),task.getException().getCause());
}
}
});
But it has no effect.
The Toast message (Toast.makeText(UsernameAndProfilePictureChooserActivity.this, "Success. Username: " + getUsername(), Toast.LENGTH_SHORT).show(); gets called, but getUsername(), which is FirebaseAuth.getInstance().getCurrentUser().getDisplayName() returns null.
Closing the app then re-opening it doesn't work.
Why is this happening?
Try to update the version of your firebase auth library.
I am using com.google.firebase:firebase-auth:10.2.0 and it works for me.
Related
I'm trying to add data to a document to Firebase Firestore. I've added a collection named users to it. Also the read/write permissions are open for now. I'm following this doc. And I'm not able to add data to document.
Here is what I'm trying to do:
private void getNewUserSnapShot() {
FirebaseFirestore db = FirebaseFirestore.getInstance();
FirebaseUser user = firebaseAuth.getCurrentUser();
Log.d(TAG, "getNewUserSnapShot: user_uid: " + user.getUid());
DocumentReference user_doc_ref = db.collection("users").document();
Log.d(TAG, "getNewUserSnapShot: document ref: " + user_doc_ref.getId());
Map<String, Object> user_data = new HashMap<>();
user_data.put("name", user.getDisplayName());
user_data.put("email", user.getEmail());
user_data.put("profile_url", user.getPhotoUrl());
Log.d(TAG, "getNewUserSnapShot: user_data: " + user_data.toString());
user_doc_ref
.set(user_data)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Toast.makeText(LoginActivity.this, task.toString(), Toast.LENGTH_LONG).show();
if (task.isSuccessful()) {
Log.d(TAG, "getNewUserSnapShot: success");
} else {
Log.d(TAG, "getNewUserSnapShot: failed");
}
}
});
}
In Logs I see only these (neither the log for failure nor for success):
2020-03-04 19:48:47.489 30744-30744/com.example.expenditure D/LoginActivity: getNewUserSnapShot: user_uid: iXOzfju6kORnhuUND8zFCPTzxY93
2020-03-04 19:48:47.499 30744-30744/com.example.expenditure D/LoginActivity: getNewUserSnapShot: document ref: 7AluPzcYMLzDKLh8YtBt
2020-03-04 19:48:47.499 30744-30744/com.example.expenditure D/LoginActivity: getNewUserSnapShot: user_data: {profile_url=https://someurl/security/reasons, name=Nikhil Wagh, email=null}
And when I see firebase console, I can't find the document with ID 7AluPzcYMLzDKLh8YtBt, according to logs which should have been created.
There is a similar question: Unable to add information to Cloud Firestore But it doesn't have right answers.
Can someone help. What am I doing wrong?
The issue was user.getPhotoUrl() returns url, but Firestore doesn't support urls. The url needs to be casted as a string, and then it works.
Cast your urls to string before adding data to Firestore.
Ok I am a running into a weird problem with firestore
I have the following structure
collection1 -> document1- >collection2
I am adding a new document to collection2 with on complete listener( I tried the success listener as well). No errors are shown. The new document is not shown on the console. The listener is not being called. However, when I query, I get ALL the added documents including the new ones. What's going on here?
Map<String, Object> data = new HashMap<>();
data.put("completed", true;
data.put("date_completed", new Date());
data.put("location", "123 main st");
data.put("notes", "");
data.put("work", "");
db.collection("collection1").document(document1).collection("collection2")
.add(data)
.addOnCompleteListener(new OnCompleteListener<DocumentReference>() {
#Override
public void onComplete(#NonNull Task<DocumentReference> task) {
if (task.isSuccessful()) {
DocumentReference documentReference = task.getResult();
Log.d(TAG, "DocumentSnapshot written with ID: " + documentReference.getId());
det.setDocId(documentReference.getId());
addr_arr.add(det);
} else {
Log.w(TAG, "Error adding document", task.getException());
Toast.makeText(EditListActivity.this, "Failed operation - " + task.getException().getMessage(),
Toast.LENGTH_SHORT).show();
hideProgressDialog();
}
}
});
Here is the query I do
CollectionReference collecRef = db.collection("collection1").document(document1).collection("collection2");
collecRef.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (DocumentSnapshot document : task.getResult()) {
// here I do document.get on all the fields, add them to object and add object to array
}
adapter.notifyDataSetChanged();
} else {
Log.d(TAG, "get failed with ", task.getException());
Toast.makeText(EditListActivity.this, "Failed operation - " + task.getException(),
Toast.LENGTH_SHORT).show();
hideProgressDialog();
}
}
});
Your app is acting like it's offline or somehow lacking a working internet connection.
When there is no network connection, the Firestore SDK won't fail on writes. It will store the write locally, and eventually sync that to the server. In the meantime, the local write becomes part of any queries, just like if the data was available on the server. So probably what you're seeing is the result of your local write.
(This is the same behavior you would see with Realtime Database.)
As far why the Firestore SDK doesn't have a connection, I don't know. You might have to troubleshoot that on your own.
My Firestore structure looks something like this:
-(coll)users
-(doc)uniqueID
name
email
(coll)clients
-(doc)uniqueID
clientName
clientEmail
What I am trying to achieve is the following:
The user signs in through FirebaseUI Auth flow
If the user (uid recovered from Auth) doesn't exist in firestore db I create a document named by his uid
Once I have the uid I run a query to load clients collection in order to display them into a list using a RecyclerView (if the collection is empty hence the user hasn't created any clients yet I display an empty list screen)
I tried to make a query using the code below as per the documentation:
clientsCollection = db.collection(FIRESTORE_COLLECTION_USERS)
.document(mUid)
.collection(FIRESTORE_COLLECTION_CLIENTS);
clientsCollection
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()){
for (DocumentSnapshot document: task.getResult()){
Log.d(LOG_TAG, document.getId() + " => " + document.getData());
}
} else {
Log.d(LOG_TAG, "error getting documents: ", task.getException());
}
}
});
I get the following RuntimeException:
java.lang.NullPointerException: Provided document path must not be null.
I get this even if the clients collection exits with some documents in it named by unique uid.
Thanks for any clue you could give me! :)
The error message indicates that mUid is null when you run the first statement. Most likely this means that you run this code before the user is signed in.
Make sure that you only call this code after the user has signed in, e.g. from an AuthStateListener.onAuthStateChanged():
FirebaseAuth.getInstance().addAuthStateListener(new AuthStateListener() {
public void onAuthStateChanged(FirebaseAuth auth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
clientsCollection = db.collection(FIRESTORE_COLLECTION_USERS)
.document(user.getUid())
.collection(FIRESTORE_COLLECTION_CLIENTS);
clientsCollection
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()){
for (DocumentSnapshot document: task.getResult()){
Log.d(LOG_TAG, document.getId() + " => " + document.getData());
}
} else {
Log.d(LOG_TAG, "error getting documents: ", task.getException());
}
}
}
}
})
I'm trying to create Change Password feature... but I don't know why getting the error, although I type the correct password. It's always returning failed.
I follow this code from
Manager Users Firebase
and this is my code
edtOldPass = (TextInputLayout) findViewById(R.id.edt_oldpass);
mCurrentUser = FirebaseAuth.getInstance().getCurrentUser();
String email = mCurrentUser.getEmail();
String pass = edtOldPass.getEditText().toString();
AuthCredential credential = EmailAuthProvider.getCredential(email, pass);
mCurrentUser.reauthenticate(credential).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Intent newpassIntent = new Intent(ReAuthActivity.this, ChangePassActivity.class);
startActivity(newpassIntent);
} else {
Toast.makeText(ReAuthActivity.this, "Incorrect Password", Toast.LENGTH_SHORT).show();
}
}
});
This code to get the password is not correct:
String pass = edtOldPass.getEditText().toString();
Calling getEditText() on a TextInputLayout returns the contained EditText widget, not the string value of the EditText.
Change it to this:
String pass = edtOldPass.getEditText().getText().toString();
private void registerUser(){
String emailId = email.getText().toString().trim().toLowerCase();
String password = pass.getText().toString().trim();
firebaseAuth.createUserWithEmailAndPassword(emailId,password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
progressDialog.dismiss();
if(task.isSuccessful()){
Toast.makeText(MainActivity.this,"Registration Successful",Toast.LENGTH_SHORT).show();
//show chatroom
finish();
startActivity(new Intent(getApplicationContext(),ProfileActivity.class));
}
else{
Toast.makeText(MainActivity.this,"Registration Failed. Please try again",Toast.LENGTH_SHORT).show();
}
}
});
}
I wish to add a username or display name to it but am unable to do so. I tried a few things but still no result. Kindly help me. I need this functionality for a project submission this week.
This is definitely possibly but just not in the user creation method.
Once you've created your user (possibly in the addOnSuccessListener) you can use something similar to the following code to update the Users DisplayName:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder().setDisplayName("John Smith").build();
user.updateProfile(profileUpdates);
Hope this helps!
Edit: I previously said to add the code to the AuthStateListener, however, Frank's suggestion below to put it in the addOnSuccessListener is better/makes more sense so I have updated the answer to reflect this.
I just recently investigated this issue for my own implementation (SDK version 4.4.1). What I've found is that it works perfectly if you are sure to utilize the exact same task.result object from registration/login and not the object from the default instance.
Another work around that helped me is to have an email reference table in your FB DB like this:
{ "EmailRef": { "username1" : "email# domain .com"}, {"username2" : "email2#domain.com"} }
And then to query for the username by the user's email (from auth.CurrentUser.Email) using a method like this:
public static void GetCurrentUserName(Firebase.Auth.FirebaseUser user)
{
string message = "";
DatabaseReference dbRef = FbDbConnection();
FirebaseDatabase.DefaultInstance.GetReference("EmailRef").OrderByValue().EqualTo(user.Email).GetValueAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
message = "GetCurrentUserName encountered an error: " + task.Exception;
ModalManager.BuildFireBaseDebugModal(message);
Debug.LogError(message);
return;
}
if (task.IsCanceled)
{
message = "GetCurrentUserName was canceled.";
Debug.LogError(message);
return;
}
if (task.IsCompleted)
{
foreach (DataSnapshot ss in task.Result.Children.AsEnumerable())
{
try
{
if (ss.Value != null)
{
if (ss.Value.ToString() == user.Email)
{
message = "GetCurrentUserName was successful -- Email: " + user.Email + " Username: " + user.DisplayName;
Debug.LogError(message);
}
}
return;
}
catch (Exception ex)
{
message = "GetCurrentUserName Exception: " + ex;
Debug.LogError(message);
return;
}
}
}
});
}