通过访问令牌创建GoogleCredential

时间:2015-03-05 07:56:31

标签: android google-drive-api google-oauth

我想为Google云端硬盘设计Android文件查看器。

首先,我使用Google Android API实现了该应用,如下所示,

private void retrieveNextPage(){

    if(mHasMore == false)
        return;

    Query query = new Query.Builder().setPageToken(mNextPageToken).build();
    com.google.android.gms.drive.Drive.DriveApi.query(getGoogleApiClient(), query).setResultCallback(metadataBufferResultResultCallback);

}

但是,Android Drive API仅允许应用查看和获取自己创建的文件。我无法通过应用程序访问驱动器上的其他文件。

因此,我转向另一个选项,直接操作Java Drive API。

根据Java开发者指南中的示例,

https://developers.google.com/drive/web/quickstart/quickstart-java

用户必须手动复制并粘贴"授权码"在浏览器和应用程序之间,这不是在Android中获取访问令牌的实用方法。

为了采用新方法,我使用Android API中的GoogleAuthUtil获取访问令牌,与Java API中的GoogleCredentialDrive一致,以获取文件列表,如下,

private static List<File> retrieveFiles(Drive service) throws IOException{
    List<File> result = new ArrayList<File>();
    Files.List request = service.files().list();
    do {
        try{
            FileList fileList = request.execute();
            result.addAll(fileList.getItems());
            request.setPageToken(fileList.getNextPageToken());

        }catch (IOException e){
            Log.d(dbgT + "JavaRetrieveFiles", "Retrieved Failed");
            request.setPageToken(null);
        }
    }while (request.getPageToken() != null && request.getPageToken().length() > 0);

    return result;
}

private class RetrieveTokenTask extends AsyncTask<String, Void, String>{

    @Override
    protected String doInBackground(String... params){
        String accountName = params[0];
        String scopes = "oauth2:" + "https://www.googleapis.com/auth/drive";
        String token = null;

        try{
            token = GoogleAuthUtil.getToken(getApplicationContext(), accountName, scopes);
        }
        catch (IOException e){
            Log.e(excpTAG, "IO Exception: " + e.getMessage());
        }
        catch (UserRecoverableAuthException e){
            startActivityForResult(e.getIntent(), REQ_SIGN_IN_REQUIRED);
        }
        catch (GoogleAuthException e)
        {
            Log.e(excpTAG, "GoogleAuthException: " + e.getMessage());
        }

        return token;
    }

    @Override
    protected void onPostExecute(String s){
        super.onPostExecute(s);

        //Get Access Token
        Log.d( dbgT + "Token", s);
        EditText tokenText = (EditText) findViewById(R.id.tokenText);
        tokenText.setText(s);

        EditText fileNameText = (EditText) findViewById(R.id.editTextMeta);

        GoogleCredential credential = new GoogleCredential().setAccessToken(s);
        HttpTransport httpTransport = new NetHttpTransport();
        JsonFactory jsonFactory = new JacksonFactory();
        Drive service = new Drive.Builder(httpTransport, jsonFactory, null).setHttpRequestInitializer(credential).build();

        List<File> fileList;
        try{
            fileList = retrieveFiles(service);
            for(int i=0; i< fileList.size(); i++)
                fileNameText.append(fileList.get(i).getTitle());
        }catch(IOException e){
            Log.d(dbgT + "RetrieveFileList", "IO Exception" );
        }

    }
}

不幸的是,当调用request.execute()中的retrieveFiles时,应用程序始终因 NetworkOnMainThreadException 的原因而崩溃。

我检查了访问令牌s,它通常采用ya29.xxx...etc.的形式,也可以传递给我的其他.NET程序,以便从Google云端硬盘中检索文件。因此,我可以确定访问令牌是正确的。

所以我的问题是,如何使用访问令牌创建正确的GoogleCredential,而不是在setFromTokenResponse中应用授权代码?

提前致谢。

1 个答案:

答案 0 :(得分:1)

非常感谢Andy的提示,这个问题只是由主线程上的网络操作引起的,这是一个非常基本的新手错误。

Google Drive SDK for Java中的Drive,使用没有任何后台/线程工作者的网络库,现在它在我将retrieveFiles()置于后台后正常运行。

在Google Play Android SDK中应用GoogleAuthUtil获取访问令牌,然后在Java SDK中使用GoogleCredential + Drive使用令牌在Google云端硬盘中执行文件操作

这是避免Android SDK for Google Drive中范围限制的正确方法,允许开发人员获得访问Google云端硬盘的完全许可。