This is a repost of Stephen Wylie’s post on Google Plus (my husband!)
THIS IS THE NEWEST AND BEST WAY TO DO OAUTH AND INTEGRATE GOOGLE. I PROMISE!
Here are a series of steps you can use in order to integrate an Android app with the Google Play Services, particularly for the sake of accessing a user’s Google Drive documents. See below for a link to some sample code that ties it all together.
Step 1: Create an account for Google API Services, and access your Google APIs Console.
Create an entry for your application, — “Create” a new “Project” if you don’t have one already, then create an OAuth2 key “for installed applications” (assuming you’re writing an Android app). This generates a “Client ID” which you’ll use in about 15 seconds. Part of this process involves obtaining the SHA1 fingerprint of my debug key, which I obtained by using the jre7 version of keytool to read the debug.keystore file. This allowed me to use the “Drive-initiated authorization” listed at https://developers.google.com/drive/about-auth#drive-initiated_authorization because I’m not intending to override any other phase of the OAuth2 process or involve any other APIs that aren’t in Drive. Remember to change this to the actual signed key once you make the release version of your APK.
Back in “Services”, enable the Google Drive API and Google Drive SDK, and this will activate an option in your sidebar called “Drive SDK”. You must fill this page out with the pertinent data relating to your application. This data includes the following:
* Put in an Application Icon.
* The Client ID is something you must generate when you create an OAuth 2.0 key in general. Just copy that Client ID into the appropriate box.
* Make up a URL for the “Open URL.”
* Throw in mime types you care about. Most folks might want to specify actual MIME types that the app is allowed to open, but for now, I only want to open up the reserved Google document types (e.g. application/vnd.google-apps.spreadsheet), which the SDK Panel won’t let me specify as a MIME type to open. If you’re only interested in the document types Drive lets you create within itself, check the “Import: Allow users to open files that can be converted to a format that this app can open” box. Check outhttps://developers.google.com/drive/enable-sdk — especially the “Setting MIME types and extensions” section for more details.
* Add some Google API Scopes. There are two required for Drive apps:https://www.googleapis.com/auth/userinfo.email andhttps://www.googleapis.com/auth/userinfo.profile. https://www.googleapis.com/auth/drive.file should be included by default, but it may be prudent to still list it here anyway. There are some others listed athttps://developers.google.com/drive/scopes. One basic one worth including in many cases is https://www.googleapis.com/auth/drive, which allows access to all files on the user’s Dtive. For read-only access to all documents, usehttps://www.googleapis.com/auth/drive.readonly.
Make sure to save your changes and then check the top (PgUp) to see if any of the input was invalid. Make any necessary changes until Google notes your changes were saved successfully.
Step 2: Watch this Google IO 2012 presentation, or thumb through the slides:https://docs.google.com/presentation/d/1LrEKp2PqESsES3upS1xsSARz35KS-9QHnYFTKvS2yzM/preview#slide=id.p19
While this will help you write your code, there are definitely some key pieces missing from it, and also things that will cause errors once you think everything’s been implemented. Here are the pitfalls:
* Slide 17 has a typo in the unbolded area which is corrected in the bolded area in slide 18 — Context does not know what startActivityForResult is. Activity does, so since I usually make it available as a class variable, the asynchronous process knows what it is without me having to pass it in.
* The ‘setQ(“mimeType=text/plain”)’ method invocation mentioned in slide 36, when used just as written, seems to produce an error: “Invalid Value”. It becomes apparent from looking at the XML message that the error came from the value in “q”; it seemed to work better once I put ‘setQ(“mimeType=\”text/plain\””)’ — note the escaped quotes around text/plain. However, this query is optional.
* Finally, and this is very important, is the line:
return GoogleAuthUtil.getToken(ctx, account.name, “oauth2:” + DriveScopes.DRIVE_READONLY);
Note that, in the presentation, it’s listed as DriveScopes.DRIVE_FILE. This only gives you access to the files the user has already created with the app. This may be what you want in some instances, but for my app, I need DRIVE_READONLY. DriveScopes.DRIVE gives the program full, unfettered R/W access to any user files, which is beyond what I need. This was described above in the “Google API Scopes” area.
Once this has been done, and the considerations above have been taken (which may not be all the ones I had to make, but the sample code definitely works), you’ll be able to use Google Play Services to connect to Google Drive.
Oh, by the way, here are the relevant pieces of a Java activity I wrote that does all this: http://one-dollar.us/DriveActivity.java Note it doesn’t take care of practically any exception cases properly, notify the user what the heck’s going on while it’s fetching the files, or even fetch the files if the user has to tap the “Yes, I really want to do this” button. I also suspect there are probably some code paths that aren’t necessary in here, or are unreachable because I put in the capability to do things 2 different ways and it only ever uses one. The good news is that the most important feature works!
Example code relating to GoogleAuthUtil, also features nice asynchronous wrapper: https://developers.google.com/android/google-play-services/reference/com/google/android/gms/auth/GoogleAuthUtil I got some more ideas from herehttps://developers.google.com/drive/examples/java#making_authorized_api_requests, but this page didn’t end up being too useful.
This piece of code provided some insight as to how to possibly include the authentication token into the http://code.google.com/p/google-oauth-java-client/wiki/OAuth2#Servlet_authorization_code_flow