Android在Google Drive SDK中打开并保存文件

Android在Google Drive SDK中打开并保存文件,android,google-drive-api,Android,Google Drive Api,在过去的六个小时里,我一直在浏览来自谷歌的文档,但我仍然不知道如何开始。我想做的就是让我现有的安卓应用程序能够从谷歌硬盘读取文件,将新文件上传到谷歌硬盘,并在谷歌硬盘上编辑现有文件 我曾读到,DriveSDKv2只专注于让Android(以及一般的移动设备)开发人员更容易地使用它,但在他们的文档中似乎什么都没有 理想情况下,我希望有人能提供一些关于如何实现这一点的文档、示例或教程(请记住,我使用的是Android。他们有很多关于如何在Google App Engine中使用Drive的内容;我已

在过去的六个小时里,我一直在浏览来自谷歌的文档,但我仍然不知道如何开始。我想做的就是让我现有的安卓应用程序能够从谷歌硬盘读取文件,将新文件上传到谷歌硬盘,并在谷歌硬盘上编辑现有文件

我曾读到,DriveSDKv2只专注于让Android(以及一般的移动设备)开发人员更容易地使用它,但在他们的文档中似乎什么都没有

理想情况下,我希望有人能提供一些关于如何实现这一点的文档、示例或教程(请记住,我使用的是Android。他们有很多关于如何在Google App Engine中使用Drive的内容;我已经看过了,但我不知道如何从这些内容过渡到Android应用。)

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


理想情况下,我希望它能像官方的Google Drive应用程序那样自动处理帐户。

查看Google I/O的视频,了解如何将Android应用程序与Drive集成:

请注意,您在视频中看到的内容基于Google Play服务:


编辑:克劳迪奥·切鲁比诺说,谷歌游戏服务现在可以使用了,这将使这一过程更加容易。然而,没有可用的示例代码(然而,他说它很快就会出现……他们说Google Play服务在4个月前“很快就会出现”,所以这个答案很有可能在2013年继续成为从Android应用程序访问Google Drive的唯一完全有效的示例。)

编辑2X:我说谷歌要到明年才能有一个有效的例子时,我好像离开了大约一个月。谷歌的官方指南在这里:

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

谷歌播放服务是不需要的。我花了50多个小时(编辑:100多个小时)把这一切都弄清楚了,但这里有很多东西可以帮助我了解:

图书馆

对于谷歌的在线服务,您通常需要在项目中使用这些库:()

  • 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 Drive,您还需要:

  • google-api-services-drive-v2-rev9-1.8.0-beta.jar()
设置控制台

下一步,转到。做一个新项目。在“服务”下,您需要打开两个选项:驱动器API驱动器SDK!它们是分开的,一个不会自动打开另一个,并且必须同时打开两个(弄明白这一点至少浪费了我20个小时的时间。)

仍然在控制台上,转到API访问。创建一个客户端,使其成为Android应用程序。给它你的bundle ID。我不认为指纹这件事实际上很重要,因为我很确定我用错了,但无论如何都要努力做到正确(谷歌提供了相关说明)

它将生成一个客户端ID。你会需要的。坚持住

编辑:我被告知我错了,你只需要打开驱动API,驱动SDK根本不需要打开,你只需要使用简单的API键,而不是为Android设置一些东西。我现在正在研究这个问题,如果我弄明白了,我可能会在几分钟内编辑这个答案

ANDROID代码-设置和上传

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;
    }
}
首先,获取身份验证令牌:

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...
        }
    }
}
最后一件事。。。如果该意图被发送出去,您将需要处理它何时返回并产生结果

@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代码-更新

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;
    }
}
关于更新Google Drive上文件的上次修改日期的两个简要说明:

  • 必须提供完全初始化的日期时间。如果您不这样做,您将从谷歌硬盘得到“坏请求”的响应
  • 您必须对来自Google Drive的文件使用setModifiedDate(),对更新请求本身使用setModifiedDate(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();
    }
    
    清单

    您将需要以下权限:获取\u帐户、使用\u凭据、管理\u帐户、INTERNET,而且您很可能还需要写入\u外部\u存储,具体取决于您希望存储文件本地副本的位置

    您的构建目标

    右键单击您的项目,进入它的属性,如果必须,在Android下将构建目标更改为GoogleAPI。如果没有,请从android下载管理器下载

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

    您需要在测试设备上设置一个Google帐户。如果您需要下载Google Drive应用程序才能正常工作,那么编写的代码将自动使用它找到的第一个Google帐户(这就是[0])IDK。我使用的是API级别15,我不知道这段代码能运行多久

    其余的

    以上应该让你开始,希望你能找到你的出路。。。老实说,这只是ab