android - 通过访问 token 创建 GoogleCredential

标签 android google-drive-api google-oauth

我想为 Google Drive 设计一个 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 中不是一种获取访问 token 的实用方法。

另辟蹊径,我使用Android API中的GoogleAuthUtil获取Access Token,恰逢GoogleCredentialDrive在 Java API 中获取文件列表,如下所示,

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" );
        }

    }
}

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

我检查了我的访问 token s,它通常是ya29.xxx...etc.的形式,它也可以传递给我的其他.NET从 Google Drive 检索文件的程序。因此我可以确定访问 token 是正确的。

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

提前致谢。

最佳答案

非常感谢Andy的提示,这个问题很简单是主线程上发生了网络操作导致的,这是一个非常基本的新手错误。

Google Drive SDK for Java 中的 Drive,使用没有任何后台/线程 worker 的网络库,现在在我将 retrieveFiles() 放入后台后它可以正常工作.

应用Google Play Android SDK中的GoogleAuthUtil获取access token,然后Java SDK中的GoogleCredential+Drive使用在 Google 云端硬盘中执行文件操作的 token 。

这是避免 Android SDK for Google Drive 范围限制的正确方法,允许开发者获得访问 Google Drive 的完整许可。

关于android - 通过访问 token 创建 GoogleCredential,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28872697/

相关文章:

android - 如何在 Activity 中收听 Geofence BroadcastReceiver?

android - 使用单个 ffmpeg 命令在视频中应用填充和写入文本

java - 如何更新 google drive api v3 java 中已有的文件

java - Google 云端硬盘缩略图链接没有 Google Apps 域信息

ios - OAuth 2嵌入式浏览器将被阻止

google-api - 如何在 G Suite 上通过同意屏幕请求域范围委派

android:使用 libgdx/universal-tween-engine 发布后移动到触摸位置

Android 应用程序可以离线和在线工作吗?我应该以哪种方式同步数据?

java - 在 google drive sdk 示例中找不到 Android 记事本提供程序类错误

go - 服务帐户流程-2条腿的Oauth Golang