Patricio Cornejo
Patricio Cornejo

Reputation: 121

firebaseAuth.getCurrentUser() return null DisplayName

When I signIn with my google account and get the name with the getDisplayName(), my name appear correctly, but in the AuthStateListener doesn't.

here part of my code:

private void handleSignInResult(GoogleSignInResult result) {

    Alert.dismissProgress();

    if (result.isSuccess()) {
        GoogleSignInAccount acct = result.getSignInAccount();

        if(acct != null) {
            Log.i("NAME", acct.getDisplayName()); <-- RETURN MY NAME CORRECTLY
            credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
            fuser.linkWithCredential(credential).addOnCompleteListener(authResult);                    
        } else {
            //ERROR
        }

    } else {
        //ERROR
    }
}

But in my AuthStateListener

@Override
    public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
        FirebaseUser nuser = firebaseAuth.getCurrentUser();

        if (nuser != null) {

            Log.i("NAME", nuser.getDisplayName()); <--- RETURN NULL 
        }
    }

Somebody know why this can happen?

Upvotes: 12

Views: 18530

Answers (9)

Edmund Johnson
Edmund Johnson

Reputation: 747

I was getting this problem when I had:

implementation 'com.google.firebase:firebase-auth:10.0.0'
implementation 'com.firebaseui:firebase-ui-auth:1.0.1'

A workaround that fixed it for me was to replace that with:

implementation 'com.google.firebase:firebase-auth:9.6.0'
implementation 'com.firebaseui:firebase-ui-auth:0.6.0'

Iterating through user.getProviderData() as suggested elsewhere didn't fix it for the later versions.

Upvotes: 1

algrid
algrid

Reputation: 5954

Based on Alan's and Ymmanuel's answers here's the 2 helper methods that I'm using:

public static String getDisplayName(FirebaseUser user) {
    String displayName = user.getDisplayName();
    if (!TextUtils.isEmpty(displayName)) {
        return displayName;
    }

    for (UserInfo userInfo : user.getProviderData()) {
        if (!TextUtils.isEmpty(userInfo.getDisplayName())) {
            return userInfo.getDisplayName();
        }
    }

    return null;
}

public static Uri getPhotoUrl(FirebaseUser user) {
    Uri photoUrl = user.getPhotoUrl();
    if (photoUrl != null) {
        return photoUrl;
    }

    for (UserInfo userInfo : user.getProviderData()) {
        if (userInfo.getPhotoUrl() != null) {
            return userInfo.getPhotoUrl();
        }
    }

    return null;
}

Upvotes: 0

Raneez Ahmed
Raneez Ahmed

Reputation: 3828

This issue is resolved in the latest verison of firebase ui compile 'com.firebaseui:firebase-ui:1.2.0'

Upvotes: 2

M&#225;rio Henrique
M&#225;rio Henrique

Reputation: 111

I found a solution for this problem, in the Firebase documentation! The solution is to update the user profile using the: UserProfileChangeRequest:

UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
                      .setDisplayName(mUser.getName())
                      .setPhotoUri(Uri.parse("https://example.com/mario-h-user/profile.jpg"))
                      .build();

            firebaseUser.updateProfile(profileUpdates)
                      .addOnCompleteListener(new OnCompleteListener<Void>() {
                          @Override
                          public void onComplete(@NonNull Task<Void> task) {
                              if (task.isSuccessful()) {
                                  Log.d(TAG, "User profile updated.");
                              }
                          }
                      });

The variable mUser is already filled with the content from the fields. I used this piece of code inside the FirebaseAuth.AuthStateListener() -> onAuthStateChanged()

Upvotes: 2

Equivocal
Equivocal

Reputation: 932

First let me say there's no need to downgrade the Gradle files or logout and login the user multiple times as stated by others just to display the user name. I've solved the issue a different way while still keeping the latest Gradle files and not having to log the user out and in multiple times. The issue with getDisplayName() is a very big one so I want to be as descriptive as possible for future users of Firebase to spare them the headache.

Here are the details of the solution:

Solution 1:

For users who authenticate(sign-in) with multiple providers such as Facebook, Google etc. and/or Email/Password that they created at sign-up:

The first thing you want to ensure is that when you have a user sign-up with the app for the first time you store their name of course to the database under their unique id. Which may look something like this:

// Method signature. Write current user's data to database
private void writeNewUser(String userId, String name, String email) {

DatabaseReference current_user_database = mDatabaseRef.child(userId);

current_user_database.child("username").setValue(name);

// Email here is not mandatory for the solution. Just here for clarity of the
// method signature
current_user_database.child("email").setValue(email);

}

After the user's name has been stored in your Firebase database and you have them sign into your app you can get their username something like this:

// Method that displays the user's username
    private void showUserName() {

        // Get instance of the current user signed-in
        mFirebaseUser = mAuth.getCurrentUser();

        // Check if user using sign-in provider account is currently signed in
        if (mFirebaseUser != null) {


            // Get the profile information retrieved from the sign-in provider(s) linked to a user
            for (UserInfo profile : mFirebaseUser.getProviderData()) {

                    // Name of the provider service the user signed in with (Facebook, Google, Twitter, Firebase, etc.)
                    String name = profile.getDisplayName();


// If displayName() is null this means that the user signed in using the email and password they created. This is the null issue we shouldn't get that we are gonna be solving below. 
                if(name == null){

                    mDatabaseRef.addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {

// Get the name the user signed-up with using dataSnapshot
                            String nameOfCurrentUser = (String) dataSnapshot.child("name").getValue();

// Set username we retrieved using dataSnapshot to the view
                            mTestUsernameTextView.setTitle(nameOfCurrentUser);

                        }

                        @Override
                        public void onCancelled(DatabaseError databaseError) {

                        }
                    });
                }

// If the name is not null that means the user signed in with a social Auth provider such as Facebook, Twitter, Google etc.
                if(name != null) {

                    // Set the TextView (or whatever view you use) to the user's name.
                    mTestUsernameTextView.setText(name);

                }

            } // End for

        } // End if

    }

That's it. Now you just call that method showUserName() or whatever your method is gonna be called inside your onCreate and hopefully this helps.

Solution 2:

For users who sign into your app using ONLY a social media service provider such as Facebook, Twitter, Google or whatever other option Firebase allows:

FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
    for (UserInfo profile : user.getProviderData()) {
        // Id of the provider (ex: google.com)
        String providerId = profile.getProviderId();

        // UID specific to the provider
        String uid = profile.getUid();

        // Name, email address, and profile photo Url
        String name = profile.getDisplayName();
        String email = profile.getEmail();
        Uri photoUrl = profile.getPhotoUrl();
    };
}

That's it for solution 2, just follow the guidelines on Firebase for that and you should be good.

Here's a link to it if you're curious: Get a user's profile information

I truly hope this helps anyone struggling with the getDisplayName() issue.

Conclusion:

If your app only has Facebook, Twitter, Google or whatever else social media sign-in options Firebase provides then just simply calling getDisplayName()method on the currently signed in user should be enough to show their username.

Otherwise if your app allows the user to sign in using an email/password they created then make sure you got their name/username at sign-up so that you can use it later on to display it.

Upvotes: 1

Ojonugwa Jude Ochalifu
Ojonugwa Jude Ochalifu

Reputation: 27256

I had the same issue, I solved it by signing out the user and resigning them back in.

Call FirebaseAuth.getInstance().signOut(); to sign them out, then try again. As I've discovered, this issue is common with using email/password authentication and Social login (Facebook in my case) at the same time.

Upvotes: 3

Android
Android

Reputation: 959

Edmund Johnson is right. This issue was introduced in Firebase Auth 9.8.0. A workaround includes downgrading to 9.6.1 or forcing 're-login' as the info is populated after the user logs out and logs back in. The problem is described in the Firebase issue

It has been reported as a bug to Firebase by one of the Firebase UI contributors - Alex Saveau.

Upvotes: 5

Alan
Alan

Reputation: 1700

Just to add to Ymmanuel's answer (Thank you!) with some example code for anyone else looking for a quick copy and paste:

FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
    // User is signed in              
    String displayName = user.getDisplayName();
    Uri profileUri = user.getPhotoUrl();

    // If the above were null, iterate the provider data
    // and set with the first non null data
    for (UserInfo userInfo : user.getProviderData()) {
        if (displayName == null && userInfo.getDisplayName() != null) {
            displayName = userInfo.getDisplayName();
        }
        if (profileUri == null && userInfo.getPhotoUrl() != null) {
            profileUri = userInfo.getPhotoUrl();
        }
    }

    accountNameTextView.setText(displayName);
    emailTextView.setText(user.getEmail());
    if (profileUri != null) {
        Glide.with(this)
                .load(profileUri)
                .fitCenter()
                .into(userProfilePicture);
    }
}

The above will try to use the first display name and photo url from the providers if it wasn't initially found in the User object.

Bonus: Using glide for images: https://github.com/bumptech/glide .

Upvotes: 9

Ymmanuel
Ymmanuel

Reputation: 2533

This is a tricky one since it is not so clear in the documentation...

Check the getProviderData()

as defined here: https://firebase.google.com/docs/reference/android/com/google/firebase/auth/FirebaseUser#public-method-summary

You can iterate that List and it will have all the providers associated with that account, included a provider with the providerId = "google.com" with a display Name = YOUR_GOOGLE_USERNAME

let me know if you cannot make it work

Upvotes: 9

Related Questions