How to add DisplayName with email + password authentication in Firebase? Android - android

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;
}
}
}
});
}

Related

Sign in With Apple - Android Implementation with Firebase

setting up the Android Firebase on Android.
I need to get the unique identifier of the user, so that I can have consistency accross all platforms no matter if the email is hided or not.
Based upon https://firebase.google.com/docs/auth/android/apple , using .startActivityForSignInWithProvider(this, provider.build()) we can see:
public void onSuccess(AuthResult authResult) {
Log.d(TAG, "checkPending:onSuccess:" + authResult);
// Get the user profile with authResult.getUser() and
// authResult.getAdditionalUserInfo(), and the ID
// token from Apple with authResult.getCredential().
And from Apple https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/authenticating_users_with_sign_in_with_apple#3383773 we can also see
The identity token is a JSON Web Token (JWT) and contains
and
sub
The subject registered claim identifies the principal that’s the subject of the identity token. Because this token is for your app, the value is the unique identifier for the user.
Question:
What I got from firebase is AuthCredential , but I am expecting JWT with "sub" in it.
How can I get it?
thanks to Ricardo from Firebase support I got this working.
in Android the sub value from Apple is in
"firebase":{"identities":{"apple.com":["001814.24f212edfsdfdfsfd69b7b5fee972e.1722"],"email":["a#b.com"]},"sign_in_provider":"apple.com"}
You get it using
auth.startActivityForSignInWithProvider(this, provider.build()).addOnSuccessListener( new OnSuccessListener<AuthResult>() {
#Override
public void onSuccess(AuthResult authResult) {
// Sign-in successful!
FirebaseUser user = authResult.getUser();
AuthCredential identityToken = authResult.getCredential();
authResult.getUser().getIdToken(false).addOnSuccessListener(new OnSuccessListener<GetTokenResult>() {
#Override
public void onSuccess(GetTokenResult result) {
String idToken = result.getToken();
//Do whatever
Log.d(TAG, "GetTokenResult result = " + idToken);
try {
decodeJWT(idToken);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
})
Where the JWT is decoded with
private static void decodeJWT(String JWTEncoded) throws Exception {
try {
String[] split = JWTEncoded.split("\\.");
Log.d("JWT_DECODED", "Header: " + getJson(split[0]));
Log.d("JWT_DECODED", "Body: " + getJson(split[1]));
} catch (UnsupportedEncodingException e) {
//Error
}
}
private static String getJson(String strEncoded) throws UnsupportedEncodingException{
byte[] decodedBytes = Base64.decode(strEncoded, Base64.URL_SAFE);
return new String(decodedBytes, "UTF-8");
}

Unable to add data to document in firestore (Android)

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.

Firestore : query all documents from a collection

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());
}
}
}
}
})

Re-authenticate failed Firebase Android

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();

Firebase setDisplayName has no effect

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.

Categories

Resources