You are on page 1of 44

The Anatomy of Apps

How iPhone, Android & Facebook Apps Consume APIs

Ed Anuff @edanuff Sam Ramji @sramji Brian Mulloy @landlessness

Apigee @apigee

groups.google.com/group/api-craft

youtube.com/apigee

New!

IRC Channel #api-craft

App User

App Store

App

App Developer

World of APIs

API

API Team

Internal Systems

Dogs API
/dogs /owners

Authorization
OAuth 2.0

RESTful API Design - Second Edition http://www.youtube.com/watch?v=QpAhXa12xvU

Build an iPhone App, an Android App and a Facebook Web App*

*Ruby on Rails app hosted on Heroku http://devcenter.heroku.com/articles/facebook

App User

App Store

App

App Developer

World of APIs

API

API Team

Internal Systems

Start with a basic HTTP request

Android
HttpClient client = new DefaultHttpClient(); HttpGet httpGet = new HttpGet("http://api.apizoo.com/v1/dogs"); HttpResponse response = client.execute(httpGet);

iOS
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://api.apizoo.com/v1/dogs"]]; NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];

Ruby on Rails
require 'net/http' response = Net::HTTP.get(api.apizoo.com/v1, /dogs)

Parse the data

Android
JSONObject dogs = new JSONObject(response);

iOS
import "JSONKit.h" NSDictionary *dogs = [response objectFromData];

Ruby on Rails
require 'yajl' parser = Yajl::Parser.new dogs = parser.parse(response) # returns a hash

Resource Object Mapping

Route Map Use

Android Spring Mobile

Route
requestEntity = new HttpEntity<Object>(requestHeaders); ResponseEntity<Dog> responseEntity = restTemplate.exchange("http://api.apizoo.com/v1/dogs/15", HttpMethod.GET, requestEntity, Dog.class);

Android Spring Mobile

Map
// Handled with introspection

Android Spring Mobile

Use
Dog dog = responseEntity.getBody()

iOS RestKit
Route
#import <RestKit/RestKit.h> RKObjectManager* manager = [RKObjectManager objectManagerWithBaseURL:@"http://api.apizoo.com/v1"]; RKDynamicRouter* router = [[RKDynamicRouter new] autorelease]; manager.router = router; [router routeClass:[Dog class] toResourcePath:@"/dogs" forMethod:RKRequestMethodPOST]; [router routeClass:[Dog class] toResourcePath:@"/dogs/(dogID)"];

iOS RestKit

Map
@implementation Dog + (NSDictionary*)elementToPropertyMappings { return [NSDictionary dictionaryWithKeysAndObjects: @"name", @"color", nil]; } @end

iOS RestKit

Use
Dog* dog = [Dog object]; dog.name = @"Rover"; Dog.color = @"red"; [[RKObjectManager sharedManager] postObject:dog delegate:self]; [[RKObjectManager sharedManager] deleteObject:dog delegate:self];

Ruby on Rails ActiveResource

Route
resource :dogs

Ruby on Rails ActiveResource

Map
class Dog < ActiveResource::Base self.site = "http://api.apizoo.com/v1" end

Ruby on Rails ActiveResource

Use
dog = Dog.new name: Rover, color: red dog.save dog.destroy

Cache the response in a database

Android Jersey + Jackson

Usage
Roll your own

iOS RestKit + Core Data

Usage
#import <RestKit/CoreData/CoreData.h> RKObjectManager* manager = [RKObjectManager objectManagerWithBaseURL:@"http://api.apizoo.com/v1"]; manager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:@"DogApp.sqlite"]; @implementation Dog + (NSString*)primaryKeyProperty { return @"dogID"; } @end

Ruby on Rails ActiveResource + ActiveRecord

Usage
class DogResource < ActiveResource::Base self.site = http://api.apizoo.com/v1 end class Dog < ActiveRecord::Base # the before methods call DogResource methods before_create :create_resource before_update :update_resource before_destroy :destroy_resource end

Simple to do list

Problem: we want new capabilities in our app not supported by APIs.

Usergrid - Data & Queries http://www.youtube.com/watch?v=zLl56sU5Bt0

Android
usergrid_ sdk

iOS
Use RESTKit

Ruby on Rails
Probably not applicable

What about offline cases

Android
Roll your own

iOS
-(BOOL)reachable { Reachability *r = [Reachability reachabilityWithHostName:@"api.apizoo.com/v1"]; NetworkStatus internetStatus = [r currentReachabilityStatus]; if(internetStatus == NotReachable) { return NO; } return YES; }

Ruby on Rails
Probably not applicable

Get authorization out of the way

Assumption: the APIs we consume use OAuth 2

Android
Roll your own

iOS RestKit
RKObjectManager* objectManager = [RKObjectManager sharedManager]; objectManager.client.baseURL = @api.apizoo.com/v1"; objectManager.client.OAuth2AccessToken = @"YOUR ACCESS TOKEN"; objectManager.client.authenticationType = RKRequestAuthenticationTypeOAuth2;

Ruby on Rails Oauth Gem


@consumer=OAuth::Consumer.new("key","secret", site: "api.apizoo.com/v1") @request_token=@consumer.get_request_token session[:request_token]=@request_token redirect_to @request_token.authorize_url @access_token=@request_token.get_access_token

Android Built-in JSON, etc. Spring Mobile (bundles Jersey & Jackson) iOS JSONKit RestKit Core Data

Ruby on Rails YAJL ActiveResource Oauth

Coming Up: March Miniseries on Apps & APIs

Questions?

THANK YOU
Subscribe to API webinars at:

youtube.com/apigee

THANK YOU
Chat on IRC #api-craft

THANK YOU
Questions and ideas to:

groups.google.com/group/api-craft

THANK YOU
Contact us at:

@edanuff ed@apigee.com
@sramji sramji@apigee.com @landlessness brian@apigee.com

You might also like