Best Practices for Accessing Google APIs on Android

flosssnailsΚινητά – Ασύρματες Τεχνολογίες

10 Δεκ 2013 (πριν από 3 χρόνια και 9 μήνες)

72 εμφανίσεις

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

4

APIs

OAuth
2.0

Client

Login

OAuth
1.0

Photos

Videos

XML

JSON

Auth

New
Google
APIs

Google
Data

APIs

Data

Formats

Any

REST

APIs

Platforms

Android

Google
App
Engine

Java 5
(SE, EE)

OUTLINE

5

APIs

OAuth
2.0

Client

Login

OAuth
1.0

Photos

Videos

XML

JSON

Auth

New
Google
APIs

Google
Data

APIs

Data

Formats

Any

REST

APIs

Platforms

Android

Google
App
Engine

Java 5
(SE, EE)

OUTLINE

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

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


if
(
feed.items

!=
null
)


for
(Activity activity :
feed.
items
)


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


}

}

Java 5
(SE, EE)

8

HelloBuzzServlet

Example

public 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

9

HelloBuzzActivity

Example

public 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

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

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

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

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

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

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

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

Android


Shrink Application with
ProGuard

Android

2300

123

0
500
1000
1500
2000
2500
Full
ProGuard

Application Size (KBs)

Based on
HelloBuzzActivity

sample (95% savings)

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

19

APIs

OAuth
2.0

Client

Login

OAuth
1.0

Photos

Videos

XML

JSON

Auth

New
Google
APIs

Google
Data

APIs

Data

Formats

Any

REST

APIs

Platforms

Android

Google
App
Engine

Java 5
(SE, EE)

OUTLINE

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

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

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

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

Google APIs


Explorer (goo.gl/Ccni0)

New
Google
APIs


Web
-
based Google APIs exploration

tool

25

OAuth 2.0


Google
apis

console (
goo.gl/UyAZB
)

New
Google
APIs

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

27

APIs

OAuth
2.0

Client

Login

OAuth
1.0

Photos

Videos

XML

JSON

Auth

New
Google
APIs

Google
Data

APIs

Data

Formats

Any

REST

APIs

Platforms

Android

Google
App
Engine

Java 5
(SE, EE)

OUTLINE

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

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

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

31

JSON


Gzip

and Partial Response

Based on
HelloBuzz

sample (95% savings)

7036

1289

286

0
1000
2000
3000
4000
5000
6000
7000
8000
Full
Gzip
Gzip & Partial
Response Size (bytes)

JSON

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


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

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

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

}







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

Media

Photos

Videos

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


}

}

38

APIs

OAuth
2.0

Client

Login

OAuth
1.0

Photos

Videos

XML

JSON

Auth

New
Google
APIs

Google
Data

APIs

Data

Formats

Any

REST

APIs

Platforms

Android

Google
App
Engine

Java 5
(SE, EE)

OUTLINE

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

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

ClientLogin

for Calendar Example

Client

Login

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;


}


});

Client

Login

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

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


}

Client

Login

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

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

OAuth 2.0 for Buzz Example

OAuth
2.0

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

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

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

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

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

53

APIs

OAuth
2.0

Client

Login

OAuth
1.0

Photos

Videos

XML

JSON

Auth

New
Google
APIs

Google
Data

APIs

Data

Formats

Any

REST

APIs

Platforms

Android

Google
App
Engine

Java 5
(SE, EE)

OUTLINE

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
)

Questions?







Speaker Feedback:
goo.gl/EUnAo

Twitter
Hashtags
:
#io2011 #
GoogleAPIs

#Android