I am trying to create a very simple login with Facebook using firebase and android studio. My login with Facebook works and I was able to run the app and sign in but none of my info has been stored in firebase (I want to have the persons name, email, etc.) I know it's something small I am probably missing but I cannot figure it out and I have tried so many things. Also I checked and all my gradle files are up to date and my firebase is set up correctly so it has nothing to do with that. plz help.
firebaseAuth = FirebaseAuth.getInstance();
firebaseAuthListner = new FirebaseAuth.AuthStateListener(){
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if(user != null){
// what do i put here to pull out the fb users info into firebase?!
goMainScreen();
}
}
};
I have tried:
if(user != null){
String name = user.getDisplayName();
String email = user.getEmail();
String uid = user.getUid();
I have tried:
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
I know it is probably a dumb mistake because I am new to firebase and android studio but any advice will help. Thank you
Are your user stored into the firebase console? (https://console.firebase.google.com)
If it is not stored in your project, it will not return anything when you call the getDisplayName(), getUser(), etc.
If they are stored, please post the complete code that you are using to do the login.
Related
I am a Unity programmer and I am using Firebase to manage user accounts. I tried to set up Facebook Login. No problems with the Facebook sdk and I can log in successfully. However, when the credential returned by Facebook sdk is used as a parameter of FirebaseAuth.DefaultInstance.SignInWithCredentialAsync, it returns internal error.
And here is my code:
void authCallBack(IResult result) {
if (result.Error != null) {
Debug.Log(result.Error);
}
else {
if (FB.IsLoggedIn) {
Debug.Log("Log in successfully.");
AccessToken token = AccessToken.CurrentAccessToken;
Credential credential = FacebookAuthProvider.GetCredential(token.TokenString);
accessToken(credential);
}
else
Debug.Log("not logged in");
}
}
public void accessToken(Credential firebaseResult) {
FirebaseAuth auth = FirebaseAuth.DefaultInstance;
Debug.Log("Auth CurrentUser: " + FirebaseAuth.DefaultInstance.CurrentUser);
if (!FB.IsLoggedIn){
return;
}
if (auth.CurrentUser != null && !string.IsNullOrEmpty(auth.CurrentUser.UserId)){
Debug.Log("CurrentUser ID: " + auth.CurrentUser.UserId);
auth.CurrentUser.LinkAndRetrieveDataWithCredentialAsync(firebaseResult).ContinueWith(task =>
{
if (task.IsCanceled || task.IsFaulted)
{
Debug.LogError("LinkWithCredentialAsync encountered an error: " + task.Exception);
// TODO: Show error message to player
return;
}
FirebaseUser newUser = task.Result.User;
Debug.LogFormat("Credentials successfully linked to Firebase user: {0} ({1})",
newUser.DisplayName, newUser.UserId);
});
} else {
auth.SignInWithCredentialAsync(firebaseResult).ContinueWith(task =>
{
if (task.IsCanceled || task.IsFaulted) {
Debug.LogError("SignInWithCredentialAsync encountered an error: " + task.Exception.InnerExceptions[0].Message);
// TODO: Show error message to player
return;
}
FirebaseUser newUser = task.Result;
Debug.LogFormat("Credentials successfully created Firebase user: {0} ({1})",
newUser.DisplayName, newUser.UserId);
});
}
}
More details in VS Debugging:
When I test it on my Android device, it comes out an error message g_methods_cached only.
Can anyone help?
P.S. Here is another question asked yesterday and I don't know if it is relevant.
FirebaseAuthWebException not found. Please verify the AAR
Oh, I have made a silly mistake!
In the Facebook Developer page, there is the App Secret in Setting > Basic. And it has to be added into Firebase Console with the App ID. No problem right now. And then......
I just copied the App Secret without showing and pasted into Firebase Console.
Which means I have set 8 black dots (●●●●●●●●) as my App Secret in my Firebase Console. I know it is too silly. But just in case there is someone careless like me.
Does anyone know how to include user photoUrl from firebase Google auth when post an article? NB: I use glide for displaying my google photourl
Google auth provider supplies the user's displayName, email and photoUrl. Anytime after you've authenticated with Google you can do this:
ImageView photoImageView;
FirebaseUser firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
if (firebaseUser != null && firebaseUser.getPhotoUrl() != null) {
Glide.with(this).load(firebaseUser.getPhotoUrl()).into(photoImageView);
}
I am currently working on an app using android studio and currently have a working login using Firebase user authentication. However, I am trying to have an image appear on the screen when the user logs after using this authentication. I want this image to be linked to that specific user. Is this possible?
You can set a photo url on a user's firebase profile with the following code:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setDisplayName("Jane Q. User")
.setPhotoUri(Uri.parse("https://example.com/jane-q-user/profile.jpg"))
.build();
user.updateProfile(profileUpdates)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User profile updated.");
}
}
});
You would then retrieve the user's profile information (including their photo URL) like so:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
// Name, email address, and profile photo Url
String name = user.getDisplayName();
String email = user.getEmail();
Uri photoUrl = user.getPhotoUrl();
// Check if user's email is verified
boolean emailVerified = user.isEmailVerified();
// The user's ID, unique to the Firebase project. Do NOT use this value to
// authenticate with your backend server, if you have one. Use
// FirebaseUser.getToken() instead.
String uid = user.getUid();
}
More info: https://firebase.google.com/docs/auth/android/manage-users
If you're using oAuth authentication and want to retrieve their profile photo from facebook, you'll find more information about how to do that at the link below:
https://firebase.google.com/docs/auth/android/facebook-login
I am developing an Android App using Firebase, In my app I am using Firebase Anonymous Login and Google sign In.
When the application starts if the user is not Logged In, then I am using Anonymous Authentication to log the user in.
Afterwards when user chooses to Sign In using Google, then I am converting Anonymous Account to a permanent account.
My issue over here is, When user's account is converted from Anonymous Account to permanent account (using Google Sign In in this case), I am not getting User's Display Name and Photo Url.
For converting from Anonymous Account to permanent account I am using below code.
AuthCredential credential = GoogleAuthProvider.getCredential(googleIdToken, null);
mAuth.getCurrentUser().linkWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d(TAG, "linkWithCredential:onComplete:" + task.isSuccessful());
if (!task.isSuccessful()) {
Toast.makeText(AnonymousAuthActivity.this, "Authentication failed.",Toast.LENGTH_SHORT).show();
//If Google Account already linked up with other UID
Tasks.await(mAuth.signInWithCredential(credential)).getUser();
}
}
});
After the Sign In process completes, the AuthStateListener onAuthStateChanged is called, Then in onAuthStateChanged I am extracting User's Display Name, User's Photo Url and User's Email. Below is the onAuthStateChanged code.
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null && !(user.isAnonymous())) {
Log.d("userDetails", "UID: " + user.getUid());
Log.d("userDetails", "Name: " + user.getDisplayName());
Log.d("userDetails", "PhotoUrl: " + user.getPhotoUrl().toString());
Log.d("userDetails", "Email: " + user.getEmail());
}
In the log I am getting null for user.getDisplayName() and user.getPhotoUrl()
I don't understand what I am doing wrong. Please help.
Thanks & Regards,
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
user.getProviderData();
loop through providers and get the desired provider
userData.getProviderId().equals(GoogleAuthProvider.PROVIDER_ID)
Uri photoUrl = userData.getPhotoUrl();
When linking accounts (or even on every sign in), call this function
Future<void> updateMissingUserPropertise(User user) async {
if (user.photoURL == null) await user.updatePhotoURL(user.providerData[0].photoURL);
if (user.displayName == null) await user.updateDisplayName(user.providerData[0].displayName);
}
In order to support multiple providers, each of which might hold a different name, photo, or phone number, Firebase auth does not modify the user properties when linking accounts.
Even if the user signs out later and signs in with Google, or any other federated account, it does not change the user properties.
The function above 'fixes' the missing user properties by grabbing them from the first provider, which is Google in your case, and setting them in the user properties for good.
The more complex version of this function, which supports the case of multiple providers, loops through the providers until a DisplayName or a photoURL are found.
Future<void> updateMissingUserPropertise(User user) async {
if (user.photoURL == null) {
user.providerData.forEach((provider) async {
if (provider.photoURL != null) {
await user.updatePhotoURL(provider.photoURL);
return;
}
});
}
if (user.displayName == null) {
user.providerData.forEach((provider) async {
if (provider.displayName != null) {
await user.updateDisplayName(provider.displayName);
return;
}
});
}
}
I am using FirebaseAuth to login user through FB. Here is the code:
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private CallbackManager mCallbackManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FacebookSdk.sdkInitialize(getApplicationContext());
// Initialize Firebase Auth
mAuth = FirebaseAuth.getInstance();
mAuthListener = firebaseAuth -> {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
if (user != null) {
Log.d(TAG, "User details : " + user.getDisplayName() + user.getEmail() + "\n" + user.getPhotoUrl() + "\n"
+ user.getUid() + "\n" + user.getToken(true) + "\n" + user.getProviderId());
}
};
}
The issue is that the photo in I get from using user.getPhotoUrl() is very small. I need a larger image and can't find a way to do that. Any help would be highly appreciated.
I have already tried this
Get larger facebook image through firebase login
but it's not working although they are for swift I don't think the API should differ.
It is not possible to obtain a profile picture from Firebase that is larger than the one provided by getPhotoUrl(). However, the Facebook graph makes it pretty simple to get a user's profile picture in any size you want, as long as you have the user's Facebook ID.
String facebookUserId = "";
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
ImageView profilePicture = (ImageView) findViewById(R.id.image_profile_picture);
// find the Facebook profile and get the user's id
for(UserInfo profile : user.getProviderData()) {
// check if the provider id matches "facebook.com"
if(FacebookAuthProvider.PROVIDER_ID.equals(profile.getProviderId())) {
facebookUserId = profile.getUid();
}
}
// construct the URL to the profile picture, with a custom height
// alternatively, use '?type=small|medium|large' instead of ?height=
String photoUrl = "https://graph.facebook.com/" + facebookUserId + "/picture?height=500";
// (optional) use Picasso to download and show to image
Picasso.with(this).load(photoUrl).into(profilePicture);
Two lines of code. FirebaseUser user = firebaseAuth.getCurrentUser();
String photoUrl = user.getPhotoUrl().toString();
photoUrl = photoUrl + "?height=500";
simply append "?height=500" at the end
If someone is looking for this but for Google account using FirebaseAuth. I have found a workaround for this. If you detail the picture URL:
https://lh4.googleusercontent.com/../.../.../.../s96-c/photo.jpg
The /s96-c/ specifies the image size (96x96 in this case)so you just need to replace that value with the desired size.
String url= FirebaseAuth.getInstance().getCurrentUser().getPhotoUrl();
url = url.replace("/s96-c/","/s300-c/");
You can analyze your photo URL to see if there is any other way to change its size.
As I said in the begining, this only works for Google accounts. Check #Mathias Brandt 's answer to get a custom facebook profile picture size.
EDIT 2020:
Thanks to Andres SK and #alextouzel for pointing this out. Photo URLs format have changed and now you can pass URL params to get different sizes of the picture. Check https://developers.google.com/people/image-sizing.
photoUrl = "https://graph.facebook.com/" + facebookId+ "/picture?height=500"
You can store this link to firebase database with user facebookId and use this in app.
Also you can change height as a parameter
Not for Android, but for iOS, but I thought it could be helpful for other people (I didn't find a iOS version of this question).
Based the provided answers I created a Swift 4.0 extension that adds a function urlForProfileImageFor(imageResolution:) to the Firebase User object. You can either ask for the standard thumbnail, a high resolution (I put this to 1024px but easily changed) or a custom resolution image. Enjoy:
extension User {
enum LoginType {
case anonymous
case email
case facebook
case google
case unknown
}
var loginType: LoginType {
if isAnonymous { return .anonymous }
for userInfo in providerData {
switch userInfo.providerID {
case FacebookAuthProviderID: return .facebook
case GoogleAuthProviderID : return .google
case EmailAuthProviderID : return .email
default : break
}
}
return .unknown
}
enum ImageResolution {
case thumbnail
case highres
case custom(size: UInt)
}
var facebookUserId : String? {
for userInfo in providerData {
switch userInfo.providerID {
case FacebookAuthProviderID: return userInfo.uid
default : break
}
}
return nil
}
func urlForProfileImageFor(imageResolution: ImageResolution) -> URL? {
switch imageResolution {
//for thumnail we just return the std photoUrl
case .thumbnail : return photoURL
//for high res we use a hardcoded value of 1024 pixels
case .highres : return urlForProfileImageFor(imageResolution:.custom(size: 1024))
//custom size is where the user specified its own value
case .custom(let size) :
switch loginType {
//for facebook we assemble the photoUrl based on the facebookUserId via the graph API
case .facebook :
guard let facebookUserId = facebookUserId else { return photoURL }
return URL(string: "https://graph.facebook.com/\(facebookUserId)/picture?height=\(size)")
//for google the trick is to replace the s96-c with our own requested size...
case .google :
guard var url = photoURL?.absoluteString else { return photoURL }
url = url.replacingOccurrences(of: "/s96-c/", with: "/s\(size)-c/")
return URL(string:url)
//all other providers we do not support anything special (yet) so return the standard photoURL
default : return photoURL
}
}
}
}
Note: From Graph API v8.0 you must provide the access token for every UserID request you do.
Hitting the graph API:
https://graph.facebook.com/<user_id>/picture?height=1000&access_token=<any_of_above_token>
With firebase:
FirebaseUser user = mAuth.getCurrentUser();
String photoUrl = user.getPhotoUrl() + "/picture?height=1000&access_token=" +
loginResult.getAccessToken().getToken();
You get the token from registerCallback just like this
LoginManager.getInstance().registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
FirebaseUser user = mAuth.getCurrentUser();
String photoUrl = user.getPhotoUrl() + "/picture?height=1000&access_token=" + loginResult.getAccessToken().getToken();
}
#Override
public void onCancel() {
Log.d("Fb on Login", "facebook:onCancel");
}
#Override
public void onError(FacebookException error) {
Log.e("Fb on Login", "facebook:onError", error);
}
});
This is what documentation says:
Beginning October 24, 2020, an access token will be required for all
UID-based queries. If you query a UID and thus must include a token:
use a User access token for Facebook Login authenticated requests
use a Page access token for page-scoped requests
use an App access token for server-side requests
use a Client access token for mobile or web client-side requests
We recommend that you only use a Client token if you are unable to use
one of the other token types.
I use this code in a Second Activity, after having already logged in, for me the Token that is obtained in loginResult.getAccessToken().getToken(); It expires after a while, so researching I found this and it has served me
final String img = mAuthProvider.imgUsuario().toString(); // is = mAuth.getCurrentUser().getPhotoUrl().toString;
final String newToken = "?height=1000&access_token=" + AccessToken.getCurrentAccessToken().getToken();
Picasso.get().load(img + newToken).into("Image reference");
Check below response
final graphResponse = await http.get(
'https://graph.facebook.com/v2.12/me?fields=name,picture.width(800).height(800),first_name,last_name,email&access_token=${fbToken}');