【问题标题】:Authorizing Drive and Sheets API on Android在 Android 上授权 Drive 和 Sheets API
【发布时间】:2015-02-17 02:38:21
【问题描述】:

好的,所以我的 Android 应用需要访问用户的 Google 云端硬盘帐户并在该帐户上编辑电子表格。我正在使用 Google Sheets API 3.0 版编辑电子表格和用于 Java 的 Drive API 客户端库以进行驱动器访问。
现在我知道用户需要授予我的应用程序访问其信息的权限。现在请纠正我,但这就是我理解的方式。

  1. 启动活动供用户选择帐户
  2. onActivityResult 方法上检查结果以查看用户是否授予权限。


现在由于我使用两个 API(驱动器和电子表格),用户必须授予两者的权限,所以我下面的代码执行以下操作。

  1. 启动活动供用户选择帐户
  2. onActivityResult 方法中选择 accountName,并将其设置为将要使用的帐户。
  3. onActivityResult 方法中,在我设置要使用的 accountName 之后,我在一个单独的线程(Asyn 任务)上进行调用,该线程将抛出 UserRecoverableAuthIOException,然后使用此异常提示用户许可Drive API。
  4. onActivityResult 方法中,作为对用户授予权限的响应,我在与上一个类似的单独线程上再次调用,这将引发UserRecoverableAuthException 以授权Sheets API。
    基本上,用户选择他们想要使用的帐户,然后授予 Drive API 权限,然后授予 Sheets API 权限。 我的问题:这是应该如何授予权限?他们是一种在一个提示中同时授予 Drive 和 Sheets API 权限的方法吗?

公共类 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;
    }
}

}

【问题讨论】:

    标签: java android google-drive-api google-sheets


    【解决方案1】:

    当您调用GoogleAuthUtil.getToken 时,您可以提供一个以空格分隔的列表,列出您要授权的所有范围。只需包括驱动器和工作表范围。从技术上讲,其他一些地方可能仍然能够引发 auth 异常,但如果你先这样做,它应该不会导致提示。

    【讨论】:

    • 您能否展示一些代码如何执行此操作以及如何将身份验证令牌从驱动器转移到工作表。我假设你会调用类似 mSpreadsheetService.setAuthToken(token)?
    • 您不需要转移 oauth 令牌。用户只需在每个范围内授权您的应用一次。当他们完成后,您可以请求新的 oauth 令牌而无需重新提示用户。因此,只需预先调用 getToken 函数来触发提示,然后根据需要执行与获取令牌相同的操作。
    • 好的,如果我错了,请纠正我。用户只需授予一次权限(第一次),此时谷歌服务器会记住我的应用程序,在谷歌开发者控制台中注册的带有 SHA1 证书和包名称的应用程序已获得权限,并且对于未来的令牌请求将不需要允许。编辑:我尝试了您所说的,只是在 GoogleAuthUtil.getToken() 中将范围连接在一起,这导致用户提示同时授予 Drive 和 Sheets 范围的权限。谢谢!
    • 是的,没错。在某些情况下会重新请求权限,例如如果用户卸载并重新安装应用程序,但通常只提示一次。
    猜你喜欢
    • 2017-10-17
    • 2015-12-26
    • 1970-01-01
    • 1970-01-01
    • 2014-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多