56

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

Embed Size (px)

Citation preview

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

Best Practices for Accessing Google APIs on AndroidYaniv InbarMay 10, 2011

Speaker Feedback: goo.gl/EUnAoTwitter Hashtags: #io2011 #GoogleAPIs #Android

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

Google APIs Client Library for Java (goo.gl/ZrqPu)

Now in Beta

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

4

APIs

OAuth 2.0

ClientLogin

OAuth 1.0

PhotosVideos

XMLJSON

Auth

New Google

APIs

Google DataAPIs

DataFormats

AnyRESTAPIs

Platforms AndroidGoogle

App Engine

Java 5 (SE, EE)

OUTLINE

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

5

APIs

OAuth 2.0

ClientLogin

OAuth 1.0

PhotosVideos

XMLJSON

Auth

New Google

APIs

Google DataAPIs

DataFormats

AnyRESTAPIs

Platforms AndroidGoogle

App Engine

Java 5 (SE, EE)

OUTLINE

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

6

PlatformsJava 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

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

7

HelloBuzz Examplepublic class HelloBuzz {

public static void main(String[] args) throws IOException {

Buzz buzz = new Buzz(new NetHttpTransport(), new JacksonFactory());

ActivityFeed feed = buzz.activities.list("112550920411899420633", "@public").execute();

if (feed.items != null)

for (Activity activity : feed.items)

System.out.println(activity.buzzObject.content);

}

}

Java 5 (SE, EE)

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

8

HelloBuzzServlet Examplepublic class HelloBuzzServlet extends HttpServlet {

@Override

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("112550920411899420633", "@public").execute();

if (feed.items != null)

for (Activity activity : feed.items)

writer.println(activity.buzzObject.content);

}

}

Google App

Engine

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

9

HelloBuzzActivity Examplepublic class HelloBuzzActivity extends ListActivity {

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Buzz buzz = new Buzz(new NetHttpTransport(), new AndroidJsonFactory());

List<Spanned> activities = new ArrayList<Spanned>();

try {

ActivityFeed feed = buzz.activities.list("112550920411899420633", "@public").execute();

if (feed.items != null)

for (Activity activity : feed.items)

activities.add(Html.fromHtml(activity.buzzObject.content));

setListAdapter(new ArrayAdapter<Spanned>(this,

android.R.layout.simple_expandable_list_item_1, activities));

} catch (IOException e) {}

}

}

Android

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

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

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

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;

}

});

}

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

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

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

13

AndroidAndroid: 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)

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

14

HelloBuzzAsyncActivity Example (part 1 of 2)public class HelloBuzzActivity extends ListActivity {

final Buzz buzz = new Buzz(new NetHttpTransport(), new AndroidJsonFactory());

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

new LoadActivities().execute();

}

class LoadActivities extends AsyncTask<Void, Void, ActivityFeed> {

final ProgressDialog dialog = new ProgressDialog(HelloBuzzActivity.this);

@Override

protected void onPreExecute() {

dialog.setMessage("Loading Activities...");

dialog.show();

}

@Override

protected ActivityFeed doInBackground(Void... params) {

try {

return buzz.activities.list("112550920411899420633", "@public").execute();

} catch (IOException e) { return null; } }

Android

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

15

HelloBuzzAsyncActivity Example (part 2 of 2) @Override

protected void onPostExecute(ActivityFeed feed) {

dialog.dismiss();

if (feed == null)

return;

List<Spanned> activities = new ArrayList<Spanned>();

if (feed.items != null)

for (Activity a : feed.items)

activities.add(Html.fromHtml(a.buzzObject.content));

setListAdapter(new ArrayAdapter<Spanned>(HelloBuzzActivity.this,

android.R.layout.simple_expandable_list_item_1, activities));

}

}

}

Android

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

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

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

17

Android – Shrink Application with ProGuardAndroid

Full ProGuard0

500

1000

1500

2000

2500

2300

123

Application Size (KBs)

Based on HelloBuzzActivity sample (95% savings)

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

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 and @Key annotations accessed via reflection

-keepclassmembers class * {

@com.google.api.client.util.Key <fields>;

}

-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault

# Needed by Guava

-dontwarn sun.misc.Unsafe

Android

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

19

APIs

OAuth 2.0

ClientLogin

OAuth 1.0

PhotosVideos

XMLJSON

Auth

New Google

APIs

Google DataAPIs

DataFormats

AnyRESTAPIs

Platforms AndroidGoogle

App Engine

Java 5 (SE, EE)

OUTLINE

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

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 DataAPIs

YouTube Data API

Google Calendar Data API

Blogger Data API

Google Contacts Data API

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

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 DataAPIs

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

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

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

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

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

24

Google APIs – Explorer (goo.gl/Ccni0) New Google

APIs• Web-based Google APIs exploration tool

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

25

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

APIs

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

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("112550920411899420633", "@public").execute();

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 = buzz.activities.insert("@me", activity).execute();

buzz.activities.delete("@me", "@self", activity.id).execute();

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

27

APIs

OAuth 2.0

ClientLogin

OAuth 1.0

PhotosVideos

XMLJSON

Auth

New Google

APIs

Google DataAPIs

DataFormats

AnyRESTAPIs

Platforms AndroidGoogle

App Engine

Java 5 (SE, EE)

OUTLINE

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

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

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

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<Activity>)

– Extend GenericJson when you need to preserve arbitrary fields

• Important when using PUT to update an entry to avoid dropping data

JSON

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

30

JSON – Data Model Example

{

"updated": "2010-05-20T23:08:07.471Z",

"id": "tag:google.com,2010:buzz:z12nu3oa1r25gr3wp04cd3zp2zvafrjrlso0k",

"object": {

"content": "Presenting live at Google I/O!”

}

}

public class Activity {

@Key public DateTime updated;

@Key public String id;

@Key public ActivityObject object;

}

public class ActivityObject {

@Key public String content;

}

JSON

Java

JSON

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

31

JSON – Gzip and Partial ResponseBased on HelloBuzz sample (95% savings)

Full Gzip Gzip & Partial0

1000

2000

3000

4000

5000

6000

7000

8000

7036

1289286

Response Size (bytes)

JSON

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

32

JSON Example – Partial with the Generated Libraries

• Before:

• After:

• Or for more data:

Buzz.Activities.List request = buzz.activities.list("112550920411899420633", "@public");request.fields = "items/object/content";ActivityFeed feed = request.execute();

JSON

ActivityFeed feed = buzz.activities.list("112550920411899420633", "@public").execute();

Buzz.Activities.List request = buzz.activities.list("112550920411899420633", "@public");request.fields = "items(object/content,updated,id)";ActivityFeed feed = request.execute();

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

33

JSON: streaming entries HttpResponse response = buzz.activities.list("112550920411899420633", "@public").executeUnparsed();

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

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

34

XML – Data Model<entry xmlns='http://www.w3.org/2005/Atom’ xmlns:gCal='http://schemas.google.com/gCal/2005'>

<id>http://www.google.com/calendar/feeds/default/calendars/abc123%40group.calendar.google.com</id>

<updated>2011-05-09T23:59:51.000Z</updated>

<title type='text'>abc 2</title>

<gCal:timezone value='UTC'/>

</entry>

public class CalendarEntry {

@Key public String id;

@Key public DateTime updated;

@Key public Title title;

@Key(“gCal:timezone”) public TimeZone timeZone;

}

public class Title {

@Key(“@type”) public String type;

@Key(“text()”) public String value;

}

public class TimeZone {

@Key(“@value”) public String value;

}

XML

Java

XML

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

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 extends Feed> F executeGetFeed(CalendarUrl url, Class<F> feedClass) throws IOException { url.fields = GoogleAtom.getFieldsFor(feedClass); HttpRequest request = requestFactory.buildGetRequest(url); return request.execute().parseAs(feedClass);}

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

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

PhotosVideos

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

37

MediaPhotosVideos

public class PostPhotoActivity extends Activity { @Override 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(); }}

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

38

APIs

OAuth 2.0

ClientLogin

OAuth 1.0

PhotosVideos

XMLJSON

Auth

New Google

APIs

Google DataAPIs

DataFormats

AnyRESTAPIs

Platforms AndroidGoogle

App Engine

Java 5 (SE, EE)

OUTLINE

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

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

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

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

ClientLogin

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

41

ClientLogin for Calendar ExampleClientLogin

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

42

ClientLogin for Calendar Example (1 of 3)public class HelloCalendarActivity extends ListActivity {

GoogleAccountManager accountManager;

HttpRequestFactory requestFactory;

SharedPreferences settings;

String accountName;

String authToken;

@Override

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;

}

});

ClientLogin

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

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();

}

}

}

ClientLogin

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

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<Bundle>() {

public void run(AccountManagerFuture<Bundle> 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);

}

ClientLogin

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

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

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

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

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

47

OAuth 2.0 for Buzz ExampleOAuth

2.0

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

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

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

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 account;

@Override

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

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

50

OAuth 2.0 for Buzz Example (2 of 4) @Override

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

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

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<Bundle>() {

public void run(AccountManagerFuture<Bundle> 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

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

52

OAuth 2.0 for Buzz Example (4 of 4) public static final int REQUEST_AUTHENTICATE = 0;

@Override

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

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

53

APIs

OAuth 2.0

ClientLogin

OAuth 1.0

PhotosVideos

XMLJSON

Auth

New Google

APIs

Google DataAPIs

DataFormats

AnyRESTAPIs

Platforms AndroidGoogle

App Engine

Java 5 (SE, EE)

OUTLINE

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

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)

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

Questions?

Speaker Feedback: goo.gl/EUnAoTwitter Hashtags: #io2011 #GoogleAPIs #Android

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