Presentation is loading. Please wait.

Presentation is loading. Please wait.

Best Practices for Accessing Google APIs on Android Yaniv Inbar May 10, 2011 Speaker Feedback: goo.gl/EUnAo Twitter Hashtags: #io2011 #GoogleAPIs #Android.

Similar presentations


Presentation on theme: "Best Practices for Accessing Google APIs on Android Yaniv Inbar May 10, 2011 Speaker Feedback: goo.gl/EUnAo Twitter Hashtags: #io2011 #GoogleAPIs #Android."— Presentation transcript:

1

2 Best Practices for Accessing Google APIs on Android Yaniv Inbar May 10, 2011 Speaker Feedback: goo.gl/EUnAo Twitter Hashtags: #io2011 #GoogleAPIs #Android

3 Google APIs Client Library for Java (goo.gl/ZrqPu) Now in Beta

4 4 APIs OAuth 2.0 Client Login OAuth 1.0 Photos Videos XMLJSON Auth New Google APIs Google Data APIs Data Formats Any REST APIs Platforms Android Google App Engine Java 5 (SE, EE) OUTLINE

5 5 APIs OAuth 2.0 Client Login OAuth 1.0 Photos Videos XMLJSON Auth New Google APIs Google Data APIs Data Formats Any REST APIs Platforms Android Google App Engine Java 5 (SE, EE) OUTLINE

6 Platforms 6 Java Platforms – Any Java Environment Platform neutral –Works (mostly) the same in any Java environment Pluggable –Pluggable HTTP library –Pluggable data format Pluggable streaming JSON library Pluggable streaming XML library –Pluggable Authentication

7 7 HelloBuzz Example public class HelloBuzz { public static void main(String[] args) throws IOException { Buzz buzz = new Buzz(new NetHttpTransport(), new JacksonFactory()); ActivityFeed feed = buzz.activities.list(" ", if (feed.items != null) for (Activity activity : feed.items) System.out.println(activity.buzzObject.content); } Java 5 (SE, EE)

8 8 HelloBuzzServlet Example public class HelloBuzzServlet extends HttpServlet protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { resp.setContentType("text/plain"); PrintWriter writer = resp.getWriter(); Buzz buzz = new Buzz(new UrlFetchTransport(), new JacksonFactory()); ActivityFeed feed = buzz.activities.list(" ", if (feed.items != null) for (Activity activity : feed.items) writer.println(activity.buzzObject.content); } Google App Engine

9 9 HelloBuzzActivity Example public class HelloBuzzActivity extends ListActivity public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Buzz buzz = new Buzz(new NetHttpTransport(), new AndroidJsonFactory()); List activities = new ArrayList (); try { ActivityFeed feed = buzz.activities.list(" ", if (feed.items != null) for (Activity activity : feed.items) activities.add(Html.fromHtml(activity.buzzObject.content)); setListAdapter(new ArrayAdapter (this, android.R.layout.simple_expandable_list_item_1, activities)); } catch (IOException e) {} } Android

10 10 Java Platforms – Pluggable HTTP library UrlFetchTransport –Google App Engine only NetHttpTransport –Based on java.net.HttpURLConnection –Included in Java & Android SDK –Preferred choice on Android since Gingerbread ApacheTransport –Based on Apache HTTP Client –Included in Android SDK –Preferred choice for older Android SDK’s up to FroYo AndroidHttp.newCompatibleTransport() –Picks NetHttpTransport or ApacheTransport based on SDK Level Platforms

11 11 Java Platforms – HTTP Request Factory Library provides request factory abstraction to provide hooks to: –Initialize all requests –Run code before executing a request –Retry unsuccessful requests Example for Google Calendar: Platforms void initializeRequestFactory() { requestFactory = transport.createRequestFactory(new HttpRequestInitializer() { public void initialize(HttpRequest request) { GoogleHeaders headers = new GoogleHeaders(); headers.setApplicationName("Google-CalendarSample/1.0"); headers.gdataVersion = "2”; request.headers = headers; request.enableGZipContent = true; } }); }

12 12 Java Platforms – HTTP Trouble-Shooting Tip Enable logging of HTTP requests and responses: –If you also need to see Authorization header, use Level.ALL instead On Android, you also need to: Logger.getLogger("com.google.api.client.http").setLevel(Level.CONFIG); adb shell setprop log.tag.HttpTransport DEBUG Platforms

13 Android 13 Android: using AsyncTask Activities run in the main UI thread –No HTTP in main thread –Otherwise Android may shut down the application (“… is not responding”) Simplest solution is to use AsyncTask Sessions from Google I/O –[2010] Beginner's Guide to Android (goo.gl/qhaZg)

14 14 HelloBuzzAsyncActivity Example (part 1 of 2) public class HelloBuzzActivity extends ListActivity { final Buzz buzz = new Buzz(new NetHttpTransport(), new public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); new LoadActivities().execute(); } class LoadActivities extends AsyncTask { final ProgressDialog dialog = new protected void onPreExecute() { dialog.setMessage("Loading Activities..."); dialog.show(); protected ActivityFeed doInBackground(Void... params) { try { return buzz.activities.list(" ", } catch (IOException e) { return null; } } Android

15 15 HelloBuzzAsyncActivity Example (part 2 of protected void onPostExecute(ActivityFeed feed) { dialog.dismiss(); if (feed == null) return; List activities = new ArrayList (); if (feed.items != null) for (Activity a : feed.items) activities.add(Html.fromHtml(a.buzzObject.content)); setListAdapter(new ArrayAdapter (HelloBuzzActivity.this, android.R.layout.simple_expandable_list_item_1, activities)); } Android

16 16 Android – Using a background Service Background service makes HTTP requests to API –Store result in a SQLite database Activity lifecycle –Send async request to background service –If alive when response arrives, process immediately –Else, onCreate check for updated data Sessions from Google I/O –[2010] Developing Android REST client applications (goo.gl/R15we) Android

17 17 Android – Shrink Application with ProGuard Android Based on HelloBuzzActivity sample (95% savings)

18 18 Android – Setting Up ProGuard (goo.gl/x1hit) Eclipse New Project Wizard generates default.properties and proguard.cfg –Add to default.properties: –Add to proguard.cfg: proguard.config=proguard.cfg # Needed by google-api-client to keep generic types annotations accessed via reflection -keepclassmembers class * ; } -keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault # Needed by Guava -dontwarn sun.misc.Unsafe Android

19 19 APIs OAuth 2.0 Client Login OAuth 1.0 Photos Videos XMLJSON Auth New Google APIs Google Data APIs Data Formats Any REST APIs Platforms Android Google App Engine Java 5 (SE, EE) OUTLINE

20 20 Google Data APIs (“GData”) Old Decentralized Architecture XML –Some have read-only JSON-C ClientLogin, OAuth 1.0, and OAuth 2.0 Examples: Google Data APIs YouTube Data API Google Calendar Data API Blogger Data API Google Contacts Data API

21 21 Google Data APIs (“GData”) – Java Library Google Data Java Client Library Nice XML data model But only works with Google Data APIs –Nothing else is supported Doesn’t support Android –May be fixed in Ice Cream Sandwich SDK? Still maintained and not deprecated –But we’ve stopped developing it 2 years ago Google Data APIs

22 22 Google APIs New Centralized Architecture JSON OAuth 1.0 and OAuth 2.0 Google I/O sessions –Google I/O ’10 “How Google Builds APIs” (goo.gl/i1WfR) –Google I/O ‘11 “Life of a Google API Developer” (goo.gl/VKJ0q) Examples: New Google APIs Buzz API Latitude API Search API for Shopping

23 23 Google APIs - Discovery Service (goo.gl/iHUN6) Announcing V1 of the Discovery Service today Directory of supported APIs Discovery document for each API –A list of API resource schemas based on JSON Schema. E.g. “ActivitiesFeed” –A list of API methods and available parameters for each method. E.g. “buzz.activities.list” –A list of available OAuth 2.0 scopes. E.g. “https://www.googleapis.com/auth/buzz” Google I/O ’11 session “Building Custom Client Libraries for Google APIs” (goo.gl/b5P6b) New Google APIs

24 24 Google APIs – Explorer (goo.gl/Ccni0) New Google APIs Web-based Google APIs exploration tool

25 25 OAuth 2.0 – Google apis console (goo.gl/UyAZB) New Google APIs

26 26 Google APIs – Generated Libraries (goo.gl/avR14) Announcing generated Java libraries based on the Discovery API –Get an activity feed: –Insert an activity: –Delete an activity: New Google APIs ActivityFeed feed = buzz.activities.list(" ", Activity activity = new Activity(); activity.buzzObject = new ActivityObject(); activity.buzzObject.content = "Posted using Google API Client Library for Java " + "(http://code.google.com/p/google-api-java-client/)"; Activity result = activity).execute(); activity.id).execute();

27 27 APIs OAuth 2.0 Client Login OAuth 1.0 Photos Videos XMLJSON Auth New Google APIs Google Data APIs Data Formats Any REST APIs Platforms Android Google App Engine Java 5 (SE, EE) OUTLINE

28 28 JSON – Streaming parser/serializer library Pluggable choice of streaming library –Avoid memory overhead of a full parser like JSONObject –Stream parsing faster than “full” data models JacksonFactory –Fastest. Based on popular Jackson library (goo.gl/Z0yZF) GsonFactory –Fast, and smaller than Jackson. –Based on Google GSON library (goo.gl/xBO5C) AndroidJsonFactory –Same as GSON, but built in to Honeycomb (SDK 3.0) in package android.util (goo.gl/uJHiR) JSON

29 29 JSON – Data Model Rich Java Object to JSON mapping –Similar to functionality provided by Jackson and Google GSON Examples –Java String/Number/Boolean maps to JSON string/number/boolean –Java enums can be used for JSON string –Java Arrays and Collection can be used for JSON arrays –Map or Java objects can be used for JSON objects –Full richness of Java supported, including generic types (e.g. List ) –Extend GenericJson when you need to preserve arbitrary fields Important when using PUT to update an entry to avoid dropping data JSON

30 30 JSON – Data Model Example { "updated": " T23:08:07.471Z", "id": "tag:google.com,2010:buzz:z12nu3oa1r25gr3wp04cd3zp2zvafrjrlso0k", "object": { "content": "Presenting live at Google I/O!” } public class Activity public DateTime public String public ActivityObject object; } public class ActivityObject public String content; } JSON Java JSON

31 31 JSON – Gzip and Partial Response Based on HelloBuzz sample (95% savings) JSON

32 32 JSON Example – Partial with the Generated Libraries Before: After: Or for more data: Buzz.Activities.List request = buzz.activities.list(" ", request.fields = "items/object/content"; ActivityFeed feed = request.execute(); JSON ActivityFeed feed = buzz.activities.list(" ", Buzz.Activities.List request = buzz.activities.list(" ", request.fields = "items(object/content,updated,id)"; ActivityFeed feed = request.execute();

33 33 JSON: streaming entries HttpResponse response = buzz.activities.list(" ", InputStream content = response.getContent(); JsonParser parser = jsonFactory.createJsonParser(content); parser.nextToken(); parser.skipToKey("data"); parser.skipToKey("items"); while (parser.nextToken() == JsonToken.START_OBJECT) { Activity activity = parser.parse(Activity.class, null); // process activity } JSON

34 34 XML – Data Model T23:59:51.000Z abc 2 public class CalendarEntry public String public DateTime public Title public TimeZone timeZone; } public class Title { public String public String value; } public class TimeZone { public String value; } XML Java XML

35 35 XML – Tips Must declare XML namespaces: Partial response fields mask is automatically computed URL query parameter: XML public static final XmlNamespaceDictionary DICTIONARY = new XmlNamespaceDictionary().set("", "http://www.w3.org/2005/Atom") // default namespace.set("gCal", "http://schemas.google.com/gCal/2005"); public class CalendarUrl extends GoogleUrl {... } F executeGetFeed(CalendarUrl url, Class feedClass) throws IOException { url.fields = GoogleAtom.getFieldsFor(feedClass); HttpRequest request = requestFactory.buildGetRequest(url); return request.execute().parseAs(feedClass); }

36 36 Media Download Media (GET): –HttpResponse.getContent() returns InputStream –HttpResponse.contentType is the media type Upload Media (POST or PUT): –Use InputStreamContent for uploading an input stream type is the content type length is the length of the media content (if known) inputStream is the media content input stream Photos Videos

37 37 Media Photos Videos public class PostPhotoActivity extends Activity public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); HttpRequestFactory requestFactory = new NetHttpTransport().createRequestFactory(); Intent intent = getIntent(); Bundle extras = intent.getExtras(); InputStreamContent content = new InputStreamContent(); ContentResolver contentResolver = getContentResolver(); Uri uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM); content.inputStream = contentResolver.openInputStream(uri); Cursor cursor = contentResolver.query(uri, null, null, null, null); cursor.moveToFirst(); content.type = intent.getType(); content.length = cursor.getLong(cursor.getColumnIndexOrThrow(Images.Media.SIZE)); HttpRequest request = requestFactory.buildPostRequest(new GenericUrl( "https://picasaweb.google.com/data/feed/api/user/default/albumid/default"), content); GoogleHeaders headers = new GoogleHeaders(); request.headers = headers; String fileName = cursor.getString(cursor.getColumnIndexOrThrow(Images.Media.DISPLAY_NAME)); headers.setSlugFromFileName(fileName); request.execute().ignore(); }

38 38 APIs OAuth 2.0 Client Login OAuth 1.0 Photos Videos XMLJSON Auth New Google APIs Google Data APIs Data Formats Any REST APIs Platforms Android Google App Engine Java 5 (SE, EE) OUTLINE

39 39 AccountManager User accounts centrally controlled on Android –Including synchronization AccountManager: abstraction to store auth token per account Need to know the “account type” and “auth token type” Google Accounts controlled by AccountManager –Account type always “com.google” –Auth token type depends on authentication method and Google API –Tip: library provides a handy GoogleAccountManager Don’t try to bypass AccountManager and handle authentication yourself Auth

40 40 ClientLogin (goo.gl/WkGFX) Username/password authentication for Google Data APIs –Not supported by new Google APIs, like Buzz and Latitude! Request permission from user to have complete read/write access to a Google service Auth token type is “service name” –For example “cl” for Google Calendar Client Login

41 41 ClientLogin for Calendar Example Client Login

42 42 ClientLogin for Calendar Example (1 of 3) public class HelloCalendarActivity extends ListActivity { GoogleAccountManager accountManager; HttpRequestFactory requestFactory; SharedPreferences settings; String accountName; String public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestFactory = transport.createRequestFactory(new HttpRequestInitializer() { public void initialize(HttpRequest request) { GoogleHeaders headers = new GoogleHeaders(); headers.gdataVersion = "2"; headers.setGoogleLogin(authToken); request.headers = headers; } }); Client Login

43 43 ClientLogin for Calendar Example (2 of 3) accountManager = new GoogleAccountManager(this); settings = this.getSharedPreferences("prefs", 0); authToken = settings.getString("authToken", null); accountName = settings.getString("accountName", null); Account account = accountManager.getAccountByName(accountName); if (account == null) { chooseAccount(); } else { new LoadCalendars().execute(); } Client Login

44 44 ClientLogin for Calendar Example (3 of 3) private static final String AUTH_TOKEN_TYPE = "cl"; private void chooseAccount() { AccountManager.get(this).getAuthTokenByFeatures("com.google", AUTH_TOKEN_TYPE, null, this, null, null, new AccountManagerCallback () { public void run(AccountManagerFuture future) { try { Bundle bundle = future.getResult(); setAccountName(bundle.getString(AccountManager.KEY_ACCOUNT_NAME)); setAuthToken(bundle.getString(AccountManager.KEY_AUTHTOKEN)); new LoadCalendars().execute(); } catch (Exception e) { } }, null); } Client Login

45 45 OAuth 2.0 (goo.gl/CdEGm) Latest OAuth standard, supported by (almost) all Google APIs –Including the Google Data APIs Request a more fine-grained “scope” of access –Example for Google Buzz: https://www.googleapis.com/auth/buzz for read/write access to Buzz data https://www.googleapis.com/auth/buzz.readonly for read access to Buzz data https://www.googleapis.com/auth/photos for read access to Buzz photos Auth tokens are temporary and expire in 1 hour –Check for 401 error response code and go through auth flow again OAuth 2.0

46 46 OAuth 2.0 – Getting an Auth Token Sorry, don’t have an ideal story here yet. Use auth token type of “oauth2:” plus space-separated scopes –For example: oauth2:https://www.googleapis.com/auth/buzz –Code example is exactly the same, just change the AUTH_TOKEN_TYPE OAuth 2.0

47 47 OAuth 2.0 for Buzz Example OAuth 2.0

48 48 OAuth 2.0 – Issues Issue #1: User Interface shows the auth token type, not a comprehensible message about what permission is being granted –Quick-and-dirty: you can use “Google Buzz” as an alias for “oauth2:https://www.googleapis.com/auth/buzz”. We will try to set up more of these aliases. Issue #2: Anonymous unregistered quota only gives you zero or near- zero for new Google APIs like Buzz –Solution: register on the Google apis console and get an “API key” or “access key” from the API Access tab under “Simple API Access” –Make sure you flip the switch to ON for the API you need in the “Services” tab –Free registered quota for Buzz for example 1,000,000 queries/day, so you only pay for usage above that level OAuth 2.0

49 49 OAuth 2.0 for Buzz Example (1 of 4) public class HelloBuzzActivity extends ListActivity { private static final String AUTH_TOKEN_TYPE = "oauth2:https://www.googleapis.com/auth/buzz"; GoogleAccessProtectedResource accessProtectedResource = new GoogleAccessProtectedResource(null); Buzz buzz; Account public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); buzz = new Buzz(new NetHttpTransport(), accessProtectedResource, new AndroidJsonFactory()); buzz.accessKey = "ABCdef123_9q";... if (account != null && accessProtectedResource.getAccessToken() == null) { getAuthToken(account); } OAuth 2.0

50 50 OAuth 2.0 for Buzz Example (2 of protected ActivityFeed doInBackground(Void... params) { try { // execute HTTP requests } catch (HttpResponseException e) { if (e.response.statusCode == 401) { accountManager.invalidateAuthToken(accessProtectedResource.getAccessToken()); accessProtectedResource.setAccessToken(null); SharedPreferences.Editor editor2 = settings.edit(); editor2.remove(PREF_AUTH_TOKEN); editor2.commit(); getAuthToken(account); } OAuth 2.0

51 51 OAuth 2.0 for Buzz Example (3 of 4) private static final String AUTH_TOKEN_TYPE = "oauth:https://www.googleapis.com/auth/buzz"; private void getAuthToken(Account account) { AccountManager.get(this).getAuthToken(account, AUTH_TOKEN_TYPE, true, new AccountManagerCallback () { public void run(AccountManagerFuture future) { try { Bundle bundle = future.getResult(); if (bundle.containsKey(AccountManager.KEY_INTENT)) { Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT); intent.setFlags(intent.getFlags() & ~Intent.FLAG_ACTIVITY_NEW_TASK); startActivityForResult(intent, REQUEST_AUTHENTICATE); } else if (bundle.containsKey(AccountManager.KEY_AUTHTOKEN)) { setAuthToken(bundle.getString(AccountManager.KEY_AUTHTOKEN)); new LoadActivities().execute(); } } catch (Exception e) { } }, null); } OAuth 2.0

52 52 OAuth 2.0 for Buzz Example (4 of 4) public static final int REQUEST_AUTHENTICATE = protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQUEST_AUTHENTICATE: if (resultCode == RESULT_OK) { gotAuthToken(account); } else { // user denied } break; } OAuth 2.0

53 53 APIs OAuth 2.0 Client Login OAuth 1.0 Photos Videos XMLJSON Auth New Google APIs Google Data APIs Data Formats Any REST APIs Platforms Android Google App Engine Java 5 (SE, EE) OUTLINE

54 54 Conclusion Google APIs Client Library for Java (goo.gl/ZrqPu) –Now in Beta! –Supports all Google APIs Generated libraries for Google APIs on new infrastructure Supports JSON, XML, and media Supports ClientLogin and OAuth 2.0 –Android developer’s guide (goo.gl/Wk5An) –Questions/Comments: Support page (goo.gl/PCNUx) Discussion on the Google Group (goo.gl/ZOMtp)

55 Questions? Speaker Feedback: goo.gl/EUnAo Twitter Hashtags: #io2011 #GoogleAPIs #Android

56


Download ppt "Best Practices for Accessing Google APIs on Android Yaniv Inbar May 10, 2011 Speaker Feedback: goo.gl/EUnAo Twitter Hashtags: #io2011 #GoogleAPIs #Android."

Similar presentations


Ads by Google