Google 云端硬盘 SDK 异常 [英] Google Drive SDK Exception

查看:21
本文介绍了Google 云端硬盘 SDK 异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试运行以下代码(主要来自 Stephen Wylie):

I am trying to run the following code (taken largely from Stephen Wylie):

package com.googledrive.googledriveapp;
// For Google Drive / Play Services
// Version 1.1 - Added new comments & removed dead code
// Stephen Wylie - 10/20/2012
import java.io.IOException;
import java.util.ArrayList;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import com.google.android.gms.auth.GoogleAuthException;
import com.google.android.gms.auth.GoogleAuthUtil;
import com.google.android.gms.auth.UserRecoverableAuthException;
import com.google.android.gms.common.AccountPicker;
import com.google.api.client.auth.oauth2.BearerToken;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.android2.AndroidHttp;
import com.google.api.client.googleapis.extensions.android2.auth.GoogleAccountManager;
import com.google.api.client.http.HttpRequestFactory;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.json.JsonHttpRequest;
import com.google.api.client.http.json.JsonHttpRequestInitializer;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.Drive.Apps.List;
import com.google.api.services.drive.Drive.Files;
import com.google.api.services.drive.DriveRequest;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import com.google.api.services.drive.model.FileList;

public class MainActivity extends Activity {
    private static final int CHOOSE_ACCOUNT=0;
    private static String accountName;
    private static int REQUEST_TOKEN=0;
    private Button btn_drive;
    private Context ctx = this;
    private Activity a = this;

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        // set up the GUI layout
        setContentView(R.layout.activity_main);
        // set the variables to access the GUI controls
        btn_drive = (Button) findViewById(R.id.btn_drive);
            btn_drive.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                chooseAccount();
            }
            });
    }

    public void chooseAccount() {
        Intent intent = AccountPicker.newChooseAccountIntent(null, null, new String[]{"com.google"}, false, null, null, null, null);
        startActivityForResult(intent, CHOOSE_ACCOUNT);
    }

    // Fetch the access token asynchronously.
    void getAndUseAuthTokenInAsyncTask(Account account) {
        AsyncTask<Account, String, String> task = new AsyncTask<Account, String, String>() {
            ProgressDialog progressDlg;
            AsyncTask<Account, String, String> me = this;

            @Override
            protected void onPreExecute() {
                progressDlg = new ProgressDialog(ctx, ProgressDialog.STYLE_SPINNER);
                progressDlg.setMax(100);
                progressDlg.setTitle("Validating...");
                progressDlg.setMessage("Verifying the login data you entered...

This action will time out after 10 seconds.");
                progressDlg.setCancelable(false);
                progressDlg.setIndeterminate(false);
                progressDlg.setOnCancelListener(new android.content.DialogInterface.OnCancelListener() {
                    public void onCancel(DialogInterface d) {
                        progressDlg.dismiss();
                        me.cancel(true);
                    }
                });
                progressDlg.show();
            }

            @Override
            protected String doInBackground(Account... params) {
                return getAccessToken(params[0]);
            }

            @Override
            protected void onPostExecute(String s) {
                if (s == null) {
                    // Wait for the extra intent
                } else {
                    accountName = s;
                    getDriveFiles();
                }
                progressDlg.dismiss();
            }
        };
        task.execute(account);
    }

    /**
     * Fetches the token from a particular Google account chosen by the user.  DO NOT RUN THIS DIRECTLY.  It must be run asynchronously inside an AsyncTask.
     * @param activity
     * @param account
     * @return
     */
    private String getAccessToken(Account account) {
        try {
            return GoogleAuthUtil.getToken(ctx, account.name, "oauth2:" + DriveScopes.DRIVE);  // IMPORTANT: DriveScopes must be changed depending on what level of access you want
        } catch (UserRecoverableAuthException e) {
            // Start the Approval Screen intent, if not run from an Activity, add the Intent.FLAG_ACTIVITY_NEW_TASK flag.
            a.startActivityForResult(e.getIntent(), REQUEST_TOKEN);
            e.printStackTrace();
            return null;
        } catch (GoogleAuthException e) {
            e.printStackTrace();
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    private Drive getDriveService() {
        HttpTransport ht = AndroidHttp.newCompatibleTransport();             // Makes a transport compatible with both Android 2.2- and 2.3+
        JacksonFactory jf = new JacksonFactory();                            // You need a JSON parser to help you out with the API response
        Credential credential = new Credential(BearerToken.authorizationHeaderAccessMethod()).setAccessToken(accountName);
        HttpRequestFactory rf = ht.createRequestFactory(credential);
        Drive.Builder b = new Drive.Builder(ht, jf, null);
        b.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {

            @Override
            public void initialize(JsonHttpRequest request) throws IOException {
                DriveRequest driveRequest = (DriveRequest) request;
                driveRequest.setPrettyPrint(true);
                driveRequest.setOauthToken(accountName);
            }
        });
        return b.build();
    }

    /**
     * Obtains a list of all files on the signed-in user's Google Drive account.
     */
    private void getDriveFiles() {
        Drive service = getDriveService();
        Log.d("SiteTrack", "FUNCTION getDriveFiles()");
        Files.List request;
        try {
            request = service.files().list(); // .setQ("mimeType="text/plain"");
        } catch (IOException e) {


            e.printStackTrace();
            return;
        }
        do {
            FileList files;
            try {
                System.out.println("got here");
                Log.d("SiteTrack", request.toString());
                **files = request.execute();**
            } catch (IOException e) {
                e.printStackTrace();
                Log.d("SiteTrack", "Exception");
                return;
            }
            ArrayList<File> fileList = (ArrayList<File>) files.getItems();
            Log.d("SiteTrack", "Files found: " + files.getItems().size());
            for (File f : fileList) {
                String fileId = f.getId();
                String title = f.getTitle();
                Log.d("SiteTrack", "File " + fileId + ": " + title);
            }
            request.setPageToken(files.getNextPageToken());
        } while (request.getPageToken() != null && request.getPageToken().length() >= 0);
    }

    protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
        if (requestCode == CHOOSE_ACCOUNT && resultCode == RESULT_OK) {
            accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
            GoogleAccountManager gam = new GoogleAccountManager(this);
            getAndUseAuthTokenInAsyncTask(gam.getAccountByName(accountName));
            Log.d("SiteTrack", "CHOOSE_ACCOUNT");
        } else if (requestCode == REQUEST_TOKEN && resultCode == RESULT_OK) {
            accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
            Log.d("SiteTrack", "REQUEST_TOKEN");
        }
    }   
}

但是,我收到以下异常:

However, I get the following exception:

11-19 16:35:27.758: W/System.err(23287): com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
11-19 16:35:27.758: W/System.err(23287): {
11-19 16:35:27.758: W/System.err(23287):   "code" : 403,
11-19 16:35:27.758: W/System.err(23287):   "errors" : [ {
11-19 16:35:27.758: W/System.err(23287):     "domain" : "usageLimits",
11-19 16:35:27.762: W/System.err(23287):     "message" : "Access Not Configured",
11-19 16:35:27.762: W/System.err(23287):     "reason" : "accessNotConfigured"
11-19 16:35:27.762: W/System.err(23287):   } ],
11-19 16:35:27.762: W/System.err(23287):   "message" : "Access Not Configured"
11-19 16:35:27.762: W/System.err(23287): }
11-19 16:35:27.762: W/System.err(23287):    at com.google.api.client.googleapis.services.GoogleClient.executeUnparsed(GoogleClient.java:237)
11-19 16:35:27.762: W/System.err(23287):    at com.google.api.client.http.json.JsonHttpRequest.executeUnparsed(JsonHttpRequest.java:207)
11-19 16:35:27.762: W/System.err(23287):    at com.google.api.services.drive.Drive$Files$List.execute(Drive.java:1071)
11-19 16:35:27.762: W/System.err(23287):    at com.googledrive.googledriveapp.MainActivity.getDriveFiles(MainActivity.java:173)
11-19 16:35:27.762: W/System.err(23287):    at com.googledrive.googledriveapp.MainActivity.access$3(MainActivity.java:156)
11-19 16:35:27.762: W/System.err(23287):    at com.googledrive.googledriveapp.MainActivity$2.onPostExecute(MainActivity.java:104)
11-19 16:35:27.765: W/System.err(23287):    at com.googledrive.googledriveapp.MainActivity$2.onPostExecute(MainActivity.java:1)
11-19 16:35:27.765: W/System.err(23287):    at android.os.AsyncTask.finish(AsyncTask.java:417)
11-19 16:35:27.765: W/System.err(23287):    at android.os.AsyncTask.access$300(AsyncTask.java:127)
11-19 16:35:27.765: W/System.err(23287):    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:429)
11-19 16:35:27.765: W/System.err(23287):    at android.os.Handler.dispatchMessage(Handler.java:99)
11-19 16:35:27.765: W/System.err(23287):    at android.os.Looper.loop(Looper.java:123)
11-19 16:35:27.765: W/System.err(23287):    at android.app.ActivityThread.main(ActivityThread.java:4627)
11-19 16:35:27.765: W/System.err(23287):    at java.lang.reflect.Method.invokeNative(Native Method)
11-19 16:35:27.769: W/System.err(23287):    at java.lang.reflect.Method.invoke(Method.java:521)
11-19 16:35:27.769: W/System.err(23287):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
11-19 16:35:27.769: W/System.err(23287):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
11-19 16:35:27.769: W/System.err(23287):    at dalvik.system.NativeStart.main(Native Method)

可追溯到我上面代码中的 files = request.execute(); 行(我用星号标记了它).我在 Google API 控制台中同时启用了 Drive SDK 和 Drive API.以下是我的 Drive SDK 设置的几个快照:对于未显示的客户端 ID 部分,我只是粘贴了 API 访问部分中的已安装应用程序的客户端 ID"(我也尝试了Drive SDK 的客户端 ID").有人知道问题出在哪里吗?

which traces to the line files = request.execute(); in my code above (I have marked it with asterisks). I have enabled both the Drive SDK and the Drive API in my Google APIs Console. Here are a couple of snapshots of my Drive SDK settings: For the Client ID section that is not pictured, I simply pasted the "Client ID for installed applications" from the API Access section (I also tried the "Client ID for Drive SDK"). Anyone know what the problem is?

推荐答案

已抱歉,我刚刚意识到我们可以使用 debug.keystore 在调试模式下对 apk 进行签名.所以,最重要的是在您的 Google API 控制台中插入正确的 SHA1 密钥.(使用 Stephen Wylie 在他的 Google+ 帖子中提到的 JRE7 工具生成)

EDITED: Sorry I just realized that we can sign the apk in debugging mode using debug.keystore. SO, the most important thing is insert the correct SHA1 key in your Google API console. (generated using the JRE7 tool as mentioned by Stephen Wylie in his Google+ post)

另请参阅 (developer.android.com/tools/publishing/app-signing.html#debugmode) 以获取密钥库密码

Also see (developer.android.com/tools/publishing/app-signing.html#debugmode) for the keystore password

经过反复试验,我终于能够在我的谷歌驱动器中列出文件虽然我不确定这是否是最正确的答案,但至少我现在可以列出文件

After some trial and error, I finally able to list files in my google drive Although I am not sure whether this is the most correct answer, but at least I am able to list files now

首先,请参考 Stephen Wylie 更新的 Google+ 帖子https://plus.google.com/u/0/114042449736049687152/posts/posts/posts/CD3L8zcJg5Z

First, please refer to Stephen Wylie updated Google+ post https://plus.google.com/u/0/114042449736049687152/posts/CD3L8zcJg5Z

使用 JRE7 工具使用您的 .keystore 生成 SHA1 密钥

generate the SHA1 key with your .keystore using the JRE7 tool

我正在使用我在 Google Play 商店中使用的 .keystore 文件(如果你没有keystore,你可以到你的项目中,点击export,然后它会要求你创建一个.keystore文件)

I am using the .keystore file that I had been using with my google play store (If you do not have any keystore, you can go to your project, click export, then it will request you to create a .keystore file)

使用生成的 SHA1 密钥,转到您的 Google API 控制台(最好从新开始,删除当前项目并开始一个新项目)

with the generated SHA1 key, go to your Google API console (it is best if you start from fresh, delete the current project and start a new one)

-启用 Drive API

-enable Drive API

-启用云端硬盘 SDK

-enable Drive SDK

-转到 API 访问

-创建客户端 ID

-重要在这里,选择已安装的应用程序 &安卓

-IMPORTANT here, choose Installed application & Android

-同样重要的是,输入您生成的 SHA1 密钥

-ALSO IMPORTANT, key in your generated SHA1 key

-键入您在 eclipse 项目中使用的正确包名称 (com.example.xxx)

-key in your CORRECT package name (com.example.xxx) that you are using in your eclipse project

-转到 Drive SDK 选项卡-上传图标

-Go to Drive SDK tab -upload icon

-重要提示,在 API Access 选项卡中输入您的 CLIENT ID(已安装应用程序的客户端 ID)

-IMPORTANT, key in your CLIENT ID (Client ID for installed applications) from the API Access tab

-插入 Stephen Wylie 帖子中提到的 3 个范围,[/userinfo.email,/userinfo.profile,/auth/drive]

-Insert 3 scopes mentioned in Stephen Wylie post, [/userinfo.email, /userinfo.profile, /auth/drive]

-插入网址

-勾选多个文件支持

再次确保代码中的包名称与插入到 Google API 控制台的包名称相同

Again, make sure your package name in your code is same as the package name you inserted into Google API Console

最后,在eclipse中,使用刚才创建的.keystore文件导出你的项目

Finally, in eclipse, export your project using the .keystore file you created just now

将导出的APK文件放入手机,安装试试.

Put the exported APK file into your phone, install and try.

检查您的 LogCat 以显示您的 Google Drive 中列出的文件

Check your LogCat to show the listed files from your Google Drive

我已经成功地使用了这种方式.

I had succeeded using this way.

已如果您使用 debug.keystore 生成了 SHA1 密钥,则可以跳过导出"部分.只需调试您的应用程序就可以了.Eclipse 将自动使用 debug.keystore 对 apk 进行签名.

EDITED: If you generated the SHA1 key with the debug.keystore, you can skip the "Export" part. Just debug your application is OK. Eclipse will automatically sign the apk with debug.keystore.

已下次您的代码准备好时,您需要使用真实的 .keystore 生成一个新的 SHA1 密钥,然后输入到 Google API 控制台.

EDITED: Next time your code is ready, you need to generate a new SHA1 key with your real .keystore, then input into the Google API console.

编辑 2:确保您的清单包含这些

EDITED 2: Make sure your manifest include these

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />

这篇关于Google 云端硬盘 SDK 异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