【发布时间】:2016-01-17 06:26:49
【问题描述】:
我正在尝试在我的 Android 应用中实现 Google 登录。 我遵循了谷歌的指导方针 https://developers.google.com/identity/sign-in/android/sign-in?configured=true 和 https://developers.google.com/identity/protocols/CrossClientAuth
我想从 google 获取授权码,然后将其发送回我的服务器,以便服务器可以处理代码并将其发送给 google 以获取访问令牌。
public static final String TAG = LoginActivity.class.getSimpleName();
private ProgressDialog loginDialog;
/* Request code used to invoke sign in user interactions. */
private static final int RC_SIGN_IN = 1;
/* RequestCode for resolutions to get GET_ACCOUNTS permission on M */
private static final int RC_PERM_GET_ACCOUNTS = 2;
/* Client used to interact with Google APIs. */
private GoogleApiClient mGoogleApiClient;
/* Is there a ConnectionResult resolution in progress? */
private boolean mIsResolving = false;
/* Should we automatically resolve ConnectionResults when possible? */
private boolean mShouldResolve = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
// Build GoogleApiClient with access to basic profile
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(Plus.API)
.addScope(new Scope(Scopes.PROFILE))
.addScope(new Scope(Scopes.EMAIL))
.addScope(new Scope(Scopes.PLUS_LOGIN))
.build();
findViewById(R.id.sign_in_button).setOnClickListener(this);
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
@Override
protected void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
@Override
public void onConnected(Bundle bundle) {
// onConnected indicates that an account was selected on the device, that the selected
// account has granted any requested permissions to our app and that we were able to
// establish a service connection to Google Play services.
Log.d(TAG, "onConnected:" + bundle);
mShouldResolve = false;
new GetIdTokenTask().execute();
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.sign_in_button) {
onSignInClicked();
}
}
private void onSignInClicked() {
// User clicked the sign-in button, so begin the sign-in process and automatically
// attempt to resolve any errors that occur.
mShouldResolve = true;
mGoogleApiClient.connect();
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
// Could not connect to Google Play Services. The user needs to select an account,
// grant permissions or resolve an error in order to sign in. Refer to the javadoc for
// ConnectionResult to see possible error codes.
Log.d(TAG, "onConnectionFailed:" + connectionResult);
if (!mIsResolving && mShouldResolve) {
if (connectionResult.hasResolution()) {
try {
connectionResult.startResolutionForResult(this, RC_SIGN_IN);
mIsResolving = true;
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Could not resolve ConnectionResult.", e);
mIsResolving = false;
mGoogleApiClient.connect();
}
}
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult:" + requestCode + ":" + resultCode + ":" + data);
if (requestCode == RC_SIGN_IN) {
// If the error resolution was not successful we should not resolve further.
if (resultCode != RESULT_OK) {
mShouldResolve = false;
}
mIsResolving = false;
mGoogleApiClient.connect();
}
}
private class GetIdTokenTask extends AsyncTask<Void, String, String> {
@Override
protected String doInBackground(Void... params) {
String accountName = Plus.AccountApi.getAccountName(mGoogleApiClient);
Account account = new Account(accountName, GoogleAuthUtil.GOOGLE_ACCOUNT_TYPE);
String code = "";
String sc = "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.login";
String SERVER_CLIENT_ID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXYYYYYYYYYYY.apps.googleusercontent.com";
String scope = "oauth2:server:client_id:" + CLIENT_ID + ":api_scope:" + sc;
try {
code = GoogleAuthUtil.getToken(getApplicationContext(), account, scope);
} catch (IOException e) {
Log.e(TAG, "Error retrieving ID token.", e);
return null;
} catch (GoogleAuthException e) {
Log.e(TAG, "Error retrieving ID token.", e);
return null;
}
return code;
}
@Override
protected void onPostExecute(String result) {
Log.i(TAG, "ID token: " + result);
if (result != null) {
// Successfully retrieved ID Token
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("https://example.com/auth/google_oauth2/callback");
try {
List nameValuePairs = new ArrayList(1);
nameValuePairs.add(new BasicNameValuePair("idToken", result));
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpClient.execute(httpPost);
int statusCode = response.getStatusLine().getStatusCode();
final String responseBody = EntityUtils.toString(response.getEntity());
Log.i(TAG, "Signed in as: " + responseBody);
} catch (ClientProtocolException e) {
Log.e(TAG, "Error sending ID token to backend.", e);
} catch (IOException e) {
Log.e(TAG, "Error sending ID token to backend.", e);
}
} else {
// There was some error getting the ID Token
// ...
Toast.makeText(getApplicationContext(), R.string.dialog_error_login_text, Toast.LENGTH_LONG).show();
}
}
}
当我尝试从中获取代码时
code = GoogleAuthUtil.getToken(getApplicationContext(), account, scopes);
我的作用域在哪里
String scope = "oauth2:server:client_id:" + CLIENT_ID + ":api_scope:" + sc;
其中 sc = "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.login";
CLIENT_ID 是我在开发者控制台中生成的 Web 服务器客户端 ID。
我来了
10-19 06:54:39.535 26012-26510/com.example.login E/LoginActivity: com.google.android.gms.auth.GoogleAuthException: Unknown
10-19 06:54:39.535 26012-26510/com.example.login E/LoginActivity: at com.google.android.gms.auth.GoogleAuthUtil.zza(Unknown Source)
10-19 06:54:39.535 26012-26510/com.example.login E/LoginActivity: at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
10-19 06:54:39.535 26012-26510/com.example.login E/LoginActivity: at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
10-19 06:54:39.535 26012-26510/com.example.login E/LoginActivity: at com.example.login.LoginActivity$GetIdTokenTask.doInBackground(LoginActivity.java:202)
10-19 06:54:39.535 26012-26510/com.example.login E/LoginActivity: at com.example.login.LoginActivity$GetIdTokenTask.doInBackground(LoginActivity.java:179)
10-19 06:54:39.535 26012-26510/com.example.login E/LoginActivity: at android.os.AsyncTask$2.call(AsyncTask.java:292)
10-19 06:54:39.535 26012-26510/com.example.login E/LoginActivity: at java.util.concurrent.FutureTask.run(FutureTask.java:237)
10-19 06:54:39.535 26012-26510/com.example.login E/LoginActivity: at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
10-19 06:54:39.535 26012-26510/com.example.login E/LoginActivity: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
10-19 06:54:39.535 26012-26510/com.example.login E/LoginActivity: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
10-19 06:54:39.535 26012-26510/com.example.login E/LoginActivity: at java.lang.Thread.run(Thread.java:818)
我不知道为什么会出现此错误。我尝试更改范围,但是当我使用 CLIENT_ID 时,它给了我这个错误。
如果我使用 Scope 如下:
String scope = "oauth2:https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/plus.login";
它给了我权限错误:
com.google.android.gms.auth.UserRecoverableAuthException: NeedPermission
我不知道我的代码有什么问题。非常感谢任何帮助。卡了快 2 天了。
【问题讨论】:
标签: android oauth-2.0 google-oauth google-signin