Bienvenue dans la partie III de la série Sharing Data With Gestures. Dans la partie II, nous avons créé notre processus de serveur intermédiaire dans Ruby on Rails. Ce processus serveur agira comme un canal entre deux périphériques qui tentent de communiquer avec un geste que nous appelons un "bruit sourd". Lorsque deux appareils sont «assommés», le serveur les compare en calculant leur proximité les uns aux autres à l'aide de coordonnées GPS, ainsi que d'un horodatage quasi identique du moment où ils ont ouvert la communication avec le serveur. Une fois cette correspondance établie, le serveur échangera les messages saisis dans l'application mobile, en simulant la communication entre appareils..
Dans la troisième partie, nous allons déployer notre application serveur sur la plate-forme heroku, puis mettre à niveau notre application mobile pour communiquer avec celle-ci..
Pour commencer, nous allons modifier notre fichier de migration de la table thumps pour qu'il soit compatible avec Postgres. Vous pouvez trouver ce fichier dans le répertoire "db / migrate" et il s'appellera ainsi: TIMESTAMP_create_thumps.rb. Le moyen le plus simple de déployer une application heroku consiste à utiliser leur service de base de données partagée, qui se trouve être Postgres au lieu de MySQL. Nous allons remplacer les lignes suivantes:
t.decimal: lat,: precision => 8,: scale => 8 t.decimal: lng,: precision => 8,: scale => 8
avec ces nouvelles lignes:
t.decimal: lat,: scale => 8 t.decimal: lng,: scale => 8
Postgres ne gère pas les gros champs décimaux différemment de MySQL. Il s'agit donc d'un changement nécessaire pour obtenir la précision en points de données dont nous avons besoin dans nos champs de latitude et de longitude..
S'agissant d'une application Rails 2.3.5, nous utiliserons l'ancienne méthode d'installation de gems par heroku en créant un fichier .gems à la racine de notre projet Rails. La plupart d'entre vous seront probablement habitués à utiliser Bundler pour ce type de tâche. Cependant, comme le plugin geokit n'a pas été mis à niveau pour être compatible avec Rails 3.0, nous devons utiliser les anciennes conventions de Rails 2..
Nous ajoutons simplement les éléments suivants à notre fichier .gems:
rails -v 2.3.5 pg geokit --version '= 1.5.0'
Ici, nous spécifions les rails gem et la version que nous utilisons pour ce projet, ainsi que le gem postgres et la version 1.5.0 du geokit gem.
Nous pouvons maintenant commencer notre déploiement! Commençons par créer un référentiel git local dans notre projet. Tout ce que nous avons à faire est d’exécuter la commande suivante dans le répertoire racine de notre projet Rails:
$ git init
Avant de nous engager dans ce référentiel, nous devons créer notre application sur la plateforme heroku. Si vous n'avez pas encore créé de compte heroku gratuit, il suffit de vous inscrire à l'adresse https://api.heroku.com/signup. Si la gemme heroku n'est pas encore installée sur votre système, vous pouvez le faire en exécutant la commande suivante:
$ sudo gem installer heroku
Une fois la gem installée, exécutez la commande suivante à partir du répertoire racine du projet:
$ heroku crée - pile bamboo-ree-1.8.7
Nous spécifions ici la pile bamboom-ree en raison de l’application de Rails 2. Dans le cas où vous venez de créer un nouveau compte, il se peut que vous demandiez vos identifiants de compte heroku. Une fois entrées, ces informations d'identification seront stockées pour de futures interactions avec les serveurs heroku. Si tout se passe bien, heroku devrait réagir avec les éléments suivants:
Créé http://APPNAME.heroku.com/ | [email protected]: APPNAME.git Heroku distant Git ajouté
Ici, j'ai remplacé le nom de l'application et le sous-domaine réels par un espace réservé appelé APPNAME. Prenez note de cet APPNAME car nous l'utiliserons plus tard. Nous allons maintenant enregistrer nos fichiers de projet dans le référentiel git local créé précédemment. C'est aussi simple que d'exécuter ces deux commandes:
$ git add. $ git commit -m "mon premier commit"
Une fois que le projet a été entièrement associé au référentiel git local, nous devons le transférer dans le référentiel distant créé lors de l'exécution de la commande heroku create..
$ git push maître heroku
La gemme heroku vous permet d'exécuter des commandes de rake à distance sur le serveur avec la commande "heroku rake". Pour terminer le déploiement, nous devons exécuter nos migrations de base de données qui généreront notre table thumps dans la base de données heroku..
$ heroku rake db: migrer
Félicitations! Vous avez déployé avec succès notre application de serveur thump sur la plate-forme heroku. Revenons maintenant à l'application mobile!
Ouvrons notre fichier main.lua dans notre application Corona et ajoutons les lignes suivantes en haut:
http = require ("socket.http") ltn12 = require ("ltn12") url = require ("socket.url") require ("Json")
Nous avons besoin de certaines bibliothèques qui nous permettront de créer une connexion socket à notre application serveur. Nous allons également inclure la bibliothèque d’analyse JSON afin de comprendre les objets de réponse que le serveur renverra..
Rappelez-vous le APPNAME qui a été donné lorsque nous avons créé l'application Heroku? Il est temps de l'utiliser maintenant:
appname local = "APPNAMEHERE"
Cette variable sera combinée ultérieurement avec d'autres pour générer l'URL de notre serveur pour les communications externes..
Dans la partie I, l'application affichait une boîte d'alerte avec notre message lorsqu'elle détectait un "bruit sourd" ou un geste secoué. Comme nous devons communiquer ce message au serveur, nous allons supprimer la ligne suivante de notre fonction getThump:
alerte locale = native.showAlert ("Thump!", "Emplacement:"? latitudeText? ","? longitudeText? "\ r \ nMessage:"? textField.text, "OK")
Nous allons maintenant ajouter des fonctionnalités à cette méthode getThump pour envoyer notre message au serveur. Décomposons ceci:
message local = textField.text local post = "thump [deviceid] ="? Reference de l'appareil? "& thump [lat] ="? latitudeText? "& thump [lng] ="? longitudeText? "& thump [message] ="? message local response =
Ici, nous générons nos variables à envoyer au serveur. La variable "post" est configurée dans le format de la chaîne de requête et notre "réponse" est déclarée comme objet de table vide pour l'instant..
local r, c, h = http.request url = "http: //"? nom de l'application? ".heroku.com / thumps", method = "POST", en-têtes = ["content-length"] = #post, ["Content-Type"] = "application / x-www-form-urlencoded", source = ltn12.source.string (post), sink = ltn12.sink.table (réponse) local jsonpost = Json.Decode (table.concat (réponse, "))
Ici, nous exécutons une requête HTTP de type POST sur notre serveur. Nous appelons notre variable appname comme sous-domaine de l'URL. Les en-têtes sont standard pour un appel postérieur typique. Dans le champ "content-length", la syntaxe lua consistant à mettre un # devant la variable affichera la longueur en caractères de cette chaîne. Puisque nous voulons stocker la réponse de notre serveur dans une variable appelée "réponse", notre dernière ligne décodera cette variable en tant qu’objet JSON et créera un objet de table lua afin que nous puissions accéder aux champs qu’elle contient..
En cas d'erreur de communication, nous devons avertir l'utilisateur que quelque chose ne va pas. Nous allons créer une méthode générique showError () pour afficher une boîte d'alerte à l'utilisateur si cela se produit:
fonction locale showError () local alert = native.showAlert ("Erreur!", "Réessayez s'il vous plait!", "OK") end
En raison du fait que Rails est mono-threadé par nature et depuis les comptes gratuits de heroku, vous ne pouvez exécuter qu'un seul processus de serveur; une fois que l'application mobile a terminé l'appel POST pour envoyer des données, nous allons interroger notre serveur, demandant un objet de réponse. Bien que ce ne soit peut-être pas le moyen idéal pour l'architecte, cela nous permet d'exécuter ce type d'application avec des ressources de serveur heroku très minimales.
Voici notre logique de sondage ci-dessous:
if (jsonpost.success == true), alors native.setActivityIndicator (true); tentatives locales = 0 function retrieveThump (événement) si 10 == tentatives, puis native.setActivityIndicator (false); timer.cancel (event.source) showError () else local response = local r, c, h = http.request url = "http: //"? nom de l'application? ".heroku.com / thumps / search? thump [deviceid] ="? Reference de l'appareil? "& thump [lat] ="? latitudeText? "& thump [lng] ="? longitudeText, method = "GET", sink = ltn12.sink.table (réponse) jsonget local = Json.Decode (table.concat (réponse, ")) if (jsonget.success == true) puis native.setActivityIndicator (false timer.cancel (event.source) alerte locale = native.showAlert ("Thump!", jsonget.message, "OK") end tentatives = tentatives + 1 timer.performWithDelay (3000, retrieveThump) fin timer. performWithDelay (1000, retrieveThump) else showError () end
Décomposons:
if (jsonpost.success == true), puis native.setActivityIndicator (true) ;? sinon showError () end
Dans le cas où notre variable "jsonpost" renvoie "success = true" du serveur, nous allons définir notre ActivityIndicator sur le périphérique sur true. Cela lance un composant de sucette natif qui signale à l'utilisateur que l'application travaille sur quelque chose. Si nous ne recevons pas le message "success = true" du serveur, nous appellerons notre fonction d'erreur générique et afficherons la boîte d'alerte d'erreur..
tentatives locales = 0 function retrieveThump (event)? end timer.performWithDelay (1000, retrieveThump)
Dans ce cas, nous définissons sur 0 une variable de tentatives en dehors du champ de notre fonction. Nous l'utiliserons plus tard pour limiter le nombre de requêtes que notre fonction d'interrogation "retrieveThump" peut effectuer. Corona a une classe de minuterie intégrée qui nous permet d’appeler une fonction sur un intervalle de temps. La fonction timer.performWithDelay prend plusieurs millisecondes et une fonction en tant que paramètres..
si 10 == tentatives, alors native.setActivityIndicator (false); timer.cancel (event.source) showError ()
Premièrement, nous vérifierons si nous avons exécuté cette fonction 10 fois. Si tel est le cas, nous allons arrêter notre ActivityIndicator en le définissant sur false, annuler notre fonction de minuterie, puis appeler notre fonction d'erreur pour avertir l'utilisateur que quelque chose s'est mal passé..
sinon réponse locale = local r, c, h = http.request url = "http: //"? nom de l'application? ".heroku.com / thumps / search? thump [deviceid] ="? Reference de l'appareil? "& thump [lat] ="? latitudeText? "& thump [lng] ="? longitudeText, method = "GET", sink = ltn12.sink.table (réponse) jsonget local = Json.Decode (table.concat (réponse, ")) if (jsonget.success == true) puis native.setActivityIndicator (false timer.cancel (event.source) alerte locale = native.showAlert ("Thump!", jsonget.message, "OK") end tentatives = tentatives + 1 timer.performWithDelay (3000, retrieveThump) fin
Si nous n'avons pas encore atteint 10 tentatives, nous allons exécuter une requête HTTP sur notre serveur afin de rechercher notre "thump" correspondant. La fonction ressemble à l'appel POST que nous avons fait précédemment, mais nous passons la méthode GET dans ce cas car nous essayons de lire et non d'écrire sur le serveur..
Si vous vous rappelez de la partie II, nous avons créé une action de recherche dans notre serveur Rails qui permet de rechercher dans notre base de données un bruit correspondant, basé sur nos coordonnées GPS et un horodatage similaire. Nous transmettons cette information au serveur via la chaîne de requête dans l'URL. Comme pour l'appel POST, nous analysons le retour du serveur en tant qu'objet JSON et nous le stockons dans une variable de table locale appelée "jsonget". Si nous recevons un succès = vrai du serveur, nous allons arrêter notre ActivityIndicator, arrêter notre exécution du minuteur et afficher notre message dans une boîte d’alerte. Si ce processus échoue, nous interrogerons simplement le serveur de la même manière pour un maximum de 10 tentatives..
Et voila! Ce tutoriel devrait vous donner une bonne base pour créer différents types d'applications qui partagent des données via des gestes. Certains ajouts intéressants peuvent être de partager via un tapotement d'écran simultané, ou d'étendre l'application pour échanger des images prises à partir de l'appareil photo ou de la bibliothèque de photos locale de l'appareil. Heureux battement!