61

過去 6 時間、Google からのドキュメントを大量に読み込んでいますが、これをどのように開始すればよいかまだわかりません。私がやりたいことは、既存の Android アプリが Google ドライブからファイルを読み取ったり、新しいファイルを Google ドライブにアップロードしたり、Google ドライブ上の既存のファイルを編集したりできるようにすることだけです。

Drive SDK v2 は、Android (およびモバイル全般) の開発者が簡単に使用できるようにすることのみに重点を置いていることを読んだことがありますが、それに関するドキュメントには事実上何もないようです。

理想的には、これを行う方法を説明する適切なドキュメント、例、またはチュートリアルを誰かに指摘してもらいたいと思います (私は Android を使用していることを覚えておいてください。Google App Engine でドライブを使用する方法についてはたくさんあります。すでに見たことがありますが、そこから Android アプリに移行する方法がわかりません。)

どのライブラリをダウンロードして自分のプロジェクトに追加する必要があるか、何をマニフェストに追加する必要があるか、最終的に Google ドライブからファイルのリストを取得してダウンロードし、変更したバージョンをアップロードする方法を知る必要があります。

理想的には、公式の Google Drive アプリが行うように、アカウントを自動的に処理することを望んでいます。

4

4 に答える 4

81

編集: Claudio Cherubino は、Google Play Services が利用可能になり、このプロセスがずっと簡単になると言っています。ただし、利用可能なサンプルコードはありません(まだ、彼はすぐに来ると言います...彼らはGoogle Playサービスが4か月前に「近日公開される」と述べたので、この回答がアクセスの唯一の完全に機能する例であり続ける可能性が高いです. Android アプリケーションから 2013 への Google ドライブ。)

編集 2X: Google が来年まで実用的な例を提供しないと言ったとき、私は約 1 か月ずれていたようです。Google の公式ガイドはこちら:

https://developers.google.com/drive/quickstart-android

私はまだ彼らの方法をテストしていないので、2012 年 9 月からの私の解決策 (以下) がまだ最良である可能性があります。

これには Google Play Services は必要ありません。それはお尻の痛みであり、私はそれをすべて理解するのに50時間以上(編集:100時間以上)費やしましたが、知っておくと役立つことがたくさんあります:

ライブラリ

一般に、Google のオンライン サービスでは、プロジェクトに次のライブラリが必要です: (手順とダウンロード リンク)

  • google-api-client-1.11.0-beta.jar
  • google-api-client-android-1.11.0-beta.jar
  • google-http-client-1.11.0-beta.jar
  • google-http-client-android-1.11.0-beta.jar
  • google-http-client-jackson-1.11.0-beta.jar
  • google-oauth-client-1.11.0-beta.jar
  • グアバ-11.0.1.jar
  • jackson-core-asl-1.9.9.jar
  • jsr305-1.3.9.jar

特に Google ドライブの場合は、これも必要になります。

コンソールのセットアップ

次に、Google コンソールに移動します。新しいプロジェクトを作成します。[サービス] で、 DRIVE APIDRIVE SDKの 2 つをオンにする必要があります。それらは別個のものであり、一方が他方を自動的にオンにするわけではなく、両方をオンにする必要があります。(これを理解することで、少なくとも 20 時間は一人で無駄になりました。)

引き続きコンソールで、API アクセスに移動します。クライアントを作成し、Android アプリにします。バンドル ID を指定します。間違ったものを使用したと確信しているので、指紋のことは実際には重要ではないと思いますが、とにかくそれを正しくするようにしてください(Googleはそのための指示を提供します.)

Client IDが生成されます。あなたはそれを必要とするでしょう。それを保持します。

編集: 私は間違っていて、Drive API を有効にするだけでよく、Drive SDK を有効にする必要はまったくなく、設定ではなく単純な API キーを使用するだけでよいと言われました。 Android向けの何かをアップします。私は今それを調べており、私がそれを理解した場合、おそらく数分でこの回答を編集します...

THE ANDROID CODE - セットアップとアップロード

まず、認証トークンを取得します。

AccountManager am = AccountManager.get(activity);
am.getAuthToken(am.getAccounts())[0],
    "oauth2:" + DriveScopes.DRIVE,
    new Bundle(),
    true,
    new OnTokenAcquired(),
    null);

次に、OnTokenAcquired() を次のように設定する必要があります。

private class OnTokenAcquired implements AccountManagerCallback<Bundle> {
    @Override
    public void run(AccountManagerFuture<Bundle> result) {
        try {
            final String token = result.getResult().getString(AccountManager.KEY_AUTHTOKEN);
            HttpTransport httpTransport = new NetHttpTransport();
            JacksonFactory jsonFactory = new JacksonFactory();
            Drive.Builder b = new Drive.Builder(httpTransport, jsonFactory, null);
            b.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {
                @Override
                public void initialize(JSonHttpRequest request) throws IOException {
                    DriveRequest driveRequest = (DriveRequest) request;
                    driveRequest.setPrettyPrint(true);
                    driveRequest.setKey(CLIENT ID YOU GOT WHEN SETTING UP THE CONSOLE BEFORE YOU STARTED CODING)
                    driveRequest.setOauthToken(token);
                }
            });

            final Drive drive = b.build();

            final com.google.api.services.drive.model.File body = new com.google.api.services.drive.model.File();
            body.setTitle("My Test File");
    body.setDescription("A Test File");
    body.setMimeType("text/plain");

            final FileContent mediaContent = new FileContent("text/plain", an ordinary java.io.File you'd like to upload. Make it using a FileWriter or something, that's really outside the scope of this answer.)
            new Thread(new Runnable() {
                public void run() {
                    try {
                        com.google.api.services.drive.model.File file = drive.files().insert(body, mediaContent).execute();
                        alreadyTriedAgain = false; // Global boolean to make sure you don't repeatedly try too many times when the server is down or your code is faulty... they'll block requests until the next day if you make 10 bad requests, I found.
                    } catch (IOException e) {
                        if (!alreadyTriedAgain) {
                            alreadyTriedAgain = true;
                            AccountManager am = AccountManager.get(activity);
                            am.invalidateAuthToken(am.getAccounts()[0].type, null); // Requires the permissions MANAGE_ACCOUNTS & USE_CREDENTIALS in the Manifest
                            am.getAuthToken (same as before...)
                        } else {
                            // Give up. Crash or log an error or whatever you want.
                        }
                    }
                }
            }).start();
            Intent launch = (Intent)result.getResult().get(AccountManager.KEY_INTENT);
            if (launch != null) {
                startActivityForResult(launch, 3025);
                return; // Not sure why... I wrote it here for some reason. Might not actually be necessary.
            }
        } catch (OperationCanceledException e) {
            // Handle it...
        } catch (AuthenticatorException e) {
            // Handle it...
        } catch (IOException e) {
            // Handle it...
        }
    }
}

THE ANDROID CODE - ダウンロード中

private java.io.File downloadGFileToJFolder(Drive drive, String token, File gFile, java.io.File jFolder) throws IOException {
    if (gFile.getDownloadUrl() != null && gFile.getDownloadUrl().length() > 0 ) {
        if (jFolder == null) {
            jFolder = Environment.getExternalStorageDirectory();
            jFolder.mkdirs();
        }
        try {

            HttpClient client = new DefaultHttpClient();
            HttpGet get = new HttpGet(gFile.getDownloadUrl());
            get.setHeader("Authorization", "Bearer " + token);
            HttpResponse response = client.execute(get);

            InputStream inputStream = response.getEntity().getContent();
            jFolder.mkdirs();
            java.io.File jFile = new java.io.File(jFolder.getAbsolutePath() + "/" + getGFileName(gFile)); // getGFileName() is my own method... it just grabs originalFilename if it exists or title if it doesn't.
            FileOutputStream fileStream = new FileOutputStream(jFile);
            byte buffer[] = new byte[1024];
            int length;
            while ((length=inputStream.read(buffer))>0) {
                fileStream.write(buffer, 0, length);
            }
            fileStream.close();
            inputStream.close();
            return jFile;
        } catch (IOException e) {        
            // Handle IOExceptions here...
            return null;
        }
    } else {
        // Handle the case where the file on Google Drive has no length here.
        return null;
    }
}

最後にもう 1 つ... そのインテントが送信された場合、結果が返されたときに処理する必要があります。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == 3025) {
        switch (resultCode) {
            case RESULT_OK:
                AccountManager am = AccountManager.get(activity);
                am.getAuthToken(Same as the other two times... it should work this time though, because now the user is actually logged in.)
                break;
            case RESULT_CANCELED:
                // This probably means the user refused to log in. Explain to them why they need to log in.
                break;
            default:
                // This isn't expected... maybe just log whatever code was returned.
                break;
        }
    } else {
        // Your application has other intents that it fires off besides the one for Drive's log in if it ever reaches this spot. Handle it here however you'd like.
    }
}

THE ANDROID CODE - 更新中

Google ドライブ上のファイルの最終更新日を更新する際の 2 つの簡単な注意事項:

  1. 完全に初期化された DateTime を提供する必要があります。そうしないと、Google ドライブから「Bad Request」という応答が返ってきます。
  2. File from Google Drive で setModifiedDate() を使用し、更新リクエスト自体で setSetModifiedDate(true) を使用する必要があります。(面白い名前ですね。「setSet[...]」、間違って入力するわけにはいきません...)

ファイル時間の更新を含む、更新を行う方法を示す簡単なサンプル コードを次に示します。

public void updateGFileFromJFile(Drive drive, File gFile, java.io.File jFile) throws IOException {
    FileContent gContent = new FileContent("text/csv", jFile);
    gFile.setModifiedDate(new DateTime(false, jFile.lastModified(), 0));
    gFile = drive.files().update(gFile.getId(), gFile, gContent).setSetModifiedDate(true).execute();
}

マニフェスト

次のアクセス許可が必要です: GET_ACCOUNTS、USE_CREDENTIALS、MANAGE_ACCOUNTS、INTERNET。ファイルのローカル コピーを保存する場所によっては、WRITE_EXTERNAL_STORAGE も必要になる可能性が高くなります。

あなたのビルドターゲット

プロジェクトを右クリックしてプロパティに移動し、必要に応じて Android でビルド ターゲットを Google API に変更します。そこにない場合は、Android ダウンロード マネージャーからダウンロードしてください。

エミュレーターでテストする場合は、そのターゲットが一般的な Android ではなく、Google API であることを確認してください。

テスト デバイスに Google アカウントを設定する必要があります。記述されたコードは、最初に見つかった Google アカウントを自動的に使用します (これが [0] です)。これが機能するために Google ドライブ アプリをダウンロードする必要がある場合は、IDK を使用します。私は API レベル 15 を使用していましたが、このコードがどこまで機能するかはわかりません。

残り

上記はあなたが始めるべきものであり、うまくいけばそこから抜け出す方法を理解できるはずです.正直なところ、これは私がこれまでに得たものとほぼ同じです. これが多くの人を助け、多くの時間を節約できることを願っています. Google ドライブを使用するように Android アプリをセットアップするための最も包括的なセットアップ ガイドを作成したと確信しています。相互にまったくリンクしていない少なくとも 6 つの異なるページに必要な資料を広めたことは、Google に恥をかかせます。

于 2012-09-07T15:41:10.477 に答える
4

Androidアプリをドライブと統合する方法については、Google I/Oのこの動画をご覧ください。

http://www.youtube.com/watch?v=xRGyzqD-vRg

ビデオに表示されているものは、GooglePlayサービスに基づいていることに注意してください。

https://developers.google.com/android/google-play-services/

于 2012-08-28T17:23:37.720 に答える
4

2015 年になり、状況が変わりました。

gradle を使用して「Drive API for Android」を取得します。

compile 'com.google.android.gms:play-services-drive:7.8.0'

いくつかの新しい doco があります (ただし、IMO はまだ精彩を欠いています):

https://developers.google.com/drive/web/quickstart/android

そして洞窟探検に行こうとしている人にとって...これまでに遭遇した最大の問題は、完全に削除されたフォルダーと通常のフォルダーを区別する方法がまったくないことです.それらを見つけることができ、フォルダーを作成し、それらの中のファイル、ファイル DriveContents への書き込みのみが常に失敗します。

于 2015-08-18T01:36:33.520 に答える