First time developing an Android application. Im trying to get the user register in our Firebase when sign in with FaceBook and Google.
So far I have the login with email and password.
Sign-in with Facebook and Google.
The question is: Do you have to register the user in firebase (when sign-in from google and facebook) to be able to create a profile for example with a picture?
This scope of the code is been implemented on a Fragment on our project:
onCreateView
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.google_credential))
.requestEmail()
.build();
//
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.enableAutoManage(getActivity(), new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
})
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
Outside of onCreateView
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
try {
// Google Sign In was successful, authenticate with Firebase
GoogleSignInAccount account = task.getResult(ApiException.class);
firebaseAuthWithGoogle(account);
} catch (ApiException e) {
// Google Sign In failed, update UI appropriately
Log.w(TAG, "Google sign in failed", e);
// ...
}
}
}
private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
Log.d("MainACtivity", "firebaseAuthWithGoogle:" + acct.getId());
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
firebaseAuth.signInWithCredential(credential)
.addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d("Main", "signInWithCredential:onComplete:" + task.isSuccessful());
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Log.w("MainAcitivyt", "signInWithCredential", task.getException());
Toast.makeText(getActivity(), "Authentication failed.",
Toast.LENGTH_SHORT).show();
}
// ...
}
});
}
I followed FireBase guides on Signup with google: https://firebase.google.com/docs/auth/android/google-signin
After a user signs in for the first time, a new user account is created and linked to the credentials—that is, the user name and password, phone number, or auth provider information—the user signed in with. This new account is stored as part of your Firebase project, and can be used to identify a user across every app in your project, regardless of how the user signs in.
This is copied after the guide, Im just trying to find any google account on firebase that I have signed-up with in my application.
EDIT:
Find out that my application have an error when signin up with google:
here the logcat:
2019-03-13 11:29:25.729 10997-10997/com.itcom202.weroom W/LoginFragment: Google sign in failed
com.google.android.gms.common.api.ApiException: 10:
at com.google.android.gms.common.internal.ApiExceptionUtil.fromStatus(Unknown Source:4)
at com.google.android.gms.auth.api.signin.GoogleSignIn.getSignedInAccountFromIntent(Unknown Source:8)
at com.itcom202.weroom.LoginFragment.onActivityResult(LoginFragment.java:194)
at android.support.v4.app.FragmentActivity.onActivityResult(FragmentActivity.java:160)
at android.app.Activity.dispatchActivityResult(Activity.java:7235)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4320)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4367)
at android.app.ActivityThread.-wrap19(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Things to consider when coding the Firebase Sign-In Auth
Follow the process covered in their Github repo and you can look at a few working sample activities in the Firebase Quick Start Github repo.
You'll also need to enable Facebook and Google Sign-In in your Firebase Console. Another important point is to make sure you are using the freshest google-services.json file every time you make a change with your Firebase Console.
Finally, make sure you have the required debug and release SHA1 fingerprints setup with you Firebase project in the Firebase Console to connect with the Firebase service when your app goes on Play store.
Accessing your Firebase Registered User Accounts
Log Into You Firebase Console.
Go to your Firebase Project and select Authentication in the left-hand side menu.
It will show a Users Tab with usernames, ids and authentication details.
For more look into Firebase documentation online.
Do you have to register the user in firebase (when sign-in from google
and facebook) to be able to create a profile for example with a
picture?
For Google Sing-In, the profile image from Google Account and some more metadata is available that can be used.
The Google Sign-In method and Facebook Sign-In method examples on Github Quickstart automatically add new users if they're signing for the first time into the Firebase project. You can try adding a new user and see it being added on your Firebase Authentication Users tab. Seen Below:
You can also give users the ability to sign out and delete their sign in accounts, also covered in the documentation and Github samples.
Related
I've implemented Google Play Game Services to my app. However when I call the interactive sign-in when silent sign in fails, the app asks permissions:
When I turn on the silent sign in for my account it works properly. However with the interactive sign-in those permissions are asked and user needs to press allow.
I want it to sign in after choosing the account and not to ask permissions.
My code:
private void signIn() {
GoogleSignInOptions signInOptions = GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN;
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(context);
if (GoogleSignIn.hasPermissions(account, signInOptions.getScopeArray())) {
// Already signed in.
// The signed in account is stored in the 'account' variable.
GoogleSignInAccount signedInAccount = account;
} else {
// Haven't been signed-in before. Try the silent sign-in first.
GoogleSignInClient signInClient = GoogleSignIn.getClient(context, signInOptions);
signInClient.silentSignIn().addOnCompleteListener(context, new OnCompleteListener<GoogleSignInAccount>() {
#Override
public void onComplete(#NonNull Task<GoogleSignInAccount> task) {
if (task.isSuccessful()) {
// The signed in account is stored in the task's result.
GoogleSignInAccount signedInAccount = task.getResult();
} else {
Intent intent = signInClient.getSignInIntent();
startActivityForResult(intent, RC_SIGN_IN);
// Player will need to sign-in explicitly using via UI.
// See [sign-in best
// practices](http://developers.google.com/games/services/checklist) for
// guidance on how and when to implement Interactive Sign-in,
// and [Performing Interactive
// Sign-in](http://developers.google.com/games/services/android/signin#performing_interactive_sign-in)
// for details on how to implement
// Interactive Sign-in.
}
}
});
}
}
In an Android application, I follow dev guides to sign-in, silentSignIn, and [signout] https://developers.google.com/identity/sign-in/android/disconnect a google account. Everything works fine for sign-in flows: after the first sign-in, the app can silentSignIn successfully and retrieve user account data.
My question raises after a successful signout: I expect silentSignIn should FAIL to require users sign-in manually again. I think that is what the dev guide in the above link meant in "...sign out of your app, and to disconnect their accounts from your app entirely". However, silentSignIn still succeeds and user account data (ex: email, profile data, etc.) can be retrieved as if the user never signs out. I am sure silentSignIn will fail after revoking access instead of signout, but then what signout is for.
Does anyone experience the same issue? Would anyone please share comments and experience on my concern? Thanks in advance.
public static GoogleSignInOptions getGSignInOptions(){
return new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestScopes(new Scope(DriveScopes.DRIVE_APPDATA))
.requestEmail()
.requestProfile()
.build();
}
// below code is excerpted from an activity
protected void signInSilently() {
Log.d(TAG, "signInSilently");
try {
GoogleSignInClient gClient = GoogleSignIn.getClient(this, getGSignInOptions());
gClient.silentSignIn().addOnCompleteListener(this,
task -> {
if (task.isSuccessful()) {
mGAccount = task.getResult();
Log.d(TAG, "signInSilently: success on " + mGAccount == null ? "" : mGAccount.getEmail());
}
});
} catch (Exception ex){
Log.e(TAG, "signInSilently: " + ex.getMessage());
handleSignInException(ex);
}
}
protected void signOut() {
Log.d(TAG, "signOut");
GoogleSignInClient gClient = GoogleSignIn.getClient(this, getGSignInOptions());
gClient.signOut().addOnCompleteListener(this,
task -> {
if (task.isSuccessful()) {
mGAccount = null;
Log.d(TAG, "signOut: success");
} else {
handleException(task.getException(), "signOut: failed!");
}
});
}
I saw a similar question on Google OAuth for web and a reasonable answer on its signout behavior from the same site and Google docs for developers: signout is designed for users to sign out of your app without signing out of Google.
Thus, apps should not call sign-in, even silentSignIn, at every launch. Instead, apps should call GoogleSignIn.getLastSignedInAccount to check if the user has signed in successfully previously. If there is no prior signin account or the returned account was granted insufficient permissions on required scopes for the app, then it's time for silentSignIn to be tried.
So it's time to close my own question: what signout is for? After a successful signout, GoogleSignIn.getLastSignedInAccount return null and the app can fall back to sign-in flows.
I am developing an application in which am using firebase PhoneAuthCredential and Google sign-in (linked) to sign in a user so that user can sign in with either phone number or google sign-in.
First, phone number is verified via otp then in next step phone auth is linked with google account (till here everything works fine, I'm able to link accounts).
Problem arises when I try to use firebaseAuth.getInstance().getCurrentUser().getDisplayName(), it return me null
I don't know what's going wrong as I am able to get display name when user is first signed with google sign-in then linked to phone number.
Thanks in advance!
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess()) {
// Google Sign In was successful, authenticate with Firebase
GoogleSignInAccount account = result.getSignInAccount();
firebaseAuthWithGoogle(Objects.requireNonNull(account));
Toast.makeText(this, ""+account.getDisplayName()+" "+account.getPhotoUrl(), Toast.LENGTH_SHORT).show(); //here getting display name
} else {
// Google Sign In failed, update UI appropriately
Toast.makeText(PhoneToGoogle.this, "It seems like you have cancelled Google Authentication!", Toast.LENGTH_LONG).show();
}
}
}
private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
Objects.requireNonNull(mAuth.getCurrentUser()).linkWithCredential(credential) //linking with phoneAuth
.addOnCompleteListener(PhoneToGoogle.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
saveUserProfileDataInFirebaseDataBase(Objects.requireNonNull(task.getResult()).getUser());
Toast.makeText(PhoneToGoogle.this, "linked", Toast.LENGTH_SHORT).show();
} else {
// If sign in fails, display a message to the user.
showSignInFailedMessage((Objects.requireNonNull(task.getException())).getLocalizedMessage());
}
}
});
}
private void saveUserProfileDataInFirebaseDataBase(final FirebaseUser user){
databaseReference.child(user.getUid()).child(NAME).setValue(user.getDisplayName());
//here getting display name null
}
It sounds like you're expecting the Google account user name to override the phone auth user name that was originally associated with the Firebase account. It turns out that it doesn't work this way. When an account is first created, it inherits the user information from the provider that was used to verify their identity. In the case of phone auth coming first, no name is known, so the account gets null. This value persists until you write code to change it.
After initial phone auth, if any other account is linked to the original Firebase auth user, it does not inherit the user info from the linked account.
If you go the other direction - Google auth followed by phone auth, the null name from the phone auth account doesn't overwrite the name obtained from Google.
I have an Android game that uses Play Games Services. Play Games Services appear to be linked to a specific Google Login. If a player starts the game, it is automatically logged into Play Games.
Now I wish to incorporate Firebase into my game as well, for example to facilitate chat.
How can I use the Play Games user account to create/login to a Firebase account?
Is there some sort of token Play Games gives me I can just pass onto Firebase?
I am trying to avoid having to use my own backend server, and avoid having the user having to sign in twice in my game, since that is a rather poor user experience.
What are my options? I'm rather stumped on how to approach this.
-- SOLVED --
First of all I needed to enable Google Signin from the Firebase auth tab.
Then I used this code in my base activity:
private FirebaseAuth mAuth;
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestIdToken("<appidfromfirebase>.apps.googleusercontent.com")
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, this)
.addConnectionCallbacks(this)
.addApi(Games.API)
.addScope(Games.SCOPE_GAMES)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
#Override
public void onConnected(Bundle connectionHint) {
if (mGoogleApiClient.hasConnectedApi(Games.API)) {
Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient).setResultCallback(
new ResultCallback<GoogleSignInResult>() {
#Override
public void onResult(GoogleSignInResult googleSignInResult) {
GoogleSignInAccount acct = googleSignInResult.getSignInAccount();
if (acct == null) {
Logger.e("account was null: " + googleSignInResult.getStatus().getStatusMessage());
return;
}
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(),null);
mAuth.signInWithCredential(credential)
.addOnCompleteListener(
new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
// check task.isSuccessful()
}
});
}
}
);
}
}
You need to use the id token for the user to link the Google identity to the Firebase Authentication.
Build the Google API client with the games config, requesting an ID token.
GoogleSignInOptions options = new GoogleSignInOptions
.Builder(GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN)
.requestIdToken(firebaseClientId)
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Games.API)
.addApi(Auth.GOOGLE_SIGN_IN_API, options)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
Then launch the SignIn Intent:
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
And when the result is returned, get the id token and pass it to Firebase.Auth:
#Override
protected void onActivityResult(int requestCode, int responseCode,
Intent intent) {
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result =
Auth.GoogleSignInApi.getSignInResultFromIntent(intent);
if (result.isSuccess()) {
AuthCredential credential = GoogleAuthProvider.getCredential(
acct.getIdToken(), null);
FirebaseAuth.getInstance().signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
}
});
}
}
}
Your logged-in Google account in your Android device is usually the one linked with your GPGS profile.
Now to answer your question, follow the Integrate With Your Play Games Services Project guide on how to use Firebase with GPGS.
When you add Firebase to your Play Game Services project in the Play
Developer console, you can:
Get access to Firebase Analytics, a free app measurement solution that
provides insight on app usage and user engagement. View your Games
events in the Firebase Analytics by logging Play Games events to
Firebase.
When you add Firebase to your Play Games Services project, you’re also
linking your Google Play Account to your Firebase
project.
Add Firebase to your Play Games Services project
In the Play Developer Console:
Click Add Firebase on the Game details page of your app Review the
policy confirmation, then click Confirm Now Firebase is added to your
Play Games Project and your Google Play account is linked to your
Firebase project. Next, you will need to add the Firebase SDK to your
app's code.
Add the Firebase SDK to your app
To get started, add Firebase Analytics to your app.
Once you have added the Firebase Analytics SDK to your app, you can
begin logging Play Games events.
I have implemented Google Signing for Android app. The user can successfully login from the Google Login Button.
This screen appears while selecting a Social Account: Screenshot
So now the user has logged in successfully by selecting his/her account.
Now, user logs out, and tries to sign in again by using Google Login Button.
At this time, he is not asked with the option to choose account, he is automatically logged in using the account he/she selected at the first time.
At the time of logout what should I do to clear the cache of selected account.
In firebase documentation for android, they only refer to use this:
Firebase.auth.signOut()
However, next time the user logs in, the app will automatically select the previous email. To avoid this, you should use the follow code as well:
googleSignInClient.signOut()
As you didn't provide any code or reference how you are logging in and logging out, it might be that you incorrectly sign out user from the app.
So here is what docs describe one should do on user logout:
https://developers.google.com/identity/sign-in/android/disconnect
Sign out:
Auth.GoogleSignInApi.signOut(mGoogleApiClient).setResultCallback(
new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
// ...
}
});
Note: You must confirm that GoogleApiClient.onConnected has been called before signing out.
Also check status which comes in onResult - maybe there is some error, which might lead to the answer.
GoogleSignInOptions gso = new GoogleSignInOptions.
Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).
build();
GoogleSignInClient googleSignInClient= GoogleSignIn.getClient(this,gso);
googleSignInClient.signOut().addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()){
FirebaseAuth.getInstance().signOut(); // very important if you are using firebase.
Intent login_intent = new Intent(getApplicationContext(),YouLoginActivity.class);
login_intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK); // clear previous task (optional)
startActivity(login_intent);
}
}
});
try using this method to log out from Google sign in:
Make sure u call it after u successfully get logged in onConnected(Bundle arg0)
public void Disconnect_google() {
try {
if (mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
mGoogleApiClient.clearDefaultAccountAndReconnect().setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
mGoogleApiClient.disconnect();
Toast.makeText(getApplicationContext(),"Disconnected",Toast.LENGTH_SHORT).show();
}
});
}
} catch (Exception e) {
Log.d("DISCONNECT ERROR", e.toString());
}
}
At the time of logout when you are login from google then use below code
if (mGoogleApiClient.isConnected()) {
Plus.AccountApi.clearDefaultAccount(mGoogleApiClient);
mGoogleApiClient.disconnect();
mGoogleApiClient.connect();
}
your problem will solve by using only single line for signOut instead of 8 lines code you can use in the signInActivity when you are signing a user
private fun signIn() {
googleSignInClient.signOut()
val signInIntent = googleSignInClient.signInIntent
startActivityForResult(signInIntent, RC_SIGN_IN)
}
and in the sign out function you can just use this
FirebaseAuth.getInstance().signOut()
where FirebaseAuth is : com.google.firebase.auth public abstract class FirebaseAuth
When you login using google it will show all the signin google account in the device. when you select any one than it proceed further but when you logout from your system and login it again. it directly choose the previous account.
so for choosing from all existing account in device you have to clear the app data.
for clearing app data follow below steps
1. go to device settings
2. choose APPs
3. select your app
4. storage/clear data