在 Android 上授权驱动器和工作表 API
Authorizing Drive and Sheets API on Android
好的,所以我的 Android 应用需要访问用户 Google 驱动器帐户并在该帐户上编辑电子表格。我正在使用 Google Sheets API 3.0 版来编辑电子表格和 Drive API Client Library for Java 以访问驱动器。
现在我知道了用户需要允许我的应用程序访问他们的信息。现在请纠正我,但我是这样理解的。
- 开始activity供用户选择账户
- 在
onActivityResult
方法上检查结果以查看用户是否授予权限。
现在,因为我使用两个 API(驱动器和电子表格),用户必须对两者都给予许可,所以我下面的代码执行以下操作。
- 开始activity供用户选择账户
- 在
onActivityResult
方法中选择 accountName,并将其设置为将要使用的帐户。
- 在
onActivityResult
方法中,在我设置要使用的 accountName 之后,我在一个单独的线程(Asyn Task)上进行调用,该线程将抛出 UserRecoverableAuthIOException
,然后使用此异常提示用户获得驱动器 API. 的权限
- 在响应用户授予权限的
onActivityResult
方法中,我在一个单独的线程上进行了另一个调用,类似于上一个,这将抛出一个 UserRecoverableAuthException
来授权工作表 API .
基本上,用户选择他们想要使用的帐户,然后授予 Drive API 权限,然后授予 Sheets API 权限。 我的问题:授予权限应该这样吗?他们是一种在一个提示中同时授予驱动器和表格 API 权限的方法吗?
public class PlannerActivity 扩展了 ActionBarActivity {
ListPlannerFragment mListFragment;
DetailPlannerFragment mDetailFragment;
YIGDataController mController;
private Drive mDrive;
private SpreadsheetService mSpreadsheetService;
private GoogleAccountCredential mGoogleAccountCredential;
private static final String TAG = "PlannerActivity";
protected static final int CHOOSE_ACCOUNT_REQUEST_CODE = 1;
protected static final int AUTHORIZE_DRIVE_ACCESS_REQUEST_CODE = 2;
protected static final int AUTHORIZE_SHEETS_ACCESS_REQUEST_CODE = 3;
//Life Cycle
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Google
verifyGoogleAPIUse();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG,"onActivity result called: result code-" + resultCode + ", resultCode-" + resultCode);
switch(requestCode) {
case CHOOSE_ACCOUNT_REQUEST_CODE:
Log.d(TAG,"Result of CHOOSE_ACCOUNT:");
if(resultCode == Activity.RESULT_OK) {
Log.d(TAG, "CHOOSE_ACCOUNT successful:");
String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
mGoogleAccountCredential.setSelectedAccountName(accountName);
mDrive = new Drive.Builder(AndroidHttp.newCompatibleTransport(),new GsonFactory(), mGoogleAccountCredential).setApplicationName("YIG Manager").build();
AuthTryDrive authTryDrive = new AuthTryDrive();
authTryDrive.execute();
} else {
Log.d(TAG, "CHOOSE_ACCOUNT failure:");
finish();
}
break;
case AUTHORIZE_DRIVE_ACCESS_REQUEST_CODE:
Log.d(TAG,"Result of AUTHORIZE_DRIVE:");
if(resultCode == Activity.RESULT_OK) {
Log.d(TAG, "AUTHORIZE_DRIVE_ACCESS success:");
AuthTrySheets authTrySheets = new AuthTrySheets();
authTrySheets.execute();
} else {
Log.d(TAG, "AUTHORIZE_DRIVE_ACCESS failed, asking to choose new account:");
finish();
}
break;
case AUTHORIZE_SHEETS_ACCESS_REQUEST_CODE:
Log.d(TAG,"Result of AUTHORIZE_SHEETS:");
if(resultCode == Activity.RESULT_OK) {
Log.d(TAG, "AUTHORIZE_SHEETS_ACCESS success:");
} else {
Log.d(TAG, "AUTHORIZE_SHEETS_ACCESS failed, asking to choose new account:");
finish();
}
break;
}
}
//Util
private void verifyGoogleAPIUse(){
mGoogleAccountCredential =GoogleAccountCredential.usingOAuth2(this, Collections.singleton(DriveScopes.DRIVE));
Log.d(TAG,"Starting activity to choose account.");
startActivityForResult(mGoogleAccountCredential.newChooseAccountIntent(),CHOOSE_ACCOUNT_REQUEST_CODE);
}
private class AuthTryDrive extends AsyncTask<Void,Void,Void>{
@Override
protected Void doInBackground(Void... params) {
//Drive
try {
Log.d(TAG, "In try statement of authorizing drive access");
FileList f = mDrive.files().list().execute();
f.toString();
} catch (UserRecoverableAuthIOException e) {
Log.d(TAG, "Drive user recoverable error");
startActivityForResult(e.getIntent(),AUTHORIZE_DRIVE_ACCESS_REQUEST_CODE);
} catch (IOException e) {
Log.d(TAG,"io excpetion in drive");
}
return null;
}
}
private class AuthTrySheets extends AsyncTask<Void,Void,Void>{
@Override
protected Void doInBackground(Void... params) {
//SpreadSheets
try {
Log.d(TAG,"In try statement of authorizing sheets access");
mSpreadsheetService = new SpreadsheetService("YIG Manager");
mSpreadsheetService.setAuthSubToken(GoogleAuthUtil.getToken(PlannerActivity.this, mGoogleAccountCredential.getSelectedAccountName(), "oauth2:https://spreadsheets.google.com/feeds https://docs.google.com/feeds"));
URL SPREADSHEET_FEED_URL = new URL(
"https://spreadsheets.google.com/feeds/spreadsheets/private/full");
SpreadsheetFeed spreadsheetFeed = mSpreadsheetService.getFeed(SPREADSHEET_FEED_URL,SpreadsheetFeed.class);
List<SpreadsheetEntry> spreadsheetEntries = spreadsheetFeed.getEntries();
} catch (UserRecoverableAuthException e) {
Log.d(TAG,"Sheets user recoverable error");
startActivityForResult(e.getIntent(),AUTHORIZE_SHEETS_ACCESS_REQUEST_CODE);
} catch (GoogleAuthException e) {
Log.d(TAG,"GoogleAuthException");
} catch (IOException e) {
Log.d(TAG,"IOException");
} catch (ServiceException e) {
Log.d(TAG,"ServiceException" + e.toString());
}
return null;
}
}
}
当您调用 GoogleAuthUtil.getToken 时,您可以提供一个 space 分隔列表,其中包含您要授权的所有范围。只需包括驱动器和工作表范围。其他一些地方在技术上可能仍然能够抛出 auth 异常,但如果你先这样做,它不应该导致提示。
好的,所以我的 Android 应用需要访问用户 Google 驱动器帐户并在该帐户上编辑电子表格。我正在使用 Google Sheets API 3.0 版来编辑电子表格和 Drive API Client Library for Java 以访问驱动器。
现在我知道了用户需要允许我的应用程序访问他们的信息。现在请纠正我,但我是这样理解的。
- 开始activity供用户选择账户
- 在
onActivityResult
方法上检查结果以查看用户是否授予权限。
现在,因为我使用两个 API(驱动器和电子表格),用户必须对两者都给予许可,所以我下面的代码执行以下操作。
- 开始activity供用户选择账户
- 在
onActivityResult
方法中选择 accountName,并将其设置为将要使用的帐户。 - 在
onActivityResult
方法中,在我设置要使用的 accountName 之后,我在一个单独的线程(Asyn Task)上进行调用,该线程将抛出UserRecoverableAuthIOException
,然后使用此异常提示用户获得驱动器 API. 的权限
- 在响应用户授予权限的
onActivityResult
方法中,我在一个单独的线程上进行了另一个调用,类似于上一个,这将抛出一个UserRecoverableAuthException
来授权工作表 API .
基本上,用户选择他们想要使用的帐户,然后授予 Drive API 权限,然后授予 Sheets API 权限。 我的问题:授予权限应该这样吗?他们是一种在一个提示中同时授予驱动器和表格 API 权限的方法吗?
public class PlannerActivity 扩展了 ActionBarActivity {
ListPlannerFragment mListFragment;
DetailPlannerFragment mDetailFragment;
YIGDataController mController;
private Drive mDrive;
private SpreadsheetService mSpreadsheetService;
private GoogleAccountCredential mGoogleAccountCredential;
private static final String TAG = "PlannerActivity";
protected static final int CHOOSE_ACCOUNT_REQUEST_CODE = 1;
protected static final int AUTHORIZE_DRIVE_ACCESS_REQUEST_CODE = 2;
protected static final int AUTHORIZE_SHEETS_ACCESS_REQUEST_CODE = 3;
//Life Cycle
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Google
verifyGoogleAPIUse();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG,"onActivity result called: result code-" + resultCode + ", resultCode-" + resultCode);
switch(requestCode) {
case CHOOSE_ACCOUNT_REQUEST_CODE:
Log.d(TAG,"Result of CHOOSE_ACCOUNT:");
if(resultCode == Activity.RESULT_OK) {
Log.d(TAG, "CHOOSE_ACCOUNT successful:");
String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
mGoogleAccountCredential.setSelectedAccountName(accountName);
mDrive = new Drive.Builder(AndroidHttp.newCompatibleTransport(),new GsonFactory(), mGoogleAccountCredential).setApplicationName("YIG Manager").build();
AuthTryDrive authTryDrive = new AuthTryDrive();
authTryDrive.execute();
} else {
Log.d(TAG, "CHOOSE_ACCOUNT failure:");
finish();
}
break;
case AUTHORIZE_DRIVE_ACCESS_REQUEST_CODE:
Log.d(TAG,"Result of AUTHORIZE_DRIVE:");
if(resultCode == Activity.RESULT_OK) {
Log.d(TAG, "AUTHORIZE_DRIVE_ACCESS success:");
AuthTrySheets authTrySheets = new AuthTrySheets();
authTrySheets.execute();
} else {
Log.d(TAG, "AUTHORIZE_DRIVE_ACCESS failed, asking to choose new account:");
finish();
}
break;
case AUTHORIZE_SHEETS_ACCESS_REQUEST_CODE:
Log.d(TAG,"Result of AUTHORIZE_SHEETS:");
if(resultCode == Activity.RESULT_OK) {
Log.d(TAG, "AUTHORIZE_SHEETS_ACCESS success:");
} else {
Log.d(TAG, "AUTHORIZE_SHEETS_ACCESS failed, asking to choose new account:");
finish();
}
break;
}
}
//Util
private void verifyGoogleAPIUse(){
mGoogleAccountCredential =GoogleAccountCredential.usingOAuth2(this, Collections.singleton(DriveScopes.DRIVE));
Log.d(TAG,"Starting activity to choose account.");
startActivityForResult(mGoogleAccountCredential.newChooseAccountIntent(),CHOOSE_ACCOUNT_REQUEST_CODE);
}
private class AuthTryDrive extends AsyncTask<Void,Void,Void>{
@Override
protected Void doInBackground(Void... params) {
//Drive
try {
Log.d(TAG, "In try statement of authorizing drive access");
FileList f = mDrive.files().list().execute();
f.toString();
} catch (UserRecoverableAuthIOException e) {
Log.d(TAG, "Drive user recoverable error");
startActivityForResult(e.getIntent(),AUTHORIZE_DRIVE_ACCESS_REQUEST_CODE);
} catch (IOException e) {
Log.d(TAG,"io excpetion in drive");
}
return null;
}
}
private class AuthTrySheets extends AsyncTask<Void,Void,Void>{
@Override
protected Void doInBackground(Void... params) {
//SpreadSheets
try {
Log.d(TAG,"In try statement of authorizing sheets access");
mSpreadsheetService = new SpreadsheetService("YIG Manager");
mSpreadsheetService.setAuthSubToken(GoogleAuthUtil.getToken(PlannerActivity.this, mGoogleAccountCredential.getSelectedAccountName(), "oauth2:https://spreadsheets.google.com/feeds https://docs.google.com/feeds"));
URL SPREADSHEET_FEED_URL = new URL(
"https://spreadsheets.google.com/feeds/spreadsheets/private/full");
SpreadsheetFeed spreadsheetFeed = mSpreadsheetService.getFeed(SPREADSHEET_FEED_URL,SpreadsheetFeed.class);
List<SpreadsheetEntry> spreadsheetEntries = spreadsheetFeed.getEntries();
} catch (UserRecoverableAuthException e) {
Log.d(TAG,"Sheets user recoverable error");
startActivityForResult(e.getIntent(),AUTHORIZE_SHEETS_ACCESS_REQUEST_CODE);
} catch (GoogleAuthException e) {
Log.d(TAG,"GoogleAuthException");
} catch (IOException e) {
Log.d(TAG,"IOException");
} catch (ServiceException e) {
Log.d(TAG,"ServiceException" + e.toString());
}
return null;
}
}
}
当您调用 GoogleAuthUtil.getToken 时,您可以提供一个 space 分隔列表,其中包含您要授权的所有范围。只需包括驱动器和工作表范围。其他一些地方在技术上可能仍然能够抛出 auth 异常,但如果你先这样做,它不应该导致提示。