Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot get private birthday from Google Plus account although explicit request

I am trying to get the user's information, including gender and age, from its Google Plus account. Since these fields may be private, I thought that requesting them explicitly would solve the problem. However, although the sign in dialog states explicitly that the app requests to View your complete date of birth, I fail to get the birthday.

These are my scopes (tried many variations):

GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        //.requestScopes(new Scope(Scopes.PROFILE))
        //.requestScopes(new Scope(Scopes.PLUS_LOGIN))
        .requestScopes(new Scope("https://www.googleapis.com/auth/user.birthday.read"),
                new Scope("https://www.googleapis.com/auth/userinfo.profile"))
        //.requestProfile()
        .requestEmail()
        .build();

mGoogleApiClient = new GoogleApiClient.Builder(this)
        .enableAutoManage(this, this)
        .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
        .addApi(Plus.API)
        .addScope(new Scope(Scopes.PROFILE))
        .build();

When using the deprecated getCurrentPerson in onActivityResult, I get null value:

if (requestCode == RC_SIGN_IN) {
    GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);

    if (mGoogleApiClient.hasConnectedApi(Plus.API)) {
        Person person  = Plus.PeopleApi.getCurrentPerson(mGoogleApiClient);
        if (person != null) {
            Log.i(TAG, person.getDisplayName());    //returns full name successfully
            Log.i(TAG, person.getGender());         //0
            Log.i(TAG, person.getBirthday());       //null
        }
    }
}

I also tried to get it from the account (GoogleSignInAccount account = result.getSignInAccount()) but as far as I've searched, this variable doesn't own the requested data at all.

Am I missing something? Or maybe it's impossible to get private data although explicit request?

Thanks.

BTW, I haven't tried yet a scenario with a private gender.

like image 446
Neria Nachum Avatar asked Jun 22 '16 08:06

Neria Nachum


1 Answers

I think this Google People API documentation will be helpful for your issue.

Please pay attention to:

If the request requires authorization (such as a request for an individual's private data), then the application must provide an OAuth 2.0 token with the request. The application may also provide the API key, but it doesn't have to.

and

Requests to the People API for non-public user data must be authorized by an authenticated user.

...

  1. If the user approves, then Google gives your application a short-lived access token.
  2. Your application requests user data, attaching the access token to the request.
  3. If Google determines that your request and the token are valid, it returns the requested data.

If your app has not got an access token, you can read Using OAuth 2.0 to Access Google APIs or try my answer at the following question:

How to get access token after user is signed in from Gmail in Android?


UPDATE: Supposing that your app can get the access token by using the sample code in my answer above, then inside onResponse, add more snippets as below:

...
@Override
public void onResponse(Response response) throws IOException {
    try {
        JSONObject jsonObject = new JSONObject(response.body().string());
        final String message = jsonObject.toString(5);
        Log.i("onResponse", message);

        // FROM HERE...
        String accessToken = jsonObject.optString("access_token");

        OkHttpClient client2 = new OkHttpClient();
        final Request request2 = new Request.Builder()
                .url("https://people.googleapis.com/v1/people/me")
                .addHeader("Authorization", "Bearer " + accessToken)
                .build();

        client2.newCall(request2).enqueue(new Callback() {
            @Override
            public void onFailure(final Request request, final IOException e) {
                Log.e("onFailure", e.toString());
            }

            @Override
            public void onResponse(Response response) throws IOException {
                try {
                    JSONObject jsonObject = new JSONObject(response.body().string());
                    final String message = jsonObject.toString(5);
                    Log.i("onResponse", message);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });
    } catch (JSONException e) {
        e.printStackTrace();
    }
}
...

Logcat info (I truncated since it's long)

I/onResponse: {
                   "photos": [
                        {
                             "url": "https:...photo.jpg",
                             "metadata": {
                                  "source": {
                                       "id": "1....774",
                                       "type": "PROFILE"
                                  },
                                  "primary": true
                             }
                        }
                   ],
                   ...                                                                               
                   "birthdays": [
                        {
                             "date": {
                                  "month": 2,
                                  "year": 1980,
                                  "day": 2
                             },
                             "metadata": {
                                  "source": {
                                       "id": "1....774",
                                       "type": "PROFILE"
                                  },
                                  "primary": true
                             }
                        }
                   ],
                   ....
              }

GoogleSignInOptions and GoogleApiClient:

String serverClientId = getString(R.string.server_client_id);
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestScopes(new Scope("https://www.googleapis.com/auth/user.birthday.read"))
        .requestServerAuthCode(serverClientId)
        .build();

GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
        .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
        .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
        .build();

Please note that the OkHttp version I use here is v2.6.0, if your app uses the newest (3.3.1), then the syntax/classes will be different. Of course, you can also use the others such as Volley, Retrofit...


Moreover, this Google's People API - Method people.get provides Try It as screenshot below

enter image description here

Other useful links:

Google Developers Blog - Announcing the People API

Google APIs related to Google People API

Authorizing with Google for REST APIs (another way to get access token)

like image 159
BNK Avatar answered Oct 19 '22 23:10

BNK