Lessons from developing an Iphone App + Server backend

Download Report

Transcript Lessons from developing an Iphone App + Server backend

Lessons from developing an
Iphone App + Server backend
Sujee Maniyam
[email protected]
http://sujee.net
http://DiscountsForMe.net
Feb 2010
Quiz
• PRIZE!
• Where was this picture taken?
My Background
• Developer (enterprise, web)
• Java / Php / Ruby / obj-C
• First iphone app (Apr 2009)
Target Audience
• Iphone app developers
• Server backend developers
for mobile apps
• Expert level:
Beginner - Intermediate
Why Client-Server Apps?
• Some apps run fine on the device
disconnected (Tips calculator)
• “I think” majority of SMART apps in the future
will have a server backend
• Some cool apps
– Amazon
– Yelp
– Red Laser
– Countless games
Server Backend gives you…
• A community (games, social interactions)
• Push Notification
• Heavy computational lifting (image
recognition)
• Up-to date data (bar code scanners)
• ‘collective intelligence’ (most popular item
today is…)
My App: DiscountsForMe
•
•
•
•
Shows member benefits
Based on location
V2.0 in app store
Memberships:
– Public radio (KQED, WHYY)
– Bank of America card
– AARP
– More…
Architecture
•
•
•
•
Server (DiscountsForMe.net) serves data
Server is Rails app
Iphone app talks to the server
<Insert usual
SERVER ---- INTERNET CLOUD ---- IPHONE
picture here>
Web App / Mobile App ?
• What should server side code support?
• Are you adding mobile support for an existing
web-app?
• Just mobile platform? (simpler ??)
• Hybrid (web + mobile)  more work
– DiscountsForMe is a hybrid app
1) Connectivity : Simple Start
• First cut : App made three server calls at
startup
– ping()
– Get_X()
– Get_Y()
•
•
•
•
Simulator
Iphone over Wi-fi
Iphone over 3G
LAG-TIME is a problem
Connectivity : Minimize Lag Time
• Noticeable lag time over 3G/Edge
• Reducing lag time
– Show cached data
– Download in background
– Condense network calls (especially if the user is
waiting for data)
• So, condensed call becomes
– Get_X()
– Get_Y()
get_X_Y()
Iphone Connectivity
• BIG LESSON 1 :
– Test on IPHONE (not just simulator)
– Test with WiFi OFF! (3G can be slow to connect, EDGE
even worse)
– You may need to reorganize the logic to improve
response time (I had to)
• LESSON 2
– Test in AirPlane Mode (all RADIOS off)
(a frequent reason network apps are rejected )
Network setup – WIFI
• Home network
over WIFI
• Run local server
on laptop
• Iphone + Simulator
can connect just fine
Setup for 3G
Network Setup for 3G
• Need a public IP
• Use a hosted server
• Or use your cable modem public-IP and have
your router do port-forwarding
• DYNDNS : http://www.dyndns.com/
2) Talking to Server : Format
• Choices : XML, JSON, other (csv, binary – protobuf/thift)
XML
smaller size than
(50% less)
• Json : use TouchJSON library
•
JSON
http://code.google.com/p/touchcode/wiki/TouchJSON
• JSON String  Touch Json  NSDictionary (yay!)
• XML : NSXML(sdk) / TouchXML / KissXML
http://www.71squared.co.uk/2009/05/processing-xml-on-theiphone/
• Rails makes it real easy to send Json/xml
– Some_obj.to_json
– Some_obj.to_xml
Keeping it small
• Trim objects
– No need to send all attributes
– Active records have extra attributes (created_at, updated_at
..etc)
• Example:
# specify attributes to serialize
obj.to_json(:only => [:name, :age])
# combine other
my_response = {}
my_response[:book_name] = book.name
my_response[:author_name] = book.author.name
render(:json => my_response.to_json())
- Compress (zip) response
GET vs POST
• iPhone SDK has a simple switch to control GET
/ POST
• What is the difference in Rails?
– Post requests have ‘authenticity token’ for cookie
based sessions
– Use DB based sessions or turn off authenticityprotection
Agenda
•
•
•
•
•
Connectivity
Data format
 Secure Data transfer
UDIDs, Keys, analytics
Controlling app from server
Secure Data Transfer
• Plain HTTP is fine most of the time
• If you want to secure data
– Symmetric key encryption (shared ‘seckr3t’ key on
Iphone app and server)
– Public-private key encryption (e.g. SSH) : private
key on server, public key on iphone
– Enter : HTTPS
Secure data transfer : httpS
• SSL is ‘good enough’ for most of us
• Get a proper SSL certificate ($30). Self-signed
certs don’t work by default
• Beware connection time is a little longer for
httpS
• Verify your ssl certificate is installed properly
http://www.digicert.com/help/
Verify SSL Cert…
Break & Quiz
Agenda
•
•
•
•
•
Connectivity
Data format
Secure Data transfer
 UDIDs, Keys, multiple versions, analytics
Controlling app from server
What do I send to the server?
• Think about including
– UDID (device id)
– And a Key (compiled within the app)
• http://example.com/iphone/foo?udid=xxxx&k
ey=yyyy
• Why?
Unique Device ID (UDID)
• Each iphone has a unique ID, etched in
hardware (just like MAC address)
• Your app can send UDID with each request
• Uses
– metrics on app usage
– Easy account creation (no signup)
Identify a User (Device)
• UDID can help you ‘auto –create’ accounts on
server
– Eg. High scores of games
• Allow users to create a custom user name
later
• Beware of a user using multiple devices
(multiple UDIDs)
Metrics
• Client Side metrics
• Server side metrics
Client Side Metrics
– Code embedded in your iphone app
– Usage, Users (new, repeat), session length
– Few companies (Flurry, Pinch Media ..etc)
– Pretty easy to integrate
– Nice dashboards
– Free! (mostly)
Metrics : Client Side
Server Side Metrics
– why?
– Some things are easily measured on server side
– ‘collective intelligence’
• Popular discounts
– Security audits
• Isolating an IP-address doing too many requests /
scraping
– Easy to extract data / graphs ..etc
– Needs a bit of work on your side
Sample Server Side log data
•
•
•
•
•
•
•
•
Device_id : iphone, android, web,
Location
Ip_address
Response_time
Response_data_size
Client_key
Created_at
Updated_at
Server Side Metric : Time To Serve
• Want to measure the time spent on each
request
• use around_filter in Controller
class MyController
around_filter :log_access, :only =>
[:get_A]
Response Time …
def log_access
start_time = Time.now
yield
end_time = Time.now
elapsed = ((end_time - start_time)*1000.0).to_int
End
Server side Metric 2) Response Size
def log_access
start_time = Time.now
yield
end_time = Time.now
elapsed = ((end_time - start_time)*1000.0).to_int
response_data_size = response.body.length
End
Response Time Chart
Time (ms)
Response Size Chart
• Response size (kbytes)
Access keys
• Keys are random, ‘sekret’ strings compiled into
the iphone app
• Sample key = “iphone_v1.0_xklajdfoi2” (human
readable + ‘hard to guess’)
• Start using ‘access keys’ from day-1
• Each request to server must have a valid key
• Uses
– Easy to control client access (Prevent scraping, DOS
..etc)
– Monitoring (what versions are being used)
– Support multiple versions, easy upgrade
Access Keys
In controller:
@@keys = [ "iphone_v0.0_foobar” ,
"iphone_v1.0_afajiu” ,
"iphone_v2.0_fi98d”,
"iphone_v2.0_plus_fsafa” ,
"android_v1.0_fasjlkuo”
]
@@keys_premium = ["iphone_v2.0_plus_fsfa"]
Supporting multiple versions
• May be supporting 2-3 client versions at a
time (users don’t always run the latest)
• Keep old ‘API’ around, build-out new API
if (is_v2_or_later(key))
{ do something }
else
{do some thing else}
• This can get convoluted (see next page…)
Supporting multiple clients…
Supporting Multiple Clients…
• Have different controllers handle different client
versions
#define SERVER @”https://foo.com/iphone1”
#define SERVER @”https://foo.com/iphone2”
• Make sure to avoid code duplication
• Plan-B : End-of-life
If ( ! is_supported_version(key))
{
send_msg(“please upgrade”);
}
Server side : keeping it secure
• Make sure ‘secret stuff’ doesn’t get logged in log-files
• In Rails :
class Mobile::MobileController < ApplicationController
filter_parameter_logging [:key, :uid]
end
• Output:
Processing IphoneController#get_memberships_and_discounts (for
166.137.132.167 at 2009-07-02 16:07:41) [POST]
Session ID: 126e5a73742f92f85c1158ea63fd960a
Parameters: {"loc"=>"39.282440,-76.765693",
"action"=>"get_memberships_and_discounts",
"uid"=>”[FILTERED]", "controller"=>"mobile/iphone", "dist"=>"25",
"mems"=>"", "key"=>"[FILTERED]"}
Example : Controllers
• MobileController
– IPhoneController < MobileController
– AndroidController < MobileController
• Most of the shared logic in ‘MobileController’
• Sample iPhone controller
Class IphoneController < MobileController
def client_type_id
3
end
end
Example …
Class MobileController
@@valid_keys = [……]
def ping
to_ret = {}
begin
validate
to_ret[:status] = “OK”
rescue
to_ret[:error] = $1.message
end
render (:json => to_ret.to_json)
end
end
Example …
Def validate
#verify the key
if (params[:key].blank?)
raise DiscountsError, "dude, where is my key?"
end
if (params[:uid].blank?)
raise DiscountsError, "dude, who are you?"
end
unless (@@valid_keys .has_key?(params[:key]))
raise DiscountsError, "un supported version, please upgrade"
end
end
end
Controlling app behavior from Server
Control …
• Apps changes are not easy to ‘get out’
– Approval process takes time
– Users may not upgrade to latest version
• Server changes are under your control and
easy to deploy
• So build in control-switches in the app, that
can be directed from server
Control…
• One example: should display ads?
– show_ads : {none | admob | tapjoy}
• Alert Messages:
– “try our new version that has cool feature XYZ”
Server Logistics
• Choosing a hosting plan
• Deploy
• monitoring
Hosting
• Shared hosting is fine, but others might
swamp your DB, CPU ..etc
• If you can, get a VPS (Virtual Private Server)
– Plans start from $20 / month (SliceHost, HostingRails ..etc)
– You have full ROOT access to the server (install
packages, run CRON jobs ..etc)
• EC2 is great also (for testing, scaling)
Server : When to get it
• Don’t wait till TESTING phase!
• Get it from DAY-1, WEEK-1
• Can use DNS services like DYNDNS to test on
your own workstation, during development
• Work on easy deploy scripts
– Capistrano
– Or rsync 
Monitoring
• So you know when your server is down
• Pingdom / CloudKick
Other Resources
• http://www.slideshare.net/raminf/iphonebackend-servers
by Ramin Firoozye
• Restful web services
Thanks!
• Sujee Maniyam
– [email protected]
– http://sujee.net
• http://DiscountsForMe.net
• Questions?