Connecting to Google Drive* from an Android* App

Download source code

This sample demonstrates how to connect to an individual’s Google Drive* online storage service from an Android application. I’ll be describing the sections of code that are executed based on the usage flow of the app. This application is based on the Google Drive sample located here. Before you start building this sample, please follow the instructions in the previous link for registering your application with Google Cloud Console.

Like most Android applications, this one begins in the onCreate function of MainActivity. In this function, you can see the credentials for connecting to the Google Drive account are set up and an activity is started to prompt the user to select their Google account from the registered accounts on the device, or to enter a new one.

mCredential = GoogleAccountCredential.usingOAuth2(this, Arrays.asList(DriveScopes.DRIVE));
        startActivityForResult(mCredential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);


After this, the function continues to set up the button listeners and the ListView listener.

Now that the basic UI is configured, the app waits for user input via the download and upload buttons. If the user presses the download button, the OnClickListener for that button launches an Intent that allows the user to select the application to pick media files from the device’s storage.


final Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() 
{
	public void onClick(View v) 
	{
	final Intent galleryIntent = new Intent(Intent.ACTION_PICK);
	galleryIntent.setType("*/*");
	startActivityForResult(galleryIntent, RESULT_STORE_FILE);
	}
});

 

 

Since the Intent was started with startActivityForResult, when it returns, the main activity’s onActivityResult function will be called with RESULT_STORE_FILE. The URI of the file selected by the user can be obtained from data.getData().


protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) 
{
	switch (requestCode) 
	{
		…
		case RESULT_STORE_FILE:
			mFileUri = data.getData();
			// Save the file to Google Drive
        		saveFileToDrive();
			break;
	}
}

With this URI, the file can be saved to the Drive, which is done with the call to saveFileToDrive(). All communication to the Drive account with the Drive APIs is done in a new thread to ensure that it doesn’t slow down the main UI thread, causing the UI to become slow and laggy.


private void saveFileToDrive() 
{
Thread t = new Thread(new Runnable() 
    	{
    		@Override
    		public void run() 
    		{
			…
    		}
    	});
    	t.start();
}


Within the run function, a new URI is created based on the real path to the media file’s contents. This is because the path that’s associated with the URI that’s returned from the Gallery Intent is a virtual path that doesn’t work with the upload feature of the Google Drive API. Here we’re getting the physical path and creating a new URI from it to upload to Google Drive.


// Create URI from real path
String path;
path = getPathFromUri(mFileUri);
mFileUri = Uri.fromFile(new java.io.File(path));
…
	java.io.File fileContent = new java.io.File(mFileUri.getPath());

Then FileContent and File variables are created to pass into the Google Drive APIs to upload the file’s content to the user’s Google Drive. A File’s object is created from the Service object created in OnCreate, and its Insert function is used to prepare the media file’s content to be uploaded. Then execute is called to actually push the content to the Google Drive in the cloud.


FileContent mediaContent = new FileContent(cR.getType(mFileUri), fileContent);
// File's meta data. 
File body = new File();
body.setTitle(fileContent.getName());
body.setMimeType(cR.getType(mFileUri));
com.google.api.services.drive.Drive.Files f1 = mService.files();
com.google.api.services.drive.Drive.Files.Insert i1 = f1.insert(body, mediaContent);
File file = i1.execute();


At this point, the upload is complete, and the user can view the file in the root of their Google Drive account.

Next the user can select the download button. Once pressed, the getDriveContents function is called.


final Button button2 = (Button) findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener()
{
	public void onClick(View v) 
	{
	getDriveContents();
	}
});


getDriveContents starts a new thread to download a list of file names of all the content in the Google Drive account.


private void getDriveContents()
{
	Thread t = new Thread(new Runnable() 
	{
		@Override
		public void run() 
		{
			mResultList = new ArrayList(); … } }); t.start(); } 

Within getDriveContents, a FileList object is set up and used to request the list of files. In order not to get a list containing every object in the root folder and every object in the trash folder, the Q value is set with the string “trashed=false”. After all the pages of file data have been obtained and stored in the ArrayList of Files, the ListView in the UI is populated to show users which files are on their Google Drive accounts to download.


com.google.api.services.drive.Drive.Files f1 = mService.files();
com.google.api.services.drive.Drive.Files.List request = null;
				
