Can't get user birthday with Google Play services API - android

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

Related

Facebook/Google signup on Firebase on Android application

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.

How to link Firebase account to Google Play Games account

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.

Request timeout in Google Fit - Android wear 2.0

I have a problem with getting google fit data on Android Wear 2.0.
My requests are getting TIMEOUT response. If the await() method has no parameters, there is no response (the await() method did not returned). Any clues whats wrong?
App uses Google Sign-In, and everything works on regular Android device.
Creating of GoogleApiClient and SignInAccount
GoogleSignInOptions signInConfig = new GoogleSignInOptions
.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestScopes(new Scope(Scopes.FITNESS_LOCATION_READ),new Scope(Scopes.FITNESS_ACTIVITY_READ))
.build();
client = new GoogleApiClient.Builder(this)
.enableAutoManage(this,this)
.addApi(Auth.GOOGLE_SIGN_IN_API, signInConfig)
.addApi(Fitness.HISTORY_API)
.addApi(Fitness.GOALS_API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
After login procedure is done I run:
new Thread(new Runnable() {
#Override
public void run() {
PendingResult<DailyTotalResult> result =
Fitness.HistoryApi.readDailyTotal(client, TYPE_STEP_COUNT_DELTA);
DailyTotalResult totalResult = result.await(60,TimeUnit.SECONDS);
if (totalResult.getStatus().isSuccess()) {
DataSet totalSet = totalResult.getTotal();
long total = totalSet.isEmpty()? 0 : totalSet.getDataPoints().get(0).getValue(FIELD_STEPS).asInt();
p("daily steps " + total);
}}).start();
}
You may want to check the correct process in inserting data wherein it was discussed that to insert data into the fitness history, first create a DataSet instance before using the HistoryApi.insertData method and wait synchronously or provide a callback method to check the status of the insertion.
For a more detailed information and sample codes, you may want to check the full documentation.
Similar problem was asked here at G+ GoogleFitDevelopersGroup. Thanks to PujieWear we managed to solve the problem. You have to use two different GoogleApiClient's, one to get authenticated, second to get the data.
I'm no sure wheather this is proper way of using Google Sign-In, but it works.
//Yet, it seems that the Scopes are not yet resolved properly on Wear 2.0.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult signInResult = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (signInResult.isSuccess()) {
acct = signInResult.getSignInAccount();
editor.putString(ACCOUNT_NAME_PREFS,acct.getEmail());
editor.commit();
dataGoogleApiClientBuilder.setAccountName(acct.getEmail());
dataGoogleApiClient = dataGoogleApiClientBuilder.build();
dataGoogleApiClient.connect();
[...]

GoogleSignInResult returns DEVELOPER_ERROR in Android app using Firebase

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.

Google login get access token with new GoogleSignInOptions

My android app currently uses the GoogleAuthUtil to signin users and fetch an access_token which is passed to the backend (code snippets below which show creating the GoogleApiClient and using GoogleAuthUtil to get the token).
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API)
.addScope(new Scope("profile"))
.build();
...
...
String accessToken = GoogleAuthUtil.getToken(GoogleLoginActivity.this,
Plus.AccountApi.getAccountName(mGoogleApiClient),
"oauth2:profile email");
which I then sent to the backend
I am now trying to move to the new Google SignIn - https://developers.google.com/identity/sign-in/android/sign-in
and so changed the GoogleApiClient creation like,
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestIdToken("<web client id>")
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, this)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
and then to do the login use,
startActivityForResult(Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient), RC_GET_TOKEN);
and on activity result use (similar to the example in the link above),
OptionalPendingResult<GoogleSignInResult> opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient);
if (opr.isDone()) {
// If the user's cached credentials are valid, the OptionalPendingResult will be "done"
// and the GoogleSignInResult will be available instantly.
Log.d(TAG, "Got cached sign-in");
handleSignInResult(opr.get());
} else {
// If the user has not previously signed in on this device or the sign-in has expired,
// this asynchronous branch will attempt to sign in the user silently. Cross-device
// single sign-on will occur in this branch.
showProgress();
opr.setResultCallback(new ResultCallback<GoogleSignInResult>() {
#Override
public void onResult(GoogleSignInResult googleSignInResult) {
hideProgress();
handleSignInResult(googleSignInResult);
}
});
}
but now it seems that in handleSingInResult(GoogleSignInResult result) I can only get an id token back with
result.getSignInAccount().getIdToken();
Does anyone know if it is possible to get an access token from this (like previously) and if so how? Any help appreciated.
After signing in you'll be able to get the token:
final String token = GoogleAuthUtil.getToken(mAppContext, mAccountName, AUTH_TOKEN_TYPE);
dont forget to do it an Asynctask. for more detail have a look at here
EDIT:
Note that, despite the method name:
GoogleAuthUtil.getToken()
it does not give you an OAuth Token, it rather returns a "short-lived authorization code" according to the documentation.
What I should do after getting the Authorization Code by calling the
GoogleAuthUtil.getToken() ?
You should transmit the Authorization Code to your backend server over HTTPS. Only from your server you should attempt to receive Access and/or Refresh token, not in your app.
So i was having the same problem. they have changed it now so the token comes through in
GoogleSignInAccount acct = result.getSignInAccount();
Log.d(TAG, "handleSignInResult2: "+acct.getIdToken());
To get access too this token you have too ask for it in
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail().requestProfile().requestId().requestIdToken(getString(R.string.server_client_ID))
.build();
The R.string.server_client_ID is the client ID from the project that you make in your Google developer Console.
I hope this helps you.
here is also the documentation i followed. https://developers.google.com/identity/sign-in/android/backend-auth

Categories

Resources