REST rajapintana mobiilikehityksessä Django & WP7 Jonne Räsänen 2011 jonne.rasanen@jyu.fi
Case iscope Hälytyspalvelu Web-palvelu Mobiilisovellus
REST (REpresentational State Transfer) Aikojakin vanhempi (1994-95) HTTP-pohjainen arkkitehtuurityyli GET, POST, PUT, DELETE
REST Hyvät puolet Yksinkertaisuus Laajasti käytössä Selkeä rakenne URI-osoitteilla
REST Rajoitteet Client-server -eriytys Tilattomuus Välimuisti Hierarkinen järjestelmä Yhtenäinen rajapinta Code on demand (valinnainen)
Django Python-pohjainen www-framework MVT-arkkitehtuuri Skaalautuva Hyvä yhteisötuki Poneja
Django-piston http://djangopackages.com/grids/g/api/ Yhä suosituimpia REST-plugineja Tuki usealle formaatille (JSON, XML..) Muokattavissa omiin tarpeisiin Kaamea ylläpito https://bitbucket.org/jespern/django-piston/wiki/home
Windows Phone 7 SilverLight-pohjainen mobiilialusta MMVM-arkkitehtuuri Avoimen yhteisön tuki http://codeplex.com
RestSharp Käytetyin REST-API.Net-ympäristössä WP7-tuki Helppokäyttöisehkö Dokumentaatio <= 0
Django models.py class Location(models.Model): user = models.foreignkey(user, null=true) lat = models.floatfield(default=0) lon = models.floatfield(default=0) time = models.datetimefield(default=datetime.datetime.now()) speed = models.floatfield(default=0) alt = models.floatfield(default=0) bearing = models.floatfield(default=0) provider = models.charfield(max_length=255, blank=true) accuracy = models.floatfield(default=0)
Django-piston handlers.py class LocationHandler(BaseHandler): # Handles user location methods_allowed = ('GET', 'PUT',) model = Location fields = ('lat', 'lon', 'time', 'bearing', 'provider', 'time', 'alt', 'speed', 'accuracy') def read(self, request): # Gets user location user = request.user return user.location def update(self, request): # Updates user location user = request.user profile = user.profile if not user.profile.allow_location_usage: # User does not allow profile updating resp = rc.bad_request resp.write(": Please enable location usage" +"to use this service.") return resp data = request.data if user.profile.allow_location_history: # Save location as a new instance # if history allowed loc = Location() loc.user = user else: loc = user.location # Add data to object loc.lat = float(data['lat']) loc.lon = float(data['lon']) loc.speed = float(data['speed']) loc.alt = float(data['alt']) loc.bearing = float(data['bearing']) loc.provider = data['provider'] loc.accuracy = float(data['accuracy']) loc.time = datetime.datetime.now() loc.save() profile.last_location = loc profile.save() UpdateLocationTask.delay(user) resp = rc.all_ok resp.write(": Location updated") return resp
Django-piston urls.py auth = HttpBasicAuthentication() # For testing purposes location_handler = Resource(handler=LocationHandler, authentication=auth) urlpatterns = patterns('', url(r'^location$', location_handler), # Get/update location )
WP7 Location.cs public class GeoLocation { public double lat { get; set; } public double lon { get; set; } public double accuracy { get; set; } public double alt { get; set; } public double speed { get; set; } public double bearing { get; set; } public string provider { get; set; } }
WP7 MainPage.xaml.cs location = new GeoLocation(); watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High); // Use high accuracy. watcher.movementthreshold = 20; // Use MovementThreshold to ignore noise in the signal. watcher.statuschanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged); watcher.start(); void watcher_statuschanged(object sender, GeoPositionStatusChangedEventArgs e) { if (e.status == GeoPositionStatus.Ready) { // Use the Position property of the GeoCoordinateWatcher object to get the current location. GeoCoordinate co = watcher.position.location; location.lat = co.latitude; location.lon = co.longitude; location.accuracy = co.horizontalaccuracy; location.provider = "provider"; location.alt = co.altitude; // Stop the Location Service to conserve battery power. watcher.stop(); } } update_location();
WP7 MainPage.xaml.cs private void update_location() { settings.trygetvalue<networkcredential>("credentials", out credentials); // Get credentials from storage RestRequest request = new RestRequest("location", Method.PUT); request.credentials = credentials; request.requestformat = DataFormat.Json; request.addbody(location); client.executeasync<geolocation>(request, (response) => { if (response.statuscode == HttpStatusCode.OK) { // Everything went fine locationupdated = true; } else { // Something went wrong MessageBox.Show(response.Content); } }); }
Kysyttävää? Django: https://www.djangoproject.com Django-piston: https://bitbucket.org/jespern/django-piston/wiki/home RestSharp: http://restsharp.org iscope: http://iscope.it.jyu.fi RESTin faktojen tarkistelua: www.niksula.hut.fi/~hpelkone/main.pdf bit.ly/restisgood