3

次のコードを実行しようとしています (主に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...\n\nThis 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");
        }
    }   
}

ただし、次の例外が発生します。

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 の両方を有効にしました。ここに、私のドライブ SDK 設定のスナップショットをいくつか示します。 ここに画像の説明を入力 ここに画像の説明を入力 写真に写っていないクライアント ID セクションについては、API アクセス セクションから「インストール済みアプリケーションのクライアント ID」を貼り付けただけです (「ドライブ SDK のクライアント ID」も試しました)。 )。誰が問題が何であるか知っていますか?

4

2 に答える 2

7

編集: 申し訳ありませんが、debug.keystore を使用してデバッグ モードで apk に署名できることに気付きました。そのため、最も重要なことは、正しい SHA1 キーを Google API コンソールに挿入することです。(Stephen Wylie の Google+ 投稿で言及されているように、JRE7 ツールを使用して生成されます)

キーストアのパスワードについては、(developer.android.com/tools/publishing/app-signing.html#debugmode) も参照してください。

試行錯誤の末、ようやくgoogleドライブのファイル一覧ができるようになりましたこれが正解かどうかはわかりませんが、少なくともファイル一覧はできるようになりました

まず、Stephen Wylie が更新した Google+ の投稿https://plus.google.com/u/0/114042449736049687152/posts/CD3L8zcJg5Zを参照して ください。

JRE7 ツールを使用して、.keystore で SHA1 キーを生成します

Google Playストアで使用していた.keystoreファイルを使用しています(キーストアがない場合は、プロジェクトに移動してエクスポートをクリックすると、.keystoreファイルを作成するように求められます)

生成された SHA1 キーを使用して、Google API コンソールに移動します (最初から開始し、現在のプロジェクトを削除して、新しいプロジェクトを開始するのが最適です)。

- ドライブ API を有効にする

-Drive SDK を有効にする

-API アクセスに移動

-クライアント ID の作成

-ここで重要、Installed application & Androidを選択

-また、重要です。生成された SHA1 キーを入力してください

-eclipse プロジェクトで使用している正しいパッケージ名 (com.example.xxx) のキー

-Drive SDK タブに移動 -アップロード アイコン

-重要、[API アクセス] タブからクライアント ID (インストール済みアプリケーションのクライアント ID) を入力してください

-Stephen Wylie の投稿で言及されている 3 つのスコープを挿入 [/userinfo.email、/userinfo.profile、/auth/drive]

-URL を挿入

-複数ファイルのサポートにチェックを入れる

繰り返しますが、コード内のパッケージ名が、Google API コンソールに挿入したパッケージ名と同じであることを確認してください

最後に、Eclipse で、今作成した .keystore ファイルを使用してプロジェクトをエクスポートします。

エクスポートした APK ファイルを携帯電話に入れ、インストールして試してください。

LogCat をチェックして、Google ドライブからリストされたファイルを表示します

この方法で成功しました。

編集済み: debug.keystore を使用して SHA1 キーを生成した場合は、「エクスポート」の部分をスキップできます。アプリケーションをデバッグするだけでOKです。Eclipse は、debug.keystore で apk に自動的に署名します。

編集済み: 次回コードの準備ができたら、実際の .keystore を使用して新しい SHA1 キーを生成し、Google API コンソールに入力する必要があります。

EDITED 2:マニフェストにこれらが含まれていることを確認してください

<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" />

使った瓶 輸入品

于 2012-11-24T16:59:26.563 に答える
3

この問題も発生し、すぐに「GoogleAPIコンソール>サービス」で間違った「サービス」を有効にしたことに気付きました。「DriveSDK」ではなく「DriveAPI」を有効にしてからアプリケーションを試してください。

手順:
1)https://code.google.com/apis/console
に移動します 2)ドロップダウンから正しいアプリケーション/プロジェクトを選択します
3)[サービス]に移動します
4)[オン]に切り替えます''ドライブAPI'

于 2012-11-20T17:25:44.013 に答える