do 
{
	try 
	{ 
		request = f1.list();
		request.setQ("trashed=false");
		com.google.api.services.drive.model.FileList fileList = request.execute();
						
		mResultList.addAll(fileList.getItems());

		request.setPageToken(fileList.getNextPageToken());
	} catch (UserRecoverableAuthIOException e) {
		startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
	} catch (IOException e) {
		e.printStackTrace();
		if (request != null)
		{
		request.setPageToken(null);
		}
	}
} while (request.getPageToken() !=null && request.getPageToken().length() > 0);
				
populateListView();

populateListView pulls the file names from the ArrayList and stores them in a simple array of strings. They can then be used with an ArrayAdapter to populate the ListView. Once the ListView is populated, the app is waiting for user input again.

 

 

At this point, the user can select a file name from the ListView and its OnItemClickListener function will be called to handle the selection.


OnItemClickListener mMessageClickedHandler = new OnItemClickListener() 
{
	public void onItemClick(AdapterView parent, View v, int position, long id) 
	{
		downloadItemFromList(position);
	}
};

Now downloadItemFromList is called with the position in the list that was selected. A new thread is spawned since communication with Google Drive will be occurring again. Once the ListView selection is associated with the correct file from the ArrayList of Files, that particular file has a download URL that can be used to set up a Request for an HTTP response. Once this is setup, execute can be called to begin the download of the file’s contents. The file’s contents are returned in the form of an InputStream.


com.google.api.client.http.HttpResponse resp = 
	mService.getRequestFactory()
	.buildGetRequest(new GenericUrl(tmp.getDownloadUrl()))
	.execute();
InputStream iStream = resp.getContent();
try 
{
	final java.io.File file = new java.io.File(Environment
		.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath(), 
		tmp.getTitle());
	showToast("Downloading: " + tmp.getTitle() + " to " + Environment
	.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath());
	storeFile(file, iStream);
} finally {
	iStream.close();
}

This InputStream can be used in conjunction with an OutputStream to store the file to a directory on the devices internal or external storage (SD card).


private void storeFile(java.io.File file, InputStream iStream)
{
	try 
	{
		final OutputStream oStream = new FileOutputStream(file);
		try
		{
			try
			{
				final byte[] buffer = new byte[1024];
				int read;
				while ((read = iStream.read(buffer)) != -1)
				{
					oStream.write(buffer, 0, read);
				}
				oStream.flush();
			} finally {
				oStream.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	} catch (IOException e) {
		e.printStackTrace();
	}
}

Once the file is written to storage, the user can select to download another file or upload a new one.

There are many more features of the Drive API that you can use to write exciting Android applications that interact with user’s Google Drive accounts. For more information on the Google Drive API, please see: https://developers.google.com/drive/v2/reference/.

Author Bio and Photo

Gideon is a member of the Intel’s Software and Services Group and works with independent software vendors to help them optimize their software for Intel® Atom™ processors. In the past he worked on a team that wrote Linux* graphics drivers for platforms running the Android OS.

 

AttachmentSize
Package icon googledriveapp.zip105.71 KB
For more complete information about compiler optimizations, see our Optimization Notice.

2 comments

Top
Houssem B.'s picture

Hi everyOne,

i'm trying to use this code but it makes exception to me "could not find class com.google.api.services.drive.driveBuilder". can anyone help me please

Amartya H.'s picture

Hi Gideon ,

Thank you for the code. It is very helpful for me.

While I am trying to upload something I am getting error. I have debug the code and found it is getting exception in this line, please help me to solve the problem -- 

com.google.api.services.drive.Drive.Files.Insert i1 = f1.insert(body, mediaContent);
 File file = i1.execute();

 

The exception in screen I am getting is - com.google.api.client.googleapis.extentions.android.gms.auth.GoogleAuthIOException

I have capture DDMS logs also that is present below - 

09-17 11:46:59.864: I/ViewRootImpl(32564): ViewRoot's Touch Event : ACTION_DOWN
09-17 11:46:59.925: I/ViewRootImpl(32564): ViewRoot's Touch Event : ACTION_UP
09-17 11:46:59.928: V/Provider/Settings(32564): get setting for user 0 by user 0 so skipping cache
09-17 11:46:59.928: V/Provider/Settings(32564): invalidate [system]: current 134 != cached 0
09-17 11:47:02.916: D/OpenGLRenderer(32564): Flushing caches (mode 0)
09-17 11:47:02.937: D/GraphicBuffer(32564): close handle(0x61d25b48) (w:544 h:960 f:1)
09-17 11:47:02.938: D/GraphicBuffer(32564): close handle(0x6253d110) (w:544 h:960 f:1)
09-17 11:47:02.939: D/GraphicBuffer(32564): close handle(0x62412f28) (w:544 h:960 f:1)
09-17 11:47:03.459: D/OpenGLRenderer(32564): Flushing caches (mode 1)
09-17 11:47:06.306: D/OpenGLRenderer(32564): Flushing caches (mode 0)
09-17 11:47:06.370: E/AtsViewAgent(32564): No Eta2 is installed
09-17 11:47:06.406: D/GraphicBuffer(32564): create handle(0x624eb678) (w:544, h:960, f:1)
09-17 11:47:06.413: D/OpenGLRenderer(32564): setViewport 540x960 <0x61d25c80>
09-17 11:47:06.578: D/GraphicBuffer(32564): create handle(0x61f354d0) (w:480, h:89, f:1)
09-17 11:47:06.737: D/OpenSSLLib(32564): OpensslErr:Module:13(114:155); file:external/openssl/crypto/asn1/asn1_lib.c ;Line:142;Function:ASN1_get_object
09-17 11:47:06.740: D/OpenSSLLib(32564): OpensslErr:Module:13(114:155); file:external/openssl/crypto/asn1/asn1_lib.c ;Line:142;Function:ASN1_get_object
09-17 11:47:07.192: D/IPCThreadState(32564): [DN #5] BR_CLEAR_DEATH_NOTIFICATION_DONE cookie 0x61f6cc60
09-17 11:47:07.203: W/System.err(32564): com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAuthIOException
09-17 11:47:07.206: W/System.err(32564):     at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential$RequestHandler.intercept(GoogleAccountCredential.java:286)
09-17 11:47:07.206: W/System.err(32564):     at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:859)
09-17 11:47:07.206: W/System.err(32564):     at com.google.api.client.googleapis.media.MediaHttpUploader.executeCurrentRequestWithoutGZip(MediaHttpUploader.java:545)
09-17 11:47:07.206: W/System.err(32564):     at com.google.api.client.googleapis.media.MediaHttpUploader.executeCurrentRequest(MediaHttpUploader.java:562)
09-17 11:47:07.206: W/System.err(32564):     at com.google.api.client.googleapis.media.MediaHttpUploader.executeUploadInitiation(MediaHttpUploader.java:519)
09-17 11:47:07.206: W/System.err(32564):     at com.google.api.client.googleapis.media.MediaHttpUploader.resumableUpload(MediaHttpUploader.java:384)
09-17 11:47:07.206: W/System.err(32564):     at com.google.api.client.googleapis.media.MediaHttpUploader.upload(MediaHttpUploader.java:336)
09-17 11:47:07.206: W/System.err(32564):     at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:418)
09-17 11:47:07.206: W/System.err(32564):     at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
09-17 11:47:07.206: W/System.err(32564):     at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
09-17 11:47:07.207: W/System.err(32564):     at com.example.restoredata.MainActivity$3.run(MainActivity.java:199)
09-17 11:47:07.207: W/System.err(32564):     at java.lang.Thread.run(Thread.java:848)
09-17 11:47:07.208: W/System.err(32564): Caused by: com.google.android.gms.auth.GoogleAuthException: Unknown
09-17 11:47:07.208: W/System.err(32564):     at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
09-17 11:47:07.209: W/System.err(32564):     at com.google.android.gms.auth.GoogleAuthUtil.getToken(Unknown Source)
09-17 11:47:07.209: W/System.err(32564):     at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential.getToken(GoogleAccountCredential.java:255)
09-17 11:47:07.209: W/System.err(32564):     at com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential$RequestHandler.intercept(GoogleAccountCredential.java:279)
09-17 11:47:07.209: W/System.err(32564):     ... 11 more
09-17 11:47:08.469: D/GraphicBuffer(32564): close handle(0x61f354d0) (w:480 h:89 f:1)
09-17 11:47:08.532: D/GraphicBuffer(32564): create handle(0x624f9b80) (w:480, h:108, f:1)
09-17 11:47:10.472: D/GraphicBuffer(32564): close handle(0x624f9b80) (w:480 h:108 f:1)

 

Add a Comment

Have a technical question? Visit our forums. Have site or software product issues? Contact support.