Upgrade to Pro — share decks privately, control downloads, hide ads and more …

(O)Authenticated rest interaction in Android

(O)Authenticated rest interaction in Android

A talk about rest interaction and oauth in android I gave in Droidcon Italy 2014. More details can be found here http://mytechaddiction.blogspot.it/2014/02/rest-interaction-in-android.html

Federico Paolinelli

February 07, 2014
Tweet

More Decks by Federico Paolinelli

Other Decks in Technology

Transcript

  1. Http call (*) URL url = new URL(“https://api.github.com/users/fedepaol/events");! ! HttpURLConnection

    conn = (HttpURLConnection) url.openConnection();! ! InputStream in = new BufferedInputStream(conn.getInputStream());! // do whatever you want with the stream! conn.disconnect();! (*)Try/Catches not included
  2. … or at least • providing a good user experience

    • being efficient in terms of power / bandwidth
  3. Antipatterns • Performing the call on the ui thread •

    Hosting the thread that perform the call in the activity (or fragment)
  4. Antipatterns • Performing the call on the ui thread •

    Hosting the thread that perform the call in the activity (or fragment) • Storing the results (only) in memory
  5. Decoupling the call from the UI • The activity might

    be killed • Config changes handling
  6. Decoupling the call from the UI • The activity might

    be killed • Config changes handling • Can’t schedule requests
  7. Decoupling the call from the UI • The activity might

    be killed • Config changes handling • Can’t schedule requests • Harder to test
  8. Service A facility for the application to tell the system

    about something it wants to be doing in the background (even when the user is not directly interacting with the application)
  9. How to tell the service to initiate a request Activity

    Service startService() Intent onStartCommand()
  10. How to tell the service to initiate a request (2)

    Activity Service bindService() bind() ServiceInterface onBind()
  11. CONS PROS Services pros / cons • Can run in

    background • Can be scheduled • When bound, offers a rich interface • Needs to be shut down • Needs to perform requests in a different thread
  12. IntentService • Performs the request inside a different thread •

    Dies when onHandleIntent returns • Queued • Command pattern protected void onHandleIntent(Intent intent) {! String myParameter = intent.getExtras().getString(…);! ! // Handle your request here! }
  13. Where to store the data • Reloading the same data

    has a cost • Decoupled from the ui • Data can be accessed when offline/prefetched Persistent Storage SQLite Content Provider
  14. Storage Use Transactions (and yieldIfContededSafely()) ! bulkInsert() with content providers

    ! Load only New data if the api offers a “since” parameter
  15. Notify the UI • Local Broadcasts ! ! • Bound

    Interface (not available with intent services) ! • EventBus (Otto, GreenRobot’s EventBus) ! Intent intent = new Intent(Constants.SERVER_REQUEST_DONE);! intent.putExtra(Constants.REQUEST_ID, mRequestId);! intent.putExtra(Constants.IGNORE_PENDING_ID, mIgnorePending);! LocalBroadcastManager.getInstance(c).sendBroadcast(intent);
  16. Notify the UI when using ContentProviders • Register observers •

    CursorLoader gets notified and reloads the cursor @Override! public Cursor query(Uri uri, String[] projection, String selection,! String[] selectionArgs, String sortOrder) {! // perform the query! cursor.setNotificationUri(getContext().getContentResolver(), uri);! return cursor;! }! ! @Override! public Uri insert(Uri uri, ContentValues values) {! // ..! getContext().getContentResolver().notifyChange(insertedId, null);! // ..! }!
  17. When to fetch the data React to user input !

    Scheduled prefetch (using AlarmManager) ! Push from the server ( GCM)
  18. Big cookie approach • The cell radio is one of

    the biggest battery drains on the phone • It takes up to 2 seconds to turn the radio on • Every time you transfer data, the radio is powered on for nearly 30 seconds
  19. SyncAdapters • Designed to be used together with Content Providers

    and Account Authenticator • Native retry mechanism and exponential backoff • Check network availability • Sync with other apps • (Were) a bit tricky to setup http://developer.android.com/training/sync-adapters/
  20. Robospice • Service decouples the interaction from the ui •

    Very high level, strongly typed • A lot of features such as caching, json parsing, prioritizing • Retry policy • Very active development https://github.com/octo-online/robospice
  21. PostmanLib • Allows asynchronous requests • Built on top of

    java scribe library • Tracks the state of pending requests https://github.com/fedepaol/PostmanLib--Rings-Twice--Android
  22. Implement a RestRequest interface public class PostmanRequest implements RestServerRequest {!

    @Override! public String getUrl() {! return "https://api.github.com/users/fedepaol/events";! }! ! @Override! public Verb getVerb() {! return Verb.GET;! }! ! @Override! public void onHttpResult(Response result, ! int statusCode, ! RequestExecutor executor,! Context context) throws ResultParseException {! String resultToParse = result.getBody();! // ...! }! } https://github.com/fedepaol/PostmanLib--Rings-Twice--Android
  23. Implement a RestRequest interface public class PostmanRequest implements RestServerRequest {!

    @Override! public String getUrl() {! return "https://api.github.com/users/fedepaol/events";! }! ! @Override! public Verb getVerb() {! return Verb.GET;! }! ! @Override! public void onHttpResult(Response result, ! int statusCode, ! RequestExecutor executor,! Context context) throws ResultParseException {! String resultToParse = result.getBody();! // ...! }! } https://github.com/fedepaol/PostmanLib--Rings-Twice--Android
  24. Implement a RestRequest interface public class PostmanRequest implements RestServerRequest {!

    @Override! public String getUrl() {! return "https://api.github.com/users/fedepaol/events";! }! ! @Override! public Verb getVerb() {! return Verb.GET;! }! ! @Override! public void onHttpResult(Response result, ! int statusCode, ! RequestExecutor executor,! Context context) throws ResultParseException {! String resultToParse = result.getBody();! // ...! }! } https://github.com/fedepaol/PostmanLib--Rings-Twice--Android
  25. Send a request and track the result PostmanRequest r =

    new PostmanRequest();! PostmanRequest r1 = new PostmanRequest();! ServerInteractionHelper.getInstance(this).sendRestAction(this, "ReqID", r, r1);! ! ! ! ! @Override! protected void onResume() {! mHelper.registerEventListener(this, this);! if (mHelper.isRequestAlreadyPending("ReqID")) {! // notify that a request is still pending, ie action bar spinner! }! }! ! @Override! public void onServerResult(String result, String requestId) {! if ("MyRequestID".equals(requestId)) {! // update the ui! }! https://github.com/fedepaol/PostmanLib--Rings-Twice--Android
  26. Send a request and track the result PostmanRequest r =

    new PostmanRequest();! PostmanRequest r1 = new PostmanRequest();! ServerInteractionHelper.getInstance(this).sendRestAction(this, "ReqID", r, r1);! ! ! ! ! @Override! protected void onResume() {! mHelper.registerEventListener(this, this);! if (mHelper.isRequestAlreadyPending("ReqID")) {! // notify that a request is still pending, ie action bar spinner! }! }! ! @Override! public void onServerResult(String result, String requestId) {! if ("MyRequestID".equals(requestId)) {! // update the ui! }! https://github.com/fedepaol/PostmanLib--Rings-Twice--Android
  27. Send a request and track the result PostmanRequest r =

    new PostmanRequest();! PostmanRequest r1 = new PostmanRequest();! ServerInteractionHelper.getInstance(this).sendRestAction(this, "ReqID", r, r1);! ! ! ! ! @Override! protected void onResume() {! mHelper.registerEventListener(this, this);! if (mHelper.isRequestAlreadyPending("ReqID")) {! // notify that a request is still pending, ie action bar spinner! }! }! ! @Override! public void onServerResult(String result, String requestId) {! if ("MyRequestID".equals(requestId)) {! // update the ui! }! https://github.com/fedepaol/PostmanLib--Rings-Twice--Android
  28. PostmanLib • Can batch / chain requests • Does not

    provide storage / caching • Does not provide scheduling out of the box • Can get a PendingIntent out of a request to schedule • Requests need to implement Parcelable https://github.com/fedepaol/PostmanLib--Rings-Twice--Android
  29. OAuth • Allows to access resources owned by the user

    without sharing credentials with the app • Used by nearly all the rest apis • User can revoke the permissions
  30. OAuth 1.0(a) - SignPost • Lightweight • Does not wrap

    http calls • Easy to use ! http://code.google.com/p/oauth-signpost/
  31. Java Scribe • Uses HttpUrlConnection under the hood • Comes

    with a lot of api support included • Supports OAuth 1.0 and OAuth 2.0 • Does not expose the HttpUrlConnection outside https://github.com/fernandezpablo85/scribe-java
  32. How to get the Auth Code use the System Browser

    ! open a WebView ! use a Custom Activity
  33. PostmanLib Register an oauth service private void setAuthService() {! OAuthHelper

    o = OAuthHelper.getInstance();! if (!o.isAlreadyAuthenticated("Facebook", this)) {! StorableServiceBuilder builder = new ! StorableServiceBuilder("Facebook")! .provider(FacebookApi.class)! .apiKey("xxxxxxxx")! .apiSecret("yyyyyyyyyy")! .callback("http://www.yoururl.com/callback", "code")! .scope("publish_actions");! ! o.registerOAuthService(builder, this);! }! } https://github.com/fedepaol/PostmanLib--Rings-Twice--Android
  34. PostmanLib Obtain the access token OAuthHelper o = OAuthHelper.getInstance();! if

    (!o.isAlreadyAuthenticated("Facebook", this)) {! o.authenticate(this, "Facebook");! } https://github.com/fedepaol/PostmanLib--Rings-Twice--Android
  35. PostmanLib Perform the request public class ShareOnFacebookAction implements RestServerRequest {!

    private static final String url = "https://graph.facebook.com/me/feed";! ! @Override! public String getOAuthSigner() {! return "Facebook";! }! // . . .! } https://github.com/fedepaol/PostmanLib--Rings-Twice--Android