Cross-Platform Data Access for Android and iPhone
Upcoming SlideShare
Loading in...5
×
 

Cross-Platform Data Access for Android and iPhone

on

  • 4,458 views

Many Apps need to access data online. This talk discusses problems and solutions when accessing remote data with Android and iPhone. After a brief review of a number of frameworks, an approach is ...

Many Apps need to access data online. This talk discusses problems and solutions when accessing remote data with Android and iPhone. After a brief review of a number of frameworks, an approach is outlined to implement data access in a cross-platform manner using a DSL.

Statistics

Views

Total Views
4,458
Views on SlideShare
4,364
Embed Views
94

Actions

Likes
5
Downloads
108
Comments
1

4 Embeds 94

http://lanyrd.com 88
http://www.slideshare.net 3
http://www.linkedin.com 2
http://coderwall.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Cross-Platform Data Access for Android and iPhone Cross-Platform Data Access for Android and iPhone Presentation Transcript

  • Cross-Platform Data Access for iPhone and Android MobileTechCon 2011 March 28th - 30th, Munich (c) 2011 @peterfriese / @itemismobile
  • cell phone usage is ubiquitous
  • s t e c n e o p h s p a r y u r o ve se e ifes u ge e a ur l w an o m ofto
  • many services only make sense when connected to the web
  • People are !fferent
  • ... so #ey have !fferent ta$es!
  • countless devices
  • diversity of platforms
  • Problems Solutions
  • (Missing) Connectivity
  • Solution: Detect Connectivity
  • Detecting ConnectivityStates we need to detect:Device not connected to internetConnection slowServer(s) not reachableServer online, but requested service not available
  • Detecting ConnectivityiPhone ReachabilityhostReach = [[ReachabilityreachabilityWithHostName:@"www.apple.com"] retain];[hostReach startNotifier];[self updateInterfaceWithReachability: hostReach];!internetReach = [[ReachabilityreachabilityForInternetConnection] retain];[internetReach startNotifier];[self updateInterfaceWithReachability: internetReach];wifiReach = [[Reachability reachabilityForLocalWiFi] retain];[wifiReach startNotifier];[self updateInterfaceWithReachability: wifiReach];http://developer.apple.com/library/ios/#samplecode/Reachability/
  • Detecting ConnectivityAndroid ConnectivityManagerConnectivityManager connectivity = (ConnectivityManager) getSystemService (Context.CONNECTIVITY_SERVICE);NetworkInfo wifiInfo = connectivity.getNetworkInfo(ConnectivityManager.TYPE_WIFI);NetworkInfo mobileInfo = connectivity.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);http://developer.android.com/reference/android/net/ConnectivityManager.html
  • Different Data Formats Proprietary XML SOAP JSON
  • Solution: Use Different Parsers
  • A Fine Selection of ParsersXMLSAXParser - (Android SDK)DocumentBuilder - (Android SDK)XmlPullParser - (Android SDK)JSONJSONTokener - (Android SDK)JSON Simple - http://code.google.com/p/json-simple/Jackson - http://jackson.codehaus.org/GSon - http://code.google.com/p/google-gson/
  • Parsing JSONGsonpublic T transform(InputStream inputStream) { InputStreamReader reader = new InputStreamReader(inputStream); BufferedReader buffered = new BufferedReader(reader); Gson gson = new Gson(); Type clazz = getGenericType(); T results = gson.fromJson(buffered, clazz); try { buffered.close(); reader.close(); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } return results;}private Type getGenericType() { Type type = ((ParameterizedType)getClass() .getGenericSuperclass()).getActualTypeArguments()[0]; return type;}
  • A Fine Selection of ParsersXMLNSXMLParser - (iPhone SDK)libxml2 - (iPhone SDK)TouchXML - https://github.com/TouchCode/TouchXMLGDataXML - http://code.google.com/p/gdata-objectivec-client/JSONTouchJSON - https://github.com/TouchCode/TouchJSONjson-framework - http://stig.github.com/json-framework/YAJL - https://github.com/lloyd/yajlJSONKit - https://github.com/johnezang/JSONKit
  • Parsing JSONJSONKit#import "JSONKit.h"/...- (id)transform:(NSString *)sourceString {! id input = [sourceString objectFromJSONString]; id result = nil; if ([input isKindOfClass:[NSArray class]]) { result = [self transformArray:input]; } else if ([input isKindOfClass:[NSDictionary class]]) { result = [self transformDictionary:input]; } return result;}
  • Data Quality
  • Solution: Massage Data
  • Massaging !!In-App vs. OnlineIn-App massaging:- needs to be rewritten for each platform- ad-hoc enhancements virtually impossible (iPhone)Server-side massaging:- write once, re-use with every app- problem with authentication (man-in-the-middle)
  • MassagingOnline toolsFeedSanitizer - http://feedsanitizer.appspot.com/HTML Tidy - http://infohound.net/tidy/JSONFormatter - http://jsonformatter.curiousconcept.com/Roll your ownYQL - http://developer.yahoo.com/yql/Node.js - http://nodejs.org/Google App Engine - http://code.google.com/appengine/
  • Massaging withvar sponsorImageExpr = /Sponsored by:.*<img.*src="(.*)">?/;var sponsoredByFilter = new SimpleFilter(function(data) {! session = data;! if (session.title.match(sponsorImageExpr)) {! ! sponsorlogoURL = session.title.match(sponsorImageExpr);! ! session.sponsorLogoURL = sponsorlogoURL[1];! ! session.title = session.title.replace( sponsorImageExpr, );!!! }! return session;});var stripHTMLFilter = new SimpleFilter(function(string) {! return string.replace(/</?[^>]+(>|$)/g, );});var sessionsFilterChain =! new FilterChain()! ! .append(sponsoredByFilter)! ! .append(stripHTMLFilter);
  • Massaging withapp.get(/sessions.:format, function(request, response) {! var isXML = (request.params.format == xml);! dataProvider.getAllSessions(function(sessions) {! ! if (isXML) {! ! ! response.header("Content-Type", "text/xml");! ! ! response.render(sessions.ejs, { layout: false, locals: { sessions: sessions } });! ! }! ! else {! ! ! response.header("Content-Type", "application/json");! ! ! response.send(JSON.decycle(shallow(sessions, 3)));! ! }! !! });});
  • Offline Data Access
  • Solution: Use Caching
  • CachingStore in a local SQL databaseSQLite - (Android SDK)OrmLite - http://ormlite.com/db4o - http://db4o.com/ActiveAndroid - https://www.activeandroid.com/AndroidActiveRecord - http://code.google.com/p/android-active-record/Store in the local file systemUse cache directory - Context.getCacheDir()
  • CachingStore in a local SQL databaseSQLite - (iPhone SDK)ActiveRecord - https://github.com/aptiva/activerecordCoreData - (iPhone SDK)Store in the local file systemURLCache sample - http://developer.apple.com/library/ios/#samplecode/URLCache
  • Putting it all together
  • Solution: Data Access Frameworks
  • FeaturesHandle spotty connectivitySupport multiple data formats (XML / JSON)Massage dataProvide offline data accessMap data to language concepts
  • Data AccessFrameworksActiveAndroid - https://www.activeandroid.com/AndroidActiveRecord - http://code.google.com/p/android-active-record/RESTProvider - https://github.com/novoda/RESTProvider
  • Data AccessFrameworks / Features Flex. Mapping Connectivity Caching JSON XMLActiveAndroid ! ! ! " "AndroidActiveRecord ! ! ! " "RESTProvider # " " #* " * experimental
  • Data AccessFrameworks / Features Flex. Mapping Connectivity Caching JSON XML ce sis tenActiveAndroid ! ! ! " er P" Ws FAndroidActiveRecord ! ! ! " "RESTProvider # " " #* " * experimental
  • Data Access RESTProviderpublic class TwitterFeedExample extends ListActivity { @Override public void onCreate(Bundle b) { super.onCreate(b); CPAsyncHandler g = new CPAsyncHandler(getContentResolver()); g.startQuery(1, null, Uri.parse("content://novoda.rest.test.twitter"), null, "q=?", new String[] { "droidcon" }, null); } private class CPAsyncHandler extends AsyncQueryHandler { @Override protected void onQueryComplete(int token, Object cookie, Cursor c) { super.onQueryComplete(token, cookie, c); setListAdapter(new SimpleCursorAdapter(TwitterFeedExample.this, android.R.layout.simple_list_item_2, c, new String[] { "from_user", "text" }, new int[] { android.R.id.text1, android.R.id.text2 })); } }}
  • Data AccessFrameworksiPhone on Rails - http://iphoneonrails.com/CoreResource - http://coreresource.org/RestKit - http://restkit.org/
  • Data AccessFrameworks / Features Flex. Mapping Connectivity Caching JSON XMLiPhoneOnRails # " " ! "CoreResource " " " " "RESTKit " " " " "
  • Data Access RESTKit- (void)loadContact { RKObjectManager* manager = [RKObjectManager objectManagerWithBaseURL:@"http://restkit.org"]; [manager loadObjectsAtResourcePath:@"/contacts/1" objectClass:[Contact class] delegate:self]}// RKObjectLoaderDelegate methods- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects{ Contact* contact = [objects objectAtIndex:0]; NSLog(@"Loaded Contact ID #%@ -> Name: %@, Company: %@", contact.id, contact.name, contact.company);}
  • Plethora of Languages ?@#!Objective-C C# Java JavaScript
  • Solution: Use A DSL
  • Solution: Use A DSL Entities Data View Mappers Controllers Entity Descriptions DSL iOS / Objective-Cdescribes data model andmapping rules Entities DSL IDE Transformers Activities Content Providers Android / Java
  • DSL Sample Fetching Blog Itemsentity BlogItem { String guid String title String link String description String creator}contentprovider Blogposts returns BlogItem[] fetches XML from (FEEDSANITIZER_URL "/sanitize?url=http%3A%2F%2Fblogs.itemis.de%2F%3Fshowfeed%3D1&format=rss") selects "rss.channel.item"
  • http://mobile.itemis.de@peterfriese | http://peterfriese.de
  • Image credits Tower bridge - http://www.flickr.com/photos/anirudhkoul/3499471010/ Little girl with cell - http://www.flickr.com/photos/spitzgogo/286917522/ Gray-haired guy on bench - http://www.flickr.com/photos/mr_t_in_dc/5524143121/ Girl with hoody, texting - http://www.flickr.com/photos/lanier67/2979124681/ Fast girl on bike - http://www.flickr.com/photos/pixel_addict/465394708/ NY Apple Store - http://www.flickr.com/photos/smoovey/3749038495/ Guy driving and texting - http://www.flickr.com/photos/lord-jim/4794895023/ Portraits: http://www.flickr.com/photos/46914331@N03/4312184861/ http://www.flickr.com/photos/pagedooley/4258558487/ http://www.flickr.com/photos/yuri-samoilov/4105603525/ http://www.flickr.com/photos/adriel_socrates/5560606768/ http://www.flickr.com/photos/adriel_socrates/5560592742/in/photostream/ http://www.flickr.com/photos/kkoshy/4729866481/ http://www.flickr.com/photos/pagedooley/4258558741/ http://www.flickr.com/photos/mescon/3668279183/ http://www.flickr.com/photos/mescon/2984454695/ http://www.flickr.com/photos/ter-burg/428205830/ http://www.flickr.com/photos/eudaimos/2107219904/ Mountains, Lake and Boat - http://www.flickr.com/photos/visulogik/2180603155/ Dead Sea Scrolls - http://www.flickr.com/photos/kjfnjy/5249145754/ Lines of communication - http://www.flickr.com/photos/ruudhein/4442182264/ Satellite dish - http://www.flickr.com/photos/26652703@N02/2502519971/