Android 在 Google Drive SDK 中打开和保存文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12164024/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android Open and Save files to/from Google Drive SDK
提问by ArtOfWarfare
I've spent the last six hours pouring over documents from Google and I still don't know how to get started with this. All I want to do is make it so my existing Android app can read files from Google Drive, upload new files to Google Drive, and edit existing files on Google Drive.
在过去的六个小时里,我一直在翻阅来自 Google 的文档,但我仍然不知道如何开始。我想要做的就是让我现有的 Android 应用程序可以从 Google Drive 读取文件,将新文件上传到 Google Drive,以及编辑 Google Drive 上的现有文件。
I've read that Drive SDK v2 was focused solely on making it easy for Android (and mobile in general) developers to use it, and yet there seems to be virtually nothing in their documentation about it.
我读过 Drive SDK v2 只专注于让 Android(以及一般的移动设备)开发人员更容易使用它,但他们的文档中似乎几乎没有任何关于它的内容。
Ideally, I'd like someone to point at some decent documentation, example, or tutorial covering how to do this (keep in mind I'm using Android. They have plenty of stuff on how to use Drive with the Google App Engine; I have already looked at it and I have no idea how to go from that to an Android app.)
理想情况下,我希望有人指出一些有关如何执行此操作的体面文档、示例或教程(请记住,我使用的是 Android。他们有很多关于如何将 Drive 与 Google App Engine 配合使用的内容;我已经看过了,我不知道如何从它转到 Android 应用程序。)
I need to know which libraries I need to download and add to my project, what I need to add to my manifest, and how I can ultimately get a list of files from Google Drive, download one, and then upload a modified version.
我需要知道我需要下载哪些库并将其添加到我的项目中,我需要添加到我的清单中,以及我最终如何从 Google Drive 获取文件列表,下载一个,然后上传修改后的版本。
Ideally, I'd like it to handle accounts automatically, the way that the officially Google Drive app does.
理想情况下,我希望它能像正式的 Google Drive 应用程序那样自动处理帐户。
回答by ArtOfWarfare
Edit: Claudio Cherubino says that Google Play Services is now available and will make this process a lot easier. However, there's no sample code available (yet, he says it's coming soon... they said Google Play Services was "coming soon" 4 months ago, so there's a good chance this answer will continue to be the only completely working example of accessing Google Drive from your Android application into 2013.)
编辑:克劳迪奥·凯鲁比诺 (Claudio Cherubino) 说 Google Play 服务现已可用,这将使此过程变得更加容易。但是,没有可用的示例代码(但是,他说它即将推出......他们说 Google Play 服务在 4 个月前“即将推出”,所以很有可能这个答案将继续成为唯一完全有效的访问示例谷歌驱动器从你的 Android 应用程序到 2013 年。)
Edit 2X: Looks like I was off by about a month when I said Google wouldn't have a working example until next year. The official guide from Google is over here:
编辑 2X:当我说谷歌要到明年才会有工作示例时,我似乎已经离开了大约一个月。Google 的官方指南在这里:
https://developers.google.com/drive/quickstart-android
https://developers.google.com/drive/quickstart-android
I haven't tested their methods yet, so it's possible that my solutions from September 2012 (below) are still the best:
我还没有测试过他们的方法,所以我 2012 年 9 月(以下)的解决方案可能仍然是最好的:
Google Play Services is NOT REQUIRED for this. It's a pain in the butt, and I spent well over 50 hours (edit: 100+ hours) figuring it all out, but here's a lot of things that it'll help to know:
为此不需要 Google Play 服务。这让我很痛苦,我花了 50 多个小时(编辑:100 多个小时)才弄明白,但了解以下很多事情会有所帮助:
THE LIBRARIES
图书馆
For Google's online services in general you'll need these libraries in your project: (Instructions and Download Link)
对于 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-Hymanson-1.11.0-beta.jar
- google-oauth-client-1.11.0-beta.jar
- guava-11.0.1.jar
- Hymanson-core-asl-1.9.9.jar
- jsr305-1.3.9.jar
- 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-Hymanson-1.11.0-beta.jar
- google-oauth-client-1.11.0-beta.jar
- 番石榴-11.0.1.jar
- Hymanson-core-asl-1.9.9.jar
- jsr305-1.3.9.jar
For Google Drive in particular you'll also need this:
特别是对于 Google Drive,您还需要这个:
- google-api-services-drive-v2-rev9-1.8.0-beta.jar (Download Link)
- google-api-services-drive-v2-rev9-1.8.0-beta.jar(下载链接)
SETTING UP THE CONSOLE
设置控制台
Next, go to Google Console. Make a new project. Under Services, you'll need to turn on two things: DRIVE APIand DRIVE SDK! They are separate, one does not automatically turn the other on, and YOU MUST TURN BOTH ON!(Figuring this out wasted at least 20 hours of my time alone.)
接下来,转到Google 控制台。做一个新项目。在服务下,您需要打开两件事:DRIVE API和DRIVE SDK!它们是分开的,一个不会自动打开另一个,您必须同时打开!(弄清楚这一点浪费了我至少 20 个小时的独处时间。)
Still on the console, go to API Access. Create a client, make it an Android app. Give it your bundle ID. I don't think the fingerprints thing is actually important, as I'm pretty sure I used the wrong one, but try to get that right anyways (Google provides instructions for it.)
仍然在控制台上,转到 API Access。创建一个客户端,使其成为 Android 应用程序。给它你的包 ID。我认为指纹实际上并不重要,因为我很确定我使用了错误的指纹,但无论如何都要尝试正确处理(Google 提供了相关说明。)
It'll generate a Client ID. You're going to need that. Hold onto it.
它将生成一个Client ID。你会需要那个。坚持住。
Edit: I've been told that I'm mistaken and that you only need to turn on Drive API, Drive SDK doesn't need to be turned on at all, and that you just need to use the Simple API Key, not set up something for Android. I'm looking into that right now and will probably edit this answer in a few minutes if i figure it out...
编辑:有人告诉我我错了,你只需要打开 Drive API,Drive SDK 根本不需要打开,你只需要使用简单的 API 密钥,而不是设置为 Android 准备一些东西。我现在正在研究这个问题,如果我弄清楚了,可能会在几分钟内编辑这个答案......
THE ANDROID CODE - Set Up and Uploading
ANDROID 代码 - 设置和上传
First, get an auth token:
首先,获取一个身份验证令牌:
AccountManager am = AccountManager.get(activity);
am.getAuthToken(am.getAccounts())[0],
"oauth2:" + DriveScopes.DRIVE,
new Bundle(),
true,
new OnTokenAcquired(),
null);
Next, OnTokenAcquired() needs to be set up something like this:
接下来, 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();
HymansonFactory jsonFactory = new HymansonFactory();
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 - Downloading
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;
}
}
One last thing... if that intent gets sent off, you'll need to handle when it returns with a result.
最后一件事......如果该意图被发送,您将需要在它返回结果时进行处理。
@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 - Updating
ANDROID 代码 - 更新
Two quick notes on updating the last modified date of a file on Google Drive:
关于更新 Google Drive 上文件的最后修改日期的两个快速说明:
- You must provide a fully initialized DateTime. If you do not, you'll get a response of "Bad Request" from Google Drive.
- You must use both setModifiedDate() on the File from Google Drive and setSetModifiedDate(true) on the update request itself. (Fun name, huh? "setSet[...]", there's no way people could mistype that one...)
- 您必须提供一个完全初始化的 DateTime。如果不这样做,您将收到来自 Google Drive 的“错误请求”响应。
- 您必须在 Google Drive 的文件上使用 setModifiedDate() 并在更新请求本身上使用 setSetModifiedDate(true) 。(有趣的名字,嗯?“setSet[...]”,人们不可能打错那个...)
Here's some brief sample code showing how to do an update, including updating the file time:
下面是一些简短的示例代码,展示了如何进行更新,包括更新文件时间:
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();
}
THE MANIFEST
清单
You'll need the following permissions: GET_ACCOUNTS, USE_CREDENTIALS, MANAGE_ACCOUNTS, INTERNET, and there's a good chance you'll need WRITE_EXTERNAL_STORAGE as well, depending on where you'd like to store the local copies of your files.
您将需要以下权限:GET_ACCOUNTS、USE_CREDENTIALS、MANAGE_ACCOUNTS、INTERNET,并且很有可能您还需要 WRITE_EXTERNAL_STORAGE,具体取决于您想要存储文件的本地副本的位置。
YOUR BUILD TARGET
您的构建目标
Right click your project, go into it's properties, and under Android change the build target to Google APIs if you must. If they aren't there, download them from the android download manager.
右键单击您的项目,进入它的属性,如果需要,在 Android 下将构建目标更改为 Google API。如果它们不存在,请从 android 下载管理器下载它们。
If you're testing on an emulator, make sure its target is Google APIs, not generic Android.
如果您在模拟器上进行测试,请确保其目标是 Google API,而不是通用 Android。
You'll need a Google Account set up on your test device. The code as written will automatically use the first Google Account it finds (that's what the [0] is.) IDK if you need to have downloaded the Google Drive app for this to have worked. I was using API Level 15, I don't know how far back this code will work.
您需要在测试设备上设置 Google 帐户。编写的代码将自动使用它找到的第一个 Google 帐户(这就是 [0] 的含义。)IDK,如果您需要下载 Google Drive 应用程序才能使其正常工作。我使用的是 API 级别 15,我不知道这段代码能用多久。
THE REST
其余的部分
The above should get you started and hopefully you can figure your way out from there... honestly, this is just about as far as I've gotten so far. I hope this helps A LOT of people and saves them A LOT of time. I'm fairly certain I've just written the most comprehensive set up guide to setting up an Android app to use Google Drive. Shame on Google for spreading the necessary material across at least 6 different pages that don't link to each other at all.
以上应该让你开始,希望你能从那里找到出路......老实说,这只是我到目前为止所得到的。我希望这可以帮助很多人并为他们节省很多时间。我很确定我刚刚编写了最全面的设置指南来设置 Android 应用程序以使用 Google Drive。谷歌将必要的材料传播到至少 6 个完全没有相互链接的不同页面,这让他们感到羞耻。
回答by Claudio Cherubino
Check this video from Google I/O to learn how to integrate your Android app with Drive:
查看来自 Google I/O 的此视频,了解如何将您的 Android 应用程序与云端硬盘集成:
http://www.youtube.com/watch?v=xRGyzqD-vRg
http://www.youtube.com/watch?v=xRGyzqD-vRg
Please be aware that what you see in the video is based on Google Play Services, which hasn't launched to the general public yet:
请注意,您在视频中看到的内容基于尚未向公众推出的Google Play 服务:
回答by straya
It's 2015, things have changed!
2015年了,一切都变了!
Get the 'Drive API for Android' with gradle:
使用 gradle 获取“Drive API for Android”:
compile 'com.google.android.gms:play-services-drive:7.8.0'
There's some new doco (although still lackluster IMO):
有一些新的 doco(尽管 IMO 仍然乏善可陈):
https://developers.google.com/drive/web/quickstart/android
https://developers.google.com/drive/web/quickstart/android
And for those about to go caving...the biggest problem I encountered thus far is that there is absolutely no way of distinguishing folders that have been permanently deleted from folders that are normal...you can find them, you can create folders and files within them, only writing to the file DriveContents will always fail.
而对于那些即将去洞穴的人......到目前为止我遇到的最大问题是绝对无法区分已永久删除的文件夹与正常文件夹......你可以找到它们,你可以创建文件夹和其中的文件,仅写入文件 DriveContents 将始终失败。
回答by woojoo666
Take a look at Google's DrEdit Example, which has a folder called android/
. Copy it, follow the readme
, and it should work (works for me on an Android emulator with KitKat).
看看谷歌的DrEdit Example,它有一个名为android/
. 复制它,按照readme
,它应该可以工作(在带有 KitKat 的 Android 模拟器上对我有用)。
.
.
P.S.
聚苯乙烯
Sorry for reviving this, but the new Google Drive Android APIdoesn't support full Drive access, only drive.file
and drive.appdata
authorization scopes, so if you need full access you have to go back to the good 'ol Google API's Client for Java(which the DrEdit example uses).
很抱歉恢复此功能,但新的Google Drive Android API不支持完全驱动器访问权限,仅支持drive.file
和drive.appdata
授权范围,因此如果您需要完全访问权限,则必须返回良好的 'ol Google API's Client for Java(DrEdit示例使用)。