I am not sure why, but there are not a lot of examples how to use Google Drive API from Android. If you're wondering about it, or you look for a working code, here it is...
I assume you've already went successfully through the Google Drive SDK Quickstart - https://developers.google.com/drive/quickstart-android .
1) If you're using Eclipse as your IDE and you don't enjoy the command line, for step 1 in the Quickstart, you can find the right SHA1 fingerprint in Window->Preferences -> Android -> Build.
2) In Google Cloud Console (https://cloud.google.com/console) enable both Drive API and Drive SDK
3) Enabling Google Drive for your Activity. The code assumes that the main purpose of the activity is to synchronize your content (I called it BackupActivity - to backup all the content from the app to the Google Drive).
a. In your Activity put the following:
b. In the onCreate put:
c. Add the following methods:
I assume you've already went successfully through the Google Drive SDK Quickstart - https://developers.google.com/drive/quickstart-android .
1) If you're using Eclipse as your IDE and you don't enjoy the command line, for step 1 in the Quickstart, you can find the right SHA1 fingerprint in Window->Preferences -> Android -> Build.
2) In Google Cloud Console (https://cloud.google.com/console) enable both Drive API and Drive SDK
3) Enabling Google Drive for your Activity. The code assumes that the main purpose of the activity is to synchronize your content (I called it BackupActivity - to backup all the content from the app to the Google Drive).
a. In your Activity put the following:
// change the following to your Activity name private final static String TAG = "BackupActivity"; static final int REQUEST_ACCOUNT_PICKER = 1; static final int REQUEST_AUTHORIZATION = 2; private static Drive service; private GoogleAccountCredential credential;
b. In the onCreate put:
credential = GoogleAccountCredential.usingOAuth2(this, Arrays.asList(DriveScopes.DRIVE)); startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
c. Add the following methods:
private Drive getDriveService(GoogleAccountCredential credential) { return new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), credential) .setApplicationName(getApplicationInfo().name).build(); } @Override protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) { switch (requestCode) { case REQUEST_ACCOUNT_PICKER: if (resultCode == RESULT_OK && data != null && data.getExtras() != null) { String accountName = data.getStringExtra( AccountManager.KEY_ACCOUNT_NAME); if (accountName != null) { credential.setSelectedAccountName(accountName); service = getDriveService(credential); backupData(); } } break; case REQUEST_AUTHORIZATION: if (resultCode == Activity.RESULT_OK) { backupData(); } else { startActivityForResult(credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER); } break; } }
d. Now you need to fill your backupData() method, I suggest the following structure:
private void backupData() { // run backup in the background Thread t = new Thread(new Runnable() { @Override public void run() { try { // your backup logic here } catch (UserRecoverableAuthIOException e) { startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION); } catch (final Exception e) { // runOnUIThread is required of Toast runOnUiThread(new Runnable() { @Override public void run() { // TODO: (for you) add an error_backup string to the resources Toast.makeText(getApplicationContext(), getResources().getString(R.string.error_backup) e.getMessage(), Toast.LENGTH_LONG).show(); } }); Log.e(TAG, "Error while data backup: " + e.getMessage()); } } }); t.start(); finish(); }e. Now you can wonder how to push data to the Google Drive. Below you will find some utility methods that I've created for this purpose (this is copy paste from real app, so sorry if something is missing - let me know in such case :)). I hope the in-code comments is enough to understand what is going on...
private final static String TAG = "GoogleDriveHelper"; public final static String BINARY_FILE_IMG_MIME_TYPE = "image/png"; public final static String BINARY_FILE_AUDIO_MIME_TYPE = "audio/amr"; /** * Get File handler for folder with provided parameters. If it doesn't exist, * it will be created. * @param service * @param folderName * @param parentId * @return file that was created or found according to provided parameters * @throws UserRecoverableAuthIOException */ public static File getOrCreateFolder(Drive service, String folderName, String parentId) throws UserRecoverableAuthIOException { File result = null; // check if the folder exists already try { String query = "mimeType='application/vnd.google-apps.folder' and trashed=false and title='" + folderName + "'"; // add parent param to the query if needed if (parentId != null) { query = query + " and '" + parentId + "' in parents"; } Files.List request = service.files().list().setQ(query); FileList files = request.execute(); if (files.getItems().size() == 0) { // File's metadata. File body = new File(); if (parentId != null) { ParentReference parent = new ParentReference(); parent.setId(parentId); java.util.Listparents = new ArrayList (); parents.add(parent); body.setParents(parents); } body.setTitle(folderName); body.setMimeType("application/vnd.google-apps.folder"); result = service.files().insert(body).execute(); } else { result = files.getItems().get(0); } } catch (UserRecoverableAuthIOException ue) { throw ue; } catch (Exception e) { Log.e(TAG, "Exception while trying to getOrCreateFolder, folderName: " + folderName + " parentId:" + parentId + " exception:" + e.getMessage()); } return result; } /** * Create or update a remote file out of a local binary file. Remote file gets * updated ONLY if file size is * different (e.g. when previous upload failed) * @param service * @param localPath * @param parentId * @return File object for the remote file or null if the local file doesn't * exist or any other error occurs. * @throws UserRecoverableAuthIOException */ public static File createOrUpdateFileFromFile(Drive service, String localPath, String parentId) throws UserRecoverableAuthIOException { File result = null; try { // check if the local file exists, if it doesn't, return null java.io.File localFile = new java.io.File(localPath); if (!localFile.exists()) { Log.w(TAG, "File doesnt exist, so skipping createOrUpdate: " + localPath); return null; } String fileName = localFile.getName(); String fileMime; if (fileName.endsWith("amr")) { fileMime = BINARY_FILE_AUDIO_MIME_TYPE; } else { fileMime = BINARY_FILE_IMG_MIME_TYPE; } // check if given file exists String query = "trashed=false and title='" + fileName + "' and '" + parentId + "' in parents"; Files.List request = service.files().list().setQ(query); FileList files = request.execute(); if (files.getItems().size() == 0) { // file doesnt exist - create a new one File body = new File(); // set parent ParentReference parent = new ParentReference(); parent.setId(parentId); java.util.List parents = new ArrayList (); parents.add(parent); body.setParents(parents); // set properties body.setTitle(fileName); body.setMimeType(fileMime); // push content InputStream in = null; try { in = new BufferedInputStream(new FileInputStream(localFile)); InputStreamContent content = new InputStreamContent(fileMime, in); Drive.Files.Insert insertRequest = service.files().insert(body, content); insertRequest.getMediaHttpUploader(). setDirectUploadEnabled(true); result = insertRequest.execute(); } finally { if (in != null) { in.close(); } } } else { // file exists, update it if the one on the server has different // size File remoteFile = files.getItems().get(0); if (localFile.length() != remoteFile.getFileSize().longValue()) { Log.d(TAG, "Performing update of file: " + localPath); InputStream in = null; try { in = new BufferedInputStream( new FileInputStream(localFile)); InputStreamContent content = new InputStreamContent(fileMime, in); Drive.Files.Update updateRequest = service.files().update(remoteFile.getId(), remoteFile, content); updateRequest.getMediaHttpUploader(). setDirectUploadEnabled(true); result = updateRequest.execute(); } finally { if (in != null) { in.close(); } } } else { Log.d(TAG, "Skipping update of file because size is the same:" + localPath); } } } catch (UserRecoverableAuthIOException ue) { throw ue; } catch (Exception e) { Log.e(TAG, "Exception while trying to createOrUpdateFile, localPath:" + localPath + " parentId:" + parentId + " exception:" + e.getMessage()); } return result; }
Comments
Post a Comment