Android打开并保存文件到/从Google Drive SDK

我已经花了六个小时从谷歌的文件倾吐,我仍然不知道如何开始这个。 我想要做的就是让现有的Android应用可以读取Google云端硬盘中的文件,将新文件上传到Google云端硬盘,并编辑Google云端硬盘上的现有文件。

我已经读过Drive Drive v2只专注于让Android(以及普通移动平台)的开发人员能够轻松使用它,但似乎在他们的文档中几乎没有任何关于它的内容。

理想情况下,我希望有人指出一些体面的文档,示例或教程,介绍如何做到这一点(请记住,我使用Android,他们有很多关于如何使用Google App Engine的Drive;我已经看过它,我不知道如何去从Android应用程序。)

我需要知道哪些库需要下载并添加到我的项目中,我需要添加到清单中,以及如何最终从Google Drive获取文件列表,下载一个文件,然后上载修改后的版本。

理想情况下,我希望它能够自动处理帐户,这是官方Google云端硬盘应用所采用的方式。


编辑:克劳迪奥Cherubino说,谷歌播放服务现在可用,并将使这个过程更容易。 然而,没有示例代码可用(然而,他表示即将推出......他们表示Google Play服务在4个月前即将推出,所以很有可能这个答案将继续成为访问2013年Android应用中的Google Drive。)

编辑2X:看起来我差一个月左右,当时我说Google直到明年才会有一个工作的例子。 谷歌的官方指南已经在这里:

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

我还没有测试过他们的方法,所以从2012年9月开始我的解决方案(下图)仍然是最好的:

Google Play服务不是必需的。 这是一个痛苦的屁股,我花了超过50个小时(编辑:100多个小时)搞清楚了这一切,但有很多事情,这将有助于知道:

图书馆

对于Google的在线服务,您一般需要在项目中使用这些库:(说明和下载链接)

  • 谷歌的API客户端-1.11.0-beta.jar
  • 谷歌的API客户端,Android的1.11.0-beta.jar
  • 谷歌-HTTP的客户端1.11.0-beta.jar
  • 谷歌-HTTP的客户端Android的1.11.0-beta.jar
  • 谷歌-HTTP客户端 - 杰克逊-1.11.0-beta.jar
  • 谷歌-OAuth的客户端1.11.0-beta.jar
  • 番石榴11.0.1.jar
  • 杰克逊核心ASL-1.9.9.jar
  • jsr305-1.3.9.jar
  • 特别是对于Google云端硬盘,您还需要这样做:

  • 谷歌API服务驱动器V2的rev9-1.8.0-beta.jar(下载链接)
  • 设置控制台

    接下来,转到Google控制台。 制作一个新项目。 在Services下,您需要打开两件事: DRIVE APIDRIVE SDK ! 他们是分开的,一个不会自动打开另一个,并且你必须打开两个! (弄清楚这一点浪费了我至少20个小时的时间。)

    仍然在控制台上,转到API访问。 创建一个客户端,使其成为一个Android应用程序。 给它你的包ID。 我不认为指纹的确是非常重要的,因为我敢肯定我使用了错误的指纹,但是无论如何都要努力做到这一点(Google为它提供了说明)。

    它会生成一个客户端ID 。 你将需要这个。 坚持下去。

    编辑:我听说我错了,只需要打开Drive API,Drive SDK根本不需要打开,而且您只需使用Simple API Key,而不是设置为Android设置一些东西。 我现在正在研究这个问题,如果我想出来,可能会在几分钟内编辑这个答案......

    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...
            }
        }
    }
    

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

    最后一件事......如果这个意图被发送出去,当它返回结果时你需要处理。

    @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.
        }
    }
    

    ANDROID CODE - 更新

    有关更新Google云端硬盘上文件上次修改日期的两个简要说明:

  • 您必须提供完全初始化的DateTime。 如果您不这样做,您会收到来自Google云端硬盘的“错误请求”响应。
  • 您必须在更新请求本身上使用来自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下载管理器下载它们。

    如果您在模拟器上进行测试,请确保其目标是Google API,而不是通用Android。

    您需要在您的测试设备上设置Google帐户。 编写的代码将自动使用它找到的第一个Google帐户(这就是[0]所代表的内容。)IDK,如果您需要下载Google Drive应用才能发挥作用。 我正在使用API​​ Level 15,我不知道这段代码会工作多久。

    其余的部分

    上述应该让你开始,希望你能从那里找出你的出路......说实话,这是迄今为止我所得到的。 我希望这能帮助很多人并为他们节省很多时间。 我相当肯定,我刚刚编写了最全面的设置指南,以设置安装Google应用的Android应用。 在Google上感到羞耻,因为至少在6个不同的页面之间传播必要的材料,而这些页面根本不相互链接。


    从Google I / O中查看此视频,了解如何将您的Android应用与云端硬盘进行整合:

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

    请注意,您在视频中看到的内容基于Google Play服务,但尚未向公众发布:

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


    这是2015年,事情已经改变!

    使用gradle获取“适用于Android的Drive API”:

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

    有一些新的doco(尽管IMO仍然乏善可陈):

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

    对于那些即将崩溃的人来说......迄今为止我遇到的最大问题是,绝对没有办法区分已经从正常文件夹中永久删除的文件夹......你可以找到它们,你可以创建文件夹和其中的文件,只写入文件DriveContents将始终失败。

    链接地址: http://www.djcxy.com/p/63047.html

    上一篇: Android Open and Save files to/from Google Drive SDK

    下一篇: Google Drive SDK Permissions by file/folder