尽管明确请求,但无法从 Google Plus 帐户获取私人生日

Cannot get private birthday from Google Plus account although explicit request

我正在尝试从其 Google Plus 帐户中获取用户的信息,包括性别和年龄。由于这些字段可能是私有的,我认为明确请求它们可以解决问题。然而,尽管登录对话框明确指出应用程序请求 View your complete date of birth,但我未能获得生日。

这些是我的示波器(尝试了很多变化):

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();

onActivityResult 中使用已弃用的 getCurrentPerson 时,我得到空值:

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
        }
    }
}

我也尝试从帐户 (GoogleSignInAccount account = result.getSignInAccount()) 中获取它,但据我搜索,这个变量根本不拥有请求的数据。

我错过了什么吗?或者虽然明确请求,但可能无法获得私人数据?

谢谢。

顺便说一句,我还没有尝试过带有私人性别的场景。

试试这个初始化

GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this).addApi(Plus.API)
                .addScope(Plus.SCOPE_PLUS_LOGIN).build();

否则请求的用户需要 public 能看到生日。

我认为 this Google People API documentation 会对您的问题有所帮助。

请关注:

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.

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.

如果您的应用没有访问令牌,您可以阅读 Using OAuth 2.0 to Access Google APIs 或在以下问题中尝试我的回答:


更新: 假设您的应用可以使用我上面答案中的示例代码获取访问令牌,然后在 onResponse 中添加更多代码段,如下所示:

...
@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 信息(因为太长我截断了)

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
                             }
                        }
                   ],
                   ....
              }

GoogleSignInOptionsGoogleApiClient:

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();

请注意,我这里使用的OkHttp版本是v2.6.0,如果你的应用是最新的(3.3.1),那么syntax/classes会有所不同。当然你也可以使用其他的比如Volley, Retrofit...


此外,this Google's People API - Method people.get提供试一试如下图

其他有用的链接:

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)