Lessons from developing a Client Server Iphone app


Published on

I launched an iphone app (Discounts For Me). The app downloads data from a server. I share some of the lessons learned while building the app and building the server back end in ruby on rails


Published in: Technology, News & Politics
  • updated presentations : http://sujee.net/tech/articles/iphone-client-server-presentations.php
    Are you sure you want to  Yes  No
    Your message goes here
  • Author : Sujee Maniyam (http://sujee.net)
    Iphone app : http://discountsforme.net/

    please leave comments here : http://sujee.net/blog/tech/tech-lessons-from-building-a-client-server-iphone-app.html
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Lessons from developing a Client Server Iphone app

  1. 1. Lessons from developing anIphone App + Server backend<br />Sujee Maniyam<br />s@sujee.net<br />http://sujee.net<br />http://DiscountsForMe.net<br />Aug 2009<br />
  2. 2. Target Audience<br />Iphone app developers<br />Server backend developers for mobile apps<br />Expert level: Beginner - Intermediate<br />
  3. 3. My Background<br />Developer (enterprise, web)<br />Java / Php / Ruby<br />First iphone/mobile app<br />
  4. 4. App: DiscountsForMe<br />Shows member benefits<br />Based on location<br />V1.0 in app store<br />Memberships:<br />Public radio (KQED)<br />Bank of America card<br />AAA, AARP<br />More…<br />
  5. 5.
  6. 6. Architecture<br />Server (DiscountsForMe.net) serves data<br />Server is Rails app<br />Iphone app talks to the server<br />&lt;Insert usual SERVER ---- INTERNET CLOUD ---- IPHONEpicture here&gt;<br />
  7. 7. Agenda<br />Connectivity<br />Data format<br />Secure Data trasnfer<br />UDIDs & Keys<br />Controlling app from server<br />
  8. 8. Connectivity : Simple Start<br />App makes three server calls<br />ping()<br />get_memberships()<br />get_discounts(my_location, my_memberships)<br />Simulator <br />Iphone over Wi-fi<br />Iphone over 3G <br />LAG-TIME is a problem<br />
  9. 9. Connectivity : Minimize Lag Time<br />Noticeable lag time over 3G/Edge<br />Reducing lag time<br />Condense network calls (especially if the user is waiting for data)<br />Download in background<br />So<br />Get_memberships()<br />Get_discounts(my_location, my_memberships)<br />get_memberships_and_discounts(loc, mymems)<br />
  10. 10. Iphone Connectivity<br />BIG LESSON 1 : <br />Test on IPHONE (not just simulator)<br />Test with WiFi OFF! (3G can be slow to connect, EDGE even worse)<br />You may need to reorganize the logic to improve response time (I had to)<br />LESSON 2<br />Test in AirPlane Mode (all RADIOS off)(a frequent reason network apps are rejected )<br />
  11. 11. Connectivity Test<br />Quick Ping<br />Which is faster?<br />httpS://www.DiscountsForMe.net/ping<br />http://www.google.com<br />SSL always takes longer to establish connection<br />Use faster sites<br />Another snippet from Erica Sadun’s book(to be verified)<br />
  12. 12. Talking to Server : Format<br />Two choices : XML, JSON<br />JSON smaller size than XML (50% less)<br />Json : use TouchJSON library http://code.google.com/p/touchcode/wiki/TouchJSON<br />XML : NSXML(sdk) / TouchXML / KissXMLhttp://www.71squared.co.uk/2009/05/processing-xml-on-the-iphone/<br />
  13. 13. Agenda<br />Connectivity<br />Data format<br />Secure Data transfer<br />UDIDs, Keys, analytics<br />Controlling app from server<br />
  14. 14. Secure Data Transfer<br />Plain HTTP is fine most of the time<br />If you want to secure data<br />Symmetric key encryption (shared ‘seckr3t’ key on Iphone app and server)<br />Public-private key encryption (e.g. SSH) : private key on server, public key on iphone<br />httpS<br />
  15. 15. Secure data transfer : httpS<br />SSL is ‘good enough’ for most of us<br />Get a proper SSL certificate ($30). Self-signed certs don’t work by default<br />Beware connection time is a little longer for httpS<br />Verify your ssl certificate is installed properlyhttp://www.digicert.com/help/<br />
  16. 16. Verify SSL Cert…<br />
  17. 17. Talking to Server : POST req<br />NSMutableURLRequest *request = [NSMutableURLRequestrequestWithURL:url];<br />[request setHTTPMethod:@&quot;POST&quot;];<br />NSMutableString *postString = [NSMutableString string];<br />[postStringappendFormat:@&quot;%@=%@&&quot;, key, value];<br />NSString *postString2 = [postString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];<br />[request setHTTPBody:[postString2 dataUsingEncoding:NSUTF8StringEncoding]];<br />NSURLResponse *response = nil;<br />NSError *error = nil;<br />NSData *data = [NSURLConnectionsendSynchronousRequest:requestreturningResponse:&responseerror:&error];<br />
  18. 18. Talking to Server : Local Server<br />#ifdef DEBUG// dev<br />#define MEMBER_SERVER @”http://localhost:3000”<br />#else// production<br />#define MEMBER_SERVER @”https://discountsforme.net”<br />#endif<br />- And define ‘DEBUG’ in build configurations<br />
  19. 19. Talking to Server : Dedicated Class<br /><ul><li>Don’t do URL connections all over the code. Have a class do it
  20. 20. Easy to debug
  21. 21. Use named methods (getDiscounts Vs connectToURL)</li></ul>@interface ServerConnection : NSObject {<br />}<br />+ (BOOL) testConnectivity;<br />+ (BOOL) isConnected;<br />+ (NSArray *) getMemberships;<br />+ (NSArray *) getDiscounts:(NSDictionary *) params;<br />@end<br />
  22. 22. Agenda<br />Connectivity<br />Data format<br />Secure Data transfer<br />UDIDs, Keys, multiple versions, analytics<br />Controlling app from server<br />
  23. 23. What do I send to the server?<br />get_memberships()<br />No parameters?...<br />Think about including<br />UDID (device id)<br />And a Key (compiled within the app)<br />http://discountsforme.net/iphone/get_memberships<br />http://discountsforme.net/iphone/get_memberships?udid=xxxx&key=yyyy<br />
  24. 24. Server Side : Unique Device ID<br />Each mobile device has a uniq ID, etched in hardware (just like MAC address)<br />Your app can send UDID with each request<br />Of course : encrypt it or via SSL<br />Very useful for metrics on app usage<br />How many unique devices have the app<br />Access patterns (repeat uses)<br />Easy account creation (no signup)<br />
  25. 25. Server side : access keys<br />Start using ‘access keys’ from day-1<br />Sample key = “iphone_v1.0_xklajdfoi2” (human readable + hard to guess)<br />Each request to server must have a valid key<br />Easy to control client access<br />Prevent scraping, DOS ..etc<br />Monitoring (what versions are being used)<br />Support multiple versions, easy upgrade<br />
  26. 26. Supporting multiple versions<br />May be supporting 2-3 client versions at a time (users don’t always run the latest)<br />Keep old ‘API’ around, build-out new API if (is_v2_or_later(key)) { do something } else {do some thing else}<br />This can get convoluted (see next page…)<br />
  27. 27. Supporting multiple clients…<br />
  28. 28. Supporting Multiple Clients…<br />Have different controllers handle different client versions#define SERVER @”https://foo.com/iphone1”#define SERVER @”https://foo.com/iphone2”<br />Make sure to avoid code duplication<br />Plan-B : End-of-life<br /> If ( ! is_supported_version(key)){send_msg(“please upgrade”);}<br />
  29. 29. Server side : keeping it secure<br />Make sure ‘secret stuff’ doesn’t get logged in log-files<br />In Rails : class Mobile::MobileController &lt; ApplicationControllerfilter_parameter_logging [:key, :uid]<br /> end<br />Output:<br />Processing IphoneController#get_memberships_and_discounts (for at 2009-07-02 16:07:41) [POST]<br /> Session ID: 126e5a73742f92f85c1158ea63fd960a<br /> Parameters: {&quot;loc&quot;=&gt;&quot;39.282440,-76.765693&quot;, &quot;action&quot;=&gt;&quot;get_memberships_and_discounts&quot;, &quot;uid&quot;=&gt;”[FILTERED]&quot;, &quot;controller&quot;=&gt;&quot;mobile/iphone&quot;, &quot;dist&quot;=&gt;&quot;25&quot;, &quot;mems&quot;=&gt;&quot;&quot;, &quot;key&quot;=&gt;&quot;[FILTERED]&quot;}<br />
  30. 30. Server side : Metrics : Logs<br />Log every thing to database, don’t rely on logfiles<br />This gives you pretty good metrics on your app usage<br />On Rails, use around_filteraround_filter :log_access, :only =&gt; [:get_discounts, :get_memberships]<br />Thirdparty metrics : FLURRY, PinchMedia…<br />
  31. 31. Server side : logging in Rails<br />def log_access<br />start_time = Time.now<br />yield<br />end_time = Time.now<br /> elapsed = ((end_time - start_time)*1000.0).to_int<br /> begin # b/c we don’t want to error during logging<br />alog = MemberAccessLog.new<br />alog.client_type_id = client_type_id<br />alog.session = session.session_id<br /> ….<br />alog.save!<br />rescue<br /> end<br />End <br />
  32. 32. Logging & Scalability<br />If all your requests are READ-ONLY (from db) it is very easy to scale<br />Load balancer can route requests to any server<br />Database can be replicated easily<br />Write-bound apps are little tricky to scale<br />
  33. 33. Agenda<br />Connectivity<br />Data format<br />Secure Data transfer<br />UDIDs, Keys, analytics<br />Controlling app from server<br />
  34. 34. Controlling app behavior from Server<br />
  35. 35. Control …<br />Apps changes are not easy to ‘get out’<br />Approval process takes time<br />Users may not upgrade to latest version<br />Server changes are under your control and easy to deploy<br />So build in control-switches in the app, that can be directed from server<br />
  36. 36. Control…<br />One example: Choosing if you are going to show ads?<br />show_ads : {none | admob | tapjoy}<br />
  37. 37. Hosting<br />Shared hosting is fine, but others might swamp your DB, CPU ..etc <br />If you can, get a VPS (Virtual Private Server)<br />Plans start from $20 / month (SliceHost, Hosting-Rails ..etc)<br />You have full ROOT access to the server (install packages, run CRON jobs ..etc)<br />EC2 is great (for testing, scaling)<br />
  38. 38. Thanks!<br />Sujee Maniyam<br />s@sujee.net<br />http://sujee.net<br />http://DiscountsForMe.net<br />Questions?<br />