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

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

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

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

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

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

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

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

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

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

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客户端 – jackson-1.11.0-beta.jar
  • 谷歌-OAuth的客户端1.11.0-beta.jar
  • 番石榴11.0.1.jar
  • jackson核心ASL-1.9.9.jar
  • jsr305-1.3.9.jar

对于Google云端硬盘,您还需要这样做:

  • 谷歌的API – 服务驱动器-V2-rev9-1.8.0-beta.jar( 下载链接 )

设置控制台

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

仍然在控制台上,转到API访问。 创build一个客户端,使其成为一个Android应用程序。 给它你的包ID。 我不认为这个指纹实际上很重要,因为我敢肯定我使用了错误的指纹,不过我们仍然试着去修正它(Google提供了指示)。

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

编辑:我被告知,我错了,你只需要打开云端硬盘API,驱动器SDK根本不需要打开,你只需要使用简单的API密钥,没有设置为Android设置一些东西。 我现在正在研究这个问题,如果我想出来,可能会在几分钟内编辑这个答案。

ANDROID代码 – 设置和上传

首先,获取一个授权令牌:

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

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

  1. 您必须提供完全初始化的DateTime。 如果不这样做,您会收到来自Google云端硬盘的“错误请求”响应。
  2. 您必须同时使用来自Google云端硬盘的文件的setModifiedDate()和更新请求本身的setSetModifiedDate(true)。 (有趣的名字,呵呵?“setSet”,人们不可能错误地input那个…)

以下是一些简单的示例代码,显示如何进行更新,包括更新文件时间:

 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,具体取决于您要在哪里存储文件的本地副本。

你的build设目标

右键单击您的项目,进入它的属性,然后在Android下,将构build目标更改为Google API。 如果他们不在那里,请从android下载pipe理器下载。

如果您在仿真器上进行testing,请确保其目标是Google API,而不是通用Android。

您需要在您的testing设备上设置Google帐户。 编写的代码将自动使用它find的第一个Google帐户(这就是[0]所示的内容)。如果您需要下载Google云端硬盘应用程序才能使用该function,则需要IDK。 我正在使用API​​级别15,我不知道这个代码会工作多久。

其余的部分

上面应该让你开始,希望你能从那里找出你的出路……说实话,这是迄今为止我所得到的。 我希望这有助于很多人,并节省很多时间。 我相当肯定,我刚刚编写了最全面的设置指南,以设置使用Google云端硬盘的Android应用。 在Google上感到羞耻,至less在6个不相关的页面之间传播必要的资料。

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

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

请注意,您在video中看到的内容基于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' 

有一些新的多克(虽然仍然乏味的海事组织):

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

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

看看Google的DrEdit Example ,它有一个名为android/的文件夹。 复制它,按照readme ,它应该工作(适用于与KitKat Android模拟器)。

PS

很抱歉,如果您需要完全访问权限,那么新的Google Drive Android API不支持完整的云端硬盘访问权限,只有drive.filedrive.appdata 授权范围 ,所以如果您需要完全访问权限,则必须返回到Google API的客户端对于Java (DrEdit示例使用)。