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

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Cross-Platform Data Access for Android and iPhone

5,660
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 …

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

1 Comment
5 Likes
Statistics
Notes
No Downloads
Views
Total Views
5,660
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
137
Comments
1
Likes
5
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

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