Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Iphone client-server app with Rails backend (v3)


Published on

Some of the lessons learned from building a client-server iphone app (DiscountsForMe)

This is version 3 of the talk, presented at SF Ruby Meetup on Feb 17, 2010

Published in: Technology, News & Politics
  • updated presentations :
    Are you sure you want to  Yes  No
    Your message goes here
  • sujee, great presentation. tons of great tips.

    I am about to start writing my first iPhone/Rails app today.

    btw, you might want to check out Apigee ( for the server side analytics. It’s free and is super easy to set up. I am using it on my Rails APIs already.
    Are you sure you want to  Yes  No
    Your message goes here
  • From the presenter:

    Some of the comments I received during the talk:

    1) 'BluePill' was mentioned for monitoring

    2) If you are just building a mobile backend and don't need the web app, you might consider Sinatra or some thing similar.

    3) how to divide processing between client / server:
    off load as much processing to client/phone. This way your server doesn't become bogged when your app takes off.

    4) I mentioned logging vital stats (time taken to server requests ..etc) so you can easily spot trends.
    Also consider Hyperic for gathering stats. It has nice history / graphing features

    5) I use APache + Phusion for my site.
    Nginx is considered a better choice for 'slow clients' like mobile apps. It keeps a low memory profile, so you'll get more connections out of a server.
    Are you sure you want to  Yes  No
    Your message goes here
  • This is version 3 of the talk, presented at SF Ruby Meetup on Feb 17, 2010
    Are you sure you want to  Yes  No
    Your message goes here

Iphone client-server app with Rails backend (v3)

  1. 1. Lessons from developing anIphone App + Server backend<br />Sujee Maniyam<br /><br /><br /><br />Feb 2010<br />
  2. 2. Quiz<br />PRIZE!<br />Where was this picture taken?<br />
  3. 3.
  4. 4. My Background<br />Developer (enterprise, web)<br />Java / Php / Ruby / obj-C<br />First iphone app (Apr 2009)<br />
  5. 5. Target Audience<br />Iphone app developers<br />Server backend developers for mobile apps<br />Expert level: Beginner - Intermediate<br />
  6. 6. Why Client-Server Apps?<br />Some apps run fine on the device disconnected (Tips calculator)<br />“I think” majority of SMART apps in the future will have a server backend<br />Some cool apps<br />Amazon<br />Yelp<br />Red Laser<br />Countless games<br />
  7. 7. Server Backend gives you…<br />A community (games, social interactions)<br />Push Notification<br />Heavy computational lifting (image recognition)<br />Up-to date data (bar code scanners)<br />‘collective intelligence’ (most popular item today is…)<br />
  8. 8. My App: DiscountsForMe<br />Shows member benefits<br />Based on location<br />V2.0 in app store<br />Memberships:<br />Public radio (KQED, WHYY)<br />Bank of America card<br />AARP<br />More…<br />
  9. 9. Architecture<br />Server ( serves data<br />Server is Rails app<br />Iphone app talks to the server<br /><Insert usual SERVER ---- INTERNET CLOUD ---- IPHONEpicture here><br />
  10. 10. Web App / Mobile App ?<br />What should server side code support?<br />Are you adding mobile support for an existing web-app?<br />Just mobile platform? (simpler ??)<br />Hybrid (web + mobile)  more work<br />DiscountsForMe is a hybrid app<br />
  11. 11. 1) Connectivity : Simple Start<br />First cut : App made three server calls at startup<br />ping()<br />Get_X()<br />Get_Y()<br />Simulator <br />Iphone over Wi-fi<br />Iphone over 3G <br />LAG-TIME is a problem<br />
  12. 12. Connectivity : Minimize Lag Time<br />Noticeable lag time over 3G/Edge<br />Reducing lag time<br />Show cached data<br />Download in background<br />Condense network calls (especially if the user is waiting for data)<br />So, condensed call becomes<br />Get_X()<br />Get_Y()<br />get_X_Y()<br />
  13. 13. 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 />
  14. 14. Network setup – WIFI<br />Home networkover WIFI<br />Run local serveron laptop<br />Iphone + Simulatorcan connect just fine<br />
  15. 15. Setup for 3G<br />
  16. 16. Network Setup for 3G<br />Need a public IP<br />Use a hosted server<br />Or use your cable modem public-IP and have your router do port-forwarding<br />DYNDNS :<br />
  17. 17. 2) Talking to Server : Format<br />Choices : XML, JSON, other (csv, binary – protobuf/thift)<br />JSON smaller size than XML (50% less)<br />Json : use TouchJSON library<br />JSON String  Touch JsonNSDictionary (yay!)<br />XML : NSXML(sdk) / TouchXML / KissXML<br />Rails makes it real easy to send Json/xml<br />Some_obj.to_json<br />Some_obj.to_xml<br />
  18. 18. Keeping it small<br />Trim objects<br />No need to send all attributes<br />Active records have extra attributes (created_at, updated_at ..etc)<br />Example:<br /># specify attributes to serialize<br />obj.to_json(:only => [:name, :age])<br /># combine other <br />my_response = {}<br />my_response[:book_name] =<br />my_response[:author_name] =<br />render(:json => my_response.to_json())<br />- Compress (zip) response<br />
  19. 19. GET vs POST<br />iPhone SDK has a simple switch to control GET / POST<br />What is the difference in Rails?<br />Post requests have ‘authenticity token’ for cookie based sessions<br />Use DB based sessions or turn off authenticity-protection<br />
  20. 20. Agenda<br />Connectivity<br />Data format<br />Secure Data transfer<br />UDIDs, Keys, analytics<br />Controlling app from server<br />
  21. 21. 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 />Enter : HTTPS<br />
  22. 22. 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 properly<br />
  23. 23.
  24. 24. Verify SSL Cert…<br />
  25. 25. Break & Quiz<br />
  26. 26. Agenda<br />Connectivity<br />Data format<br />Secure Data transfer<br />UDIDs, Keys, multiple versions, analytics<br />Controlling app from server<br />
  27. 27. What do I send to the server?<br />Think about including<br />UDID (device id)<br />And a Key (compiled within the app)<br /><br />Why?<br />
  28. 28. Unique Device ID (UDID)<br />Each iphone has a unique ID, etched in hardware (just like MAC address)<br />Your app can send UDID with each request<br />Uses<br />metrics on app usage<br />Easy account creation (no signup)<br />
  29. 29. Identify a User (Device)<br />UDID can help you ‘auto –create’ accounts on server<br />Eg. High scores of games<br />Allow users to create a custom user name later<br />Beware of a user using multiple devices (multiple UDIDs)<br />
  30. 30. Metrics<br />Client Side metrics<br />Server side metrics<br />
  31. 31. Client Side Metrics<br />Code embedded in your iphone app<br />Usage, Users (new, repeat), session length<br />Few companies (Flurry, Pinch Media ..etc)<br />Pretty easy to integrate<br />Nice dashboards<br />Free! (mostly)<br />
  32. 32. Metrics : Client Side<br />
  33. 33. Server Side Metrics<br />why?<br />Some things are easily measured on server side<br />‘collective intelligence’<br />Popular discounts<br />Security audits<br />Isolating an IP-address doing too many requests / scraping<br />Easy to extract data / graphs ..etc<br />Needs a bit of work on your side<br />
  34. 34. Sample Server Side log data<br />Device_id : iphone, android, web, <br />Location<br />Ip_address<br />Response_time<br />Response_data_size<br />Client_key<br />Created_at<br />Updated_at<br />
  35. 35. Server Side Metric : Time To Serve <br />Want to measure the time spent on each request<br />use around_filter in Controllerclass MyControlleraround_filter :log_access, :only => [:get_A]<br />
  36. 36. Response Time …<br />def log_access<br />start_time =<br />yield<br />end_time =<br />elapsed = ((end_time - start_time)*1000.0).to_int<br />End <br />
  37. 37. Server side Metric 2) Response Size<br />def log_access<br />start_time =<br />yield<br />end_time =<br />elapsed = ((end_time - start_time)*1000.0).to_int<br />response_data_size = response.body.length<br />End <br />
  38. 38. Response Time Chart<br />Time (ms)<br />
  39. 39. Response Size Chart<br />Response size (kbytes)<br />
  40. 40. Access keys<br />Keys are random, ‘sekret’ strings compiled into the iphone app<br />Sample key = “iphone_v1.0_xklajdfoi2” (human readable + ‘hard to guess’)<br />Start using ‘access keys’ from day-1<br />Each request to server must have a valid key<br />Uses<br />Easy to control client access (Prevent scraping, DOS ..etc)<br />Monitoring (what versions are being used)<br />Support multiple versions, easy upgrade<br />
  41. 41. Access Keys<br />In controller:<br /> @@keys = [ "iphone_v0.0_foobar” , <br /> "iphone_v1.0_afajiu” ,<br /> "iphone_v2.0_fi98d”,<br /> "iphone_v2.0_plus_fsafa” ,<br /> "android_v1.0_fasjlkuo”<br /> ]<br />@@keys_premium = ["iphone_v2.0_plus_fsfa"]<br />
  42. 42. 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 />
  43. 43. Supporting multiple clients…<br />
  44. 44. Supporting Multiple Clients…<br />Have different controllers handle different client versions#define SERVER @””#define SERVER @””<br />Make sure to avoid code duplication<br />Plan-B : End-of-life<br /> If ( ! is_supported_version(key)){send_msg(“please upgrade”);}<br />
  45. 45. Server side : keeping it secure<br />Make sure ‘secret stuff’ doesn’t get logged in log-files<br />In Rails : class Mobile::MobileController < 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: {"loc"=>"39.282440,-76.765693", "action"=>"get_memberships_and_discounts", "uid"=>”[FILTERED]", "controller"=>"mobile/iphone", "dist"=>"25", "mems"=>"", "key"=>"[FILTERED]"}<br />
  46. 46. Example : Controllers<br />MobileController<br />IPhoneController < MobileController<br />AndroidController < MobileController<br />Most of the shared logic in ‘MobileController’<br />Sample iPhone controllerClass IphoneController < MobileController def client_type_id 3 end end<br />
  47. 47. Example …<br />Class MobileController<br /> @@valid_keys = [……]<br /> def ping<br />to_ret = {}<br /> begin<br /> validate<br />to_ret[:status] = “OK”<br /> rescue<br />to_ret[:error] = $1.message<br /> end<br /> render (:json => to_ret.to_json)<br /> end<br />end<br />
  48. 48. Example …<br />Def validate<br /> #verify the key<br /> if (params[:key].blank?)<br /> raise DiscountsError, "dude, where is my key?"<br /> end<br /> if (params[:uid].blank?)<br /> raise DiscountsError, "dude, who are you?"<br /> end<br /> unless (@@valid_keys .has_key?(params[:key]))<br /> raise DiscountsError, "un supported version, please upgrade"<br /> end <br /> end<br />end<br />
  49. 49. Controlling app behavior from Server<br />
  50. 50. 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 />
  51. 51. Control…<br />One example: should display ads?<br />show_ads : {none | admob | tapjoy}<br />Alert Messages:<br />“try our new version that has cool feature XYZ”<br />
  52. 52. Server Logistics<br />Choosing a hosting plan<br />Deploy<br />monitoring<br />
  53. 53. 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 also (for testing, scaling)<br />
  54. 54. Server : When to get it<br />Don’t wait till TESTING phase!<br />Get it from DAY-1, WEEK-1<br />Can use DNS services like DYNDNS to test on your own workstation, during development<br />Work on easy deploy scripts<br />Capistrano<br />Or rsync<br />
  55. 55. Monitoring<br />So you know when your server is down<br />Pingdom / CloudKick<br />
  56. 56. Other Resources<br /> RaminFiroozye<br />Restful web services<br />
  57. 57. Thanks!<br />Sujee Maniyam<br /><br /><br /><br />Questions?<br />