【问题标题】:GoogleAuthUtil: get access token that will provide an email address?GoogleAuthUtil:获取将提供电子邮件地址的访问令牌?
【发布时间】:2015-01-30 02:36:13
【问题描述】:

我无法获取访问令牌来提供电子邮件地址。我正在使用 GoogleAuthUtil。 (结果说token无效)

我用这个:

  mGoogleApiClient = new GoogleApiClient.Builder (cordova.getActivity().getApplicationContext())
   .addConnectionCallbacks (this)
   .addOnConnectionFailedListener (this)
   .addApi (Games.API)
   .addScope (Games.SCOPE_GAMES)
   .addApi(Plus.API)
   .addScope(Plus.SCOPE_PLUS_PROFILE)
   .addScope(Plus.SCOPE_PLUS_LOGIN)
   .build ();


还有这个:

scope = "oauth2:" + Scopes.PROFILE + " " + "email";

删除“电子邮件”可以为我提供有效的访问令牌——但响应中没有电子邮件地址。

这是我的代码。

package com.flyingsoftgames.googleplayservices;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.Scopes;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.GoogleApiClient.ConnectionCallbacks;
import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.games.Players;
import com.google.android.gms.games.Games;

import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.gms.auth.GooglePlayServicesAvailabilityException;
import com.google.android.gms.plus.Account;
import com.google.android.gms.plus.Plus;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.PluginResult;
import org.apache.cordova.PluginResult.Status;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;

import android.app.Activity;

import android.os.AsyncTask;
import android.os.Bundle;
import org.apache.cordova.*;

import java.io.IOException;

import android.util.Log;

public class GooglePlayServices extends CordovaPlugin implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

 private static final String LOG_TAG = "GooglePlayServices";
 private static final int REQ_SIGN_IN_REQUIRED = 55664;

 public static GoogleApiClient mGoogleApiClient   = null;
 public CallbackContext        tryConnectCallback = null;
 public String                 accessToken        = "";
 private int                   connectionAttempts = 0;
 @Override public void onConnectionFailed (ConnectionResult result) {
  String errormessage = result.toString();
  Log.w (LOG_TAG, errormessage);
  connectionAttempts += 1;
  if (!result.hasResolution() || connectionAttempts >= 2) {
   Log.w (LOG_TAG, "Error: no resolution. Google Play Services connection failed.");
   tryConnectCallback.error ("Error: " + errormessage + "."); tryConnectCallback = null;
   return;
  }
  try {
   result.startResolutionForResult (cordova.getActivity(), result.getErrorCode());
  } catch (SendIntentException e) {
   // There was an error with the resolution intent. Try again.
   mGoogleApiClient.connect ();
  }
 }

 @Override public void onConnected (Bundle connectionHint) {
  String mAccountName = Plus.AccountApi.getAccountName(mGoogleApiClient);
  new RetrieveTokenTask().execute (mAccountName);
  Games.setViewForPopups (mGoogleApiClient, webView);
 }

 public void onActivityResult (int requestCode, int responseCode, Intent intent) {
  if (!mGoogleApiClient.isConnecting()) mGoogleApiClient.connect ();
 }

 @Override public void onConnectionSuspended (int cause) {
  mGoogleApiClient.connect ();
 }

 public boolean execute (String action, JSONArray inputs, CallbackContext callbackContext) throws JSONException {
  if        ("getPlayerId".equals(action)) {
   String playerId = Games.Players.getCurrentPlayerId (mGoogleApiClient);
   callbackContext.sendPluginResult (new PluginResult (PluginResult.Status.OK, playerId));
  } else if ("tryConnect".equals(action)) {
   tryConnect (callbackContext);
  } else if ("getAccessToken".equals(action)) {
   callbackContext.sendPluginResult (new PluginResult (PluginResult.Status.OK, accessToken));
  }
  return true;
 }

 // tryConnect runs the callback with a value of false if Google Play Services isn't available.
 public void tryConnect (CallbackContext callbackContext) {
  boolean isGpsAvailable = (GooglePlayServicesUtil.isGooglePlayServicesAvailable(cordova.getActivity()) == ConnectionResult.SUCCESS);
  if (!isGpsAvailable) {
   callbackContext.sendPluginResult (new PluginResult (PluginResult.Status.OK, false));
   return;
  }
  tryConnectCallback = callbackContext;
  mGoogleApiClient = new GoogleApiClient.Builder (cordova.getActivity().getApplicationContext())
   .addConnectionCallbacks (this)
   .addOnConnectionFailedListener (this)
   .addApi (Games.API)
   .addScope (Games.SCOPE_GAMES)
   .addApi(Plus.API)
   .addScope(Plus.SCOPE_PLUS_PROFILE)
   .addScope(Plus.SCOPE_PLUS_LOGIN)
   .build ();
  mGoogleApiClient.connect ();
 }


 private class RetrieveTokenTask extends AsyncTask<String, Void, String> {
  @Override protected String doInBackground (String... params) {
   String accountName = params[0];
   String scope = "oauth2:" + Scopes.PROFILE + " " + "email";
   Context context = cordova.getActivity().getApplicationContext();
   try {
    accessToken = GoogleAuthUtil.getToken (context, accountName, scope);
   } catch (IOException e) {
    String errormessage = e.getMessage();
    Log.e (LOG_TAG, errormessage);
    if (tryConnectCallback != null) tryConnectCallback.error ("Error: " + errormessage + "."); tryConnectCallback = null;
   } catch (UserRecoverableAuthException e) {
    cordova.getActivity().startActivityForResult (e.getIntent(), REQ_SIGN_IN_REQUIRED);
   } catch (GoogleAuthException e) {
    String errormessage = e.getMessage();
    Log.e (LOG_TAG, errormessage);
    if (tryConnectCallback != null) tryConnectCallback.error ("Error: " + errormessage + "."); tryConnectCallback = null;
   }
   return accessToken;
  }

  @Override protected void onPostExecute (String newAccessToken) {
   super.onPostExecute (newAccessToken);
   accessToken = newAccessToken;   
   if (tryConnectCallback != null) {
    String playerId = Games.Players.getCurrentPlayerId (mGoogleApiClient);
    tryConnectCallback.sendPluginResult (new PluginResult (PluginResult.Status.OK, playerId));
    tryConnectCallback = null;
   }
  }
 }
}

【问题讨论】:

    标签: android oauth oauth-2.0 google-play google-play-services


    【解决方案1】:

    似乎在https://security.google.com/settings/security/permissions?hl=en 中清除应用程序的权限确实会触发重新授权屏幕,但从 .getToken 收到的访问令牌已过时。需要使用GoogleAuthUtil.clearToken (context, accessToken);清除旧令牌,否则旧令牌必须超时。因此,我们可以这样做:

    accessToken = GoogleAuthUtil.getToken(context, accountName, scope);
    GoogleAuthUtil.clearToken (context, accessToken);
    accessToken = GoogleAuthUtil.getToken(context, accountName, scope);
    

    但是:

    这似乎只有在重新启动应用程序的几次迭代后才能解决,因为 GoogleAuthUtil.getToken 在需要新权限时是异步的,并且会弹出两个单独的权限屏幕:一个来自 Google(从 GoogleAuthUtil.getToken 和一个来自 Google+(由GoogleApiClient.Builder 触发)。

    编辑: 使用AccountPicker 类消除了使用GoogleApiClient.Builder 的需要!

    见: https://github.com/agamemnus/googleplaytoken

    【讨论】:

      猜你喜欢
      • 2017-05-07
      • 1970-01-01
      • 2018-09-05
      • 2012-02-08
      • 1970-01-01
      • 2016-09-13
      • 1970-01-01
      • 2021-01-05
      • 1970-01-01
      相关资源
      最近更新 更多