チュートリアルに従ってみました: https://developers.google.com/Android/guides/http-auth 。
コード:
token = GoogleAuthUtil.getToken(getApplicationContext(),
mEmail, mScope);
マニフェスト:
<uses-permission Android:name="Android.permission.GET_ACCOUNTS"/>
<uses-permission Android:name="Android.permission.NETWORK"/>
<uses-permission Android:name="Android.permission.USE_CREDENTIALS"/>
<uses-permission Android:name="Android.permission.INTERNET"/>
エラー:
01-17 18:37:38.230: W/System.err(3689): com.google.Android.gms.auth.UserRecoverableAuthException: NeedPermission
01-17 18:37:38.230: W/System.err(3689): at com.google.Android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
01-17 18:37:38.230: W/System.err(3689): at com.google.Android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
01-17 18:37:38.230: W/System.err(3689): at com.example.mgoogleauth.MainActivity$GetIOStreamTask.doInBackground(MainActivity.Java:39)
01-17 18:37:38.230: W/System.err(3689): at com.example.mgoogleauth.MainActivity$GetIOStreamTask.doInBackground(MainActivity.Java:1)
01-17 18:37:38.230: W/System.err(3689): at Android.os.AsyncTask$2.call(AsyncTask.Java:287)
01-17 18:37:38.230: W/System.err(3689): at Java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.Java:305)
01-17 18:37:38.230: W/System.err(3689): at Java.util.concurrent.FutureTask.run(FutureTask.Java:137)
01-17 18:37:38.230: W/System.err(3689): at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1076)
01-17 18:37:38.230: W/System.err(3689): at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:569)
01-17 18:37:38.230: W/System.err(3689): at Java.lang.Thread.run(Thread.Java:856)
Android向けドライブクイックスタートを試してみてください。ドライブへのファイルの承認とアップロードの方法を示す段階的なガイドです。 https://developers.google.com/drive/quickstart-Android
具体的には、UserRecoverableExceptionをキャッチせず、ユーザーにアプリを承認させる意図をトリガーしていないようです。これは、クイックスタートサンプルでリンクおよび処理したGoogle Play Servicesドキュメントに次のように記載されています。
...
} catch (UserRecoverableAuthIOException e) {
startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
}
...
公式のGoogleAuthUtilチュートリアル のgetAndUseAuthTokenBlocking()メソッドは、例外を処理する方法を非常によく説明しています。
// Example of how to use the GoogleAuthUtil in a blocking, non-main thread context
void getAndUseAuthTokenBlocking() {
try {
// Retrieve a token for the given account and scope. It will always return either
// a non-empty String or throw an exception.
final String token = GoogleAuthUtil.getToken(Context, String, String)(context, email, scope);
// Do work with token.
...
if (server indicates token is invalid) {
// invalidate the token that we found is bad so that GoogleAuthUtil won't
// return it next time (it may have cached it)
GoogleAuthUtil.invalidateToken(Context, String)(context, token);
// consider retrying getAndUseTokenBlocking() once more
return;
}
return;
} catch (GooglePlayServicesAvailabilityException playEx) {
Dialog alert = GooglePlayServicesUtil.getErrorDialog(
playEx.getConnectionStatusCode(),
this,
MY_ACTIVITYS_AUTH_REQUEST_CODE);
...
} catch (UserRecoverableAuthException userAuthEx) {
// Start the user recoverable action using the intent returned by
// getIntent()
myActivity.startActivityForResult(
userAuthEx.getIntent(),
MY_ACTIVITYS_AUTH_REQUEST_CODE);
return;
} catch (IOException transientEx) {
// network or server error, the call is expected to succeed if you try again later.
// Don't attempt to call again immediately - the request is likely to
// fail, you'll hit quotas or back-off.
...
return;
} catch (GoogleAuthException authEx) {
// Failure. The call is not expected to ever succeed so it should not be
// retried.
...
return;
}
}
私は同じエラーがありました、私の場合は間違ったスコープを使用していました、私はちょうど変更します
https://www.googleapis.com/auth/plus.login
for
https://www.googleapis.com/auth/userinfo.profile
このドキュメントページで https://developers.google.com/+/mobile/Android/sign-in にこの例外の説明があります。
特に、次の行に注意する必要があります。
認証コードをリクエストすると、GoogleAuthUtil.getTokenの最初の呼び出しで常にUserRecoverableAuthExceptionがスローされます
catch (UserRecoverableAuthException e) {
// Requesting an authorization code will always throw
// UserRecoverableAuthException on the first call to GoogleAuthUtil.getToken
// because the user must consent to offline access to their data. After
// consent is granted control is returned to your activity in onActivityResult
// and the second call to GoogleAuthUtil.getToken will succeed.
startActivityForResult(e.getIntent(), AUTH_CODE_REQUEST_CODE);
return;
}
ドキュメントは最近更新され、SDK M(アクセス許可の要求)をサポートするようになり、OAuthダイアログを表示します。
[〜#〜] note [〜#〜]多くの場合、Googleドキュメントは最新ではありませんが、問題を報告するときには注意を払っているようです。この例は、1週間でフィードバックを送信して更新されました。動作しない例があれば、フィードバックを送ってください!
https://developers.google.com/drive/v3/web/quickstart/Android
ここでの答えは受動的な解決策であり、予防的なものではありません。
私の非常に短い経験によると、UserRecoverableAuthException:NeedPermissionは、次の3つの場合にスローされます。
#1 Googleへのサインイン時に適切なスコープは要求されません
要求しているスコープが正しいことを確認してください。 Androidは、許可要求ダイアログを介して認証プロセス後に許可を許可するようにユーザーに要求する必要があります。これにより、APIを呼び出すときにUserRecoverableAuthExceptionが防止されます。
GoogleSignInOptions o = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestScopes(new Scope(DriveScopes.DRIVE)) // request permission for Drive API
.requestScopes(new Scope(SheetsScopes.SPREADSHEETS)) // request permission for Sheets API
.requestEmail()
.build();
#2ユーザーは許可を拒否しました
ユーザーが許可要求ダイアログで「拒否」ボタンを押しました。
#3ユーザーはアプリからの許可を拒否しました
Android 8.1.xに関しては、個々のアプリの許可を拒否できるメニューがあります。ただし、他のバージョンについてはわかりません。
Settings > Google > Connected apps
#2および#3によってスローされるUserRecoverableAuthExceptionは、ユーザーアクティビティの結果であるため、避けられません。しかし、ユーザーの拒否にもかかわらず、以下のコードで許可要求ダイアログを再び表示することは無意味ではありませんか?
} catch (UserRecoverableAuthIOException e) {
startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
}