Cross-Platform Data Access for Android and iPhone

6,298 views

Published on

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.

Published in: Technology

Cross-Platform Data Access for Android and iPhone

  1. 1. Cross-Platform Data Access for iPhone and Android MobileTechCon 2011 March 28th - 30th, Munich (c) 2011 @peterfriese / @itemismobile
  2. 2. cell phone usage is ubiquitous
  3. 3. 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
  4. 4. many services only make sense when connected to the web
  5. 5. People are !fferent
  6. 6. ... so #ey have !fferent ta$es!
  7. 7. countless devices
  8. 8. diversity of platforms
  9. 9. Problems Solutions
  10. 10. (Missing) Connectivity
  11. 11. Solution: Detect Connectivity
  12. 12. Detecting ConnectivityStates we need to detect:Device not connected to internetConnection slowServer(s) not reachableServer online, but requested service not available
  13. 13. 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/
  14. 14. 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
  15. 15. Different Data Formats Proprietary XML SOAP JSON
  16. 16. Solution: Use Different Parsers
  17. 17. 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/
  18. 18. 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;}
  19. 19. 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
  20. 20. 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;}
  21. 21. Data Quality
  22. 22. Solution: Massage Data
  23. 23. 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)
  24. 24. 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/
  25. 25. 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);
  26. 26. 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)));! ! }! !! });});
  27. 27. Offline Data Access
  28. 28. Solution: Use Caching
  29. 29. 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()
  30. 30. 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
  31. 31. Putting it all together
  32. 32. Solution: Data Access Frameworks
  33. 33. FeaturesHandle spotty connectivitySupport multiple data formats (XML / JSON)Massage dataProvide offline data accessMap data to language concepts
  34. 34. Data AccessFrameworksActiveAndroid - https://www.activeandroid.com/AndroidActiveRecord - http://code.google.com/p/android-active-record/RESTProvider - https://github.com/novoda/RESTProvider
  35. 35. Data AccessFrameworks / Features Flex. Mapping Connectivity Caching JSON XMLActiveAndroid ! ! ! " "AndroidActiveRecord ! ! ! " "RESTProvider # " " #* " * experimental
  36. 36. Data AccessFrameworks / Features Flex. Mapping Connectivity Caching JSON XML ce sis tenActiveAndroid ! ! ! " er P" Ws FAndroidActiveRecord ! ! ! " "RESTProvider # " " #* " * experimental
  37. 37. 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 })); } }}
  38. 38. Data AccessFrameworksiPhone on Rails - http://iphoneonrails.com/CoreResource - http://coreresource.org/RestKit - http://restkit.org/
  39. 39. Data AccessFrameworks / Features Flex. Mapping Connectivity Caching JSON XMLiPhoneOnRails # " " ! "CoreResource " " " " "RESTKit " " " " "
  40. 40. 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);}
  41. 41. Plethora of Languages ?@#!Objective-C C# Java JavaScript
  42. 42. Solution: Use A DSL
  43. 43. 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
  44. 44. 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"
  45. 45. http://mobile.itemis.de@peterfriese | http://peterfriese.de
  46. 46. 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/

×