6

Stephen Wylie の Google Drive の例 (ここ) を実装しようとしています。これが私のコードです:

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

これが私のマニフェストです:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.googledrive.googledriveapp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="android.app.ActivityGroup" />
        </activity>
    </application>
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

ここに私の activity_main.xml があります:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/btn_drive"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Connect to Google Drive" />
</LinearLayout>

そして、これが私が受け取ったLogCatエラーです。ボタンが押されると発生します。

10-28 00:25:28.637: E/AndroidRuntime(842): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=com.google.android.gms.common.account.CHOOSE_ACCOUNT (has extras) }
10-28 00:25:28.637: E/AndroidRuntime(842):  at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1512)
10-28 00:25:28.637: E/AndroidRuntime(842):  at android.app.Instrumentation.execStartActivity(Instrumentation.java:1384)
10-28 00:25:28.637: E/AndroidRuntime(842):  at android.app.Activity.startActivityForResult(Activity.java:3190)
10-28 00:25:28.637: E/AndroidRuntime(842):  at com.googledrive.googledriveapp.MainActivity.chooseAccount(MainActivity.java:67)
10-28 00:25:28.637: E/AndroidRuntime(842):  at com.googledrive.googledriveapp.MainActivity$1.onClick(MainActivity.java:60)
10-28 00:25:28.637: E/AndroidRuntime(842):  at android.view.View.performClick(View.java:3511)
10-28 00:25:28.637: E/AndroidRuntime(842):  at android.view.View$PerformClick.run(View.java:14105)
10-28 00:25:28.637: E/AndroidRuntime(842):  at android.os.Handler.handleCallback(Handler.java:605)
10-28 00:25:28.637: E/AndroidRuntime(842):  at android.os.Handler.dispatchMessage(Handler.java:92)
10-28 00:25:28.637: E/AndroidRuntime(842):  at android.os.Looper.loop(Looper.java:137)
10-28 00:25:28.637: E/AndroidRuntime(842):  at android.app.ActivityThread.main(ActivityThread.java:4424)
10-28 00:25:28.637: E/AndroidRuntime(842):  at java.lang.reflect.Method.invokeNative(Native Method)
10-28 00:25:28.637: E/AndroidRuntime(842):  at java.lang.reflect.Method.invoke(Method.java:511)
10-28 00:25:28.637: E/AndroidRuntime(842):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
10-28 00:25:28.637: E/AndroidRuntime(842):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
10-28 00:25:28.637: E/AndroidRuntime(842):  at dalvik.system.NativeStart.main(Native Method)

誰でも助けてもらえますか?

4

2 に答える 2

8

私たちはいくつかの実験を行ってきましたが、現在の理論では、新しい Google OAuth ライブラリは最新バージョンの Google Play に依存しているというものです。

お使いのデバイスにまだ Android Marketplace または古い Google Play がある場合、OAuth を機能させることができないことがわかりました。

そのため、Android マーケットプレイスまたは Google Play アプリを開いてアップグレードを開始してみてください。

Android マーケットプレイスを開き、Google Play へのアップグレードに同意します。
マーケットプレイスを閉じて、Google Play アプリを開きます。Google Play の利用規約に同意します。数秒待ってニワトリを犠牲にすると、Google OAuth を実行できるようになります。

編集: Google Play の正しいバージョンがユーザーにない場合にアプリが何をすべきかについて、Google がいくつかのガイダンスを提供しているようです。参照: https://developer.android.com/google/play-services/setup.html#ensure

于 2012-12-19T19:22:04.073 に答える
7

Google Drive APIは(Googleの人々によると)実際のデバイスでのみ機能するようです。エミュレーターでは、このエラーでクラッシュします。

だから私のアドバイスは、実際のデバイスで試してみてください。

于 2012-11-12T11:25:35.227 に答える