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.
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.
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.
So I've been messing with this for a couple of days now and I cannot figure out why it doesn't work. I am really hoping someone can help me.
I am trying to authenticate a user with Google sign in using Firebase. So following their guide here I have set up Google sign in to get an OAuth token and then use that to authenticate with Firebase. So I set up Google as they describe in their guide here but that is as far as I got. The OAuth token I get from Google is always null and the result code is Status{statusCode=DEVELOPER_ERROR, resolution=null}.
So far, my activity looks like this:
public static final int RC_GOOGLE_LOGIN = 1;
private GoogleApiClient mGoogleApiClient;
final Context context = this;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Firebase.setAndroidContext(this);
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestIdToken(this.getResources().getString(R.string.server_client_id))
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, this)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
SignInButton signInButton = (SignInButton) findViewById(R.id.googlebtn);
signInButton.setSize(SignInButton.SIZE_WIDE);
signInButton.setScopes(gso.getScopeArray());
signInButton.setOnClickListener(this);
}
#Override
public void onClick (View v) {
switch (v.getId()) {
case R.id.googlebtn:
signIn();
break;
}
}
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_GOOGLE_LOGIN);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_GOOGLE_LOGIN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
}
}
private void handleSignInResult(GoogleSignInResult result) {
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
GoogleSignInAccount acct = result.getSignInAccount();
String idToken = acct.getIdToken();
}
}
I have been googling this for a while and think I've tried everything that is already suggested. Of course I have done everything in the guides, added dependencies ('com.google.android.gms:play-services-auth:8.4.0') and created the necessary clients in the developer console.
I have also checked (multiple times) that the server client ID I am using is the right one from the Developer console, and that it matches my package name in both my gradle file and Manifest file. I have added the google-services.json file to my /app directory and even regenerated it to make sure it matches. I have also checked that the SHA1 key is correct and it still gives the same error.
If I remove the requestIdToken from the Google sign in options it works though, but that doesn't help me as I then cannot sign in with Firebase. Can someone tell me what I need to do to make it work?
Have you set your R.string.server_client_id?
Open the Credentials page in the API Console.
The Web application type client ID is your backend server's OAuth 2.0 client ID.
https://developers.google.com/identity/sign-in/android/start-integrating#get_your_backend_servers_oauth_20_client_id
After the SHA-1 this is the next stumbling point that I've seen.
EDIT
After a new try I finally got my birthday. I didn't change the implementation. I guess it took a few hours for the changes in my Google Plus profile to propagate, making my birthday public. A bit more than expected. Now I'm wondering whether I can ask this permission (birthday) when the user sign in, without the need of the birthday to be public.
As suggested by this information in the developers guide :
For additional profile data that might be available, see
GoogleSignInAccount. Note that any of the profile fields can be null,
depending on which scopes you requested and what information the
user's profile includes.
Initial POST
I would like to get the birthdays of a user after he signed in Google Plus. Being not familiar with Google APIs in general, I'm wondering whether my implementation makes some sense or not. Right now, I'm just trying to get my own birthday from my Google account linked to my device.
Here is what I did. I followed the steps from developer guide for the sign in procedure. In addition to OAuth, I added the Google Plus dependency in gradle:
compile 'com.google.android.gms:play-services-plus:8.3.0'
In my Activity, there is a button to sign in Google Plus.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(new Scope(Scopes.PLUS_ME), new Scope(Scopes.PLUS_LOGIN),new Scope(Scopes.PROFILE))
.build();
GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API)
.build();
loginButton = (SignInButton) findViewById(R.id.sign_in_button);
loginButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
});
After the initial sign in, I try to connect to the Google Play Services.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
Log.d(TAG, "handleSignInResult:" + result.isSuccess());
if (result.isSuccess()) {
mGoogleApiClient.connect(GoogleApiClient.SIGN_IN_MODE_OPTIONAL);
}
}
}
Once connected, I try to fetch the birthday of the user.
#Override
public void onConnected(Bundle bundle) {
Person currentPerson = Plus.PeopleApi
.getCurrentPerson(mGoogleApiClient);
addGoogleProfile(currentPerson); //Add the user to a list of persons
refreshListView(); //update the listView
Log.d(TAG, "Current person: name=" + currentPerson.getDisplayName() + ", has birthday = " + (currentPerson.hasBirthday() ? "yes, it is" + currentPerson.getBirthday() : "no"));
}
Problem
The birthday is never set and always appears to be null. Other data such as the name and profile image are accessible. I didn't find much information on the different Scopes. I'm more familiar with Facebook API where the permissions are more explicitly requested upon login.
Any idea on what I am missing ?
Ho and I set my birthday field as "public" of the associated Google account.
Cheers
Dear you can only getting the following information :-
mePerson.getId()
mePerson.getDisplayName()
mePerson.getImage().getUrl()
mePerson.getUrl()
We can get the birthday of a user from gmail, but for that the user needs to have public visibility of the birthday.
Follow these steps:
Login to gmail and go to: https://myaccount.google.com/u/1/birthday?hl=en&pli=1
Click on "Manage sharing settings" and set birthday to public
Add scope: https://www.googleapis.com/auth/plus.login