Ответ 1
Изменить: Клаудио Керубино говорит, что Google Play Services теперь доступна и сделает этот процесс намного проще. Тем не менее, нет образца кода (все же, он говорит, что это скоро... они сказали, что Google Play Services "скоро появится" 4 месяца назад, так что есть хороший шанс, что этот ответ будет оставаться единственным полностью рабочим примером доступа Google Диска из приложения Android в 2013 году.)
Edit 2X: Похоже, я был около месяца, когда сказал, что у Google не будет рабочего примера до следующего года. Официальное руководство от Google находится здесь:
https://developers.google.com/drive/quickstart-android
Я еще не тестировал свои методы, поэтому возможно, что мои решения с сентября 2012 года (ниже) все же самые лучшие:
Службы Google Play НЕ НЕОБХОДИМО для этого. Это боль в прикладе, и я провел более 50 часов (отредактируйте: 100 часов), выясняя все это, но здесь много всего, что это поможет узнать:
БИБЛИОТЕКИ
Для онлайн-сервисов Google в целом вам понадобятся эти библиотеки в вашем проекте: (Инструкции и ссылка на скачивание)
- Google-апи-клиент-1.11.0-beta.jar
- Google-апи-клиент-андроид-1.11.0-beta.jar
- Google-клиент-клиент-1.11.0-beta.jar
- Google-HTTP-клиент-андроид-1.11.0-beta.jar
- Google-клиент-клиент-ДЖЕКСОН-1.11.0-beta.jar
- Google-OAuth-клиент-1.11.0-beta.jar
- гуавы-11.0.1.jar
- ДЖЕКСОНА-ядро-ASL-1.9.9.jar
- jsr305-1.3.9.jar
Для Google Диска, в частности, вам также понадобится следующее:
- google-api-services-drive-v2-rev9-1.8.0-beta.jar(Ссылка для скачивания)
НАСТРОЙКА КОНСОЛИ
Затем перейдите в Консоль Google. Сделайте новый проект. В разделе "Службы" вам нужно включить две вещи: DRIVE API и DRIVE SDK! Они отделены друг от друга, один не включается автоматически, а ВЫ ДОЛЖНЫ ОБРАТИТЬСЯ ОБОИХ! (рискуя потратить впустую как минимум 20 часов моего времени.)
Еще на консоли перейдите к API Access. Создайте клиент, сделайте его Android-приложение. Дайте ему свой идентификатор связки. Я не думаю, что отпечатки пальцев на самом деле важны, поскольку я уверен, что я использовал неправильный, но стараюсь получить это право в любом случае (Google предоставляет инструкции для него.)
Он будет генерировать идентификатор клиента. Тебе это понадобится. Держитесь за него.
Изменить: мне сказали, что я ошибаюсь, и что вам нужно всего лишь включить Drive API, Drive SDK вообще не нужно включать, и вам просто нужно использовать Simple API Key, не настроил что-то для 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 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 - Загрузка
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 log in if it ever reaches this spot. Handle it here however you'd like.
}
}
КОД ANDROID - Обновление
Две быстрые заметки об обновлении последней измененной даты файла на Google Диске:
- Вы должны предоставить полностью инициализированное DateTime. Если вы этого не сделаете, вы получите ответ "Плохой запрос" с Google Диска.
- Вы должны использовать как setModifiedDate() в Файле с Google Диска, так и 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 измените цель сборки на API Google, если нужно. Если их там нет, загрузите их из диспетчера загрузки Android.
Если вы тестируете эмулятор, убедитесь, что его целью является API Google, а не общий Android.
Вам понадобится учетная запись Google, настроенная на вашем тестовом устройстве. При написании кода автоматически будет использоваться первая найденная им учетная запись Google (что означает [0].) IDK, если вам нужно загрузить приложение Google Диска для этого. Я использовал API-уровень 15, я не знаю, как далеко этот код будет работать.
ОТДЫХ
Вышесказанное должно помочь вам начать, и, надеюсь, вы сможете понять, откуда это происходит... честно говоря, это примерно так, как я до сих пор понял. Надеюсь, это поможет МНОМУ людей и сэкономит им много времени. Я уверен, что я только что написал наиболее полное руководство по настройке приложения Android для использования Google Диска. Позор в Google для распространения необходимого материала по крайней мере на 6 разных страницах, которые вообще не связаны друг с другом.