Willkommen zu Teil III der Serie "Daten mit Gesten teilen". In Teil II haben wir unseren intermediären Serverprozess in Ruby on Rails erstellt. Dieser Serverprozess fungiert als Verbindungskanal zwischen zwei Geräten, die versuchen, mit einer Geste zu kommunizieren, die wir "Schlagen" nennen. Wenn zwei Geräte zusammen "schlagartig" sind, passt der Server zu ihnen, indem sie ihre Nähe zueinander durch GPS-Koordinaten sowie einen nahezu identischen Zeitstempel für den Zeitpunkt der Kommunikation mit dem Server berechnen. Sobald diese Übereinstimmung hergestellt wurde, tauscht der Server die in der mobilen App eingegebenen Nachrichten aus und simuliert die Kommunikation von Gerät zu Gerät.
In Teil III werden wir unsere Server-App auf der Heroku-Plattform bereitstellen und dann unsere mobile App aktualisieren, um mit ihr zu kommunizieren.
Zu Beginn ändern wir die Migrationsdatei für die Thumps-Tabelle, um mit Postgres kompatibel zu sein. Sie finden diese Datei im Verzeichnis "db / migrate" und heißen etwa TIMESTAMP_create_thumps.rb. Die einfachste Möglichkeit, eine Heroku-App bereitzustellen, ist die Verwendung ihres gemeinsam genutzten Datenbankdienstes, der Postgres anstelle von MySQL ist. Wir werden folgende Zeilen ersetzen:
t.decimal: lat,: precision => 8,: scale => 8 t.decimal: lng,: precision => 8,: scale => 8
mit diesen neuen Zeilen:
t.decimal: lat,: scale => 8 t.decimal: lng,: scale => 8
Postgres behandelt große Dezimalfelder anders als MySQL. Dies ist eine notwendige Änderung, um sicherzustellen, dass wir die Datenpunktgenauigkeit erhalten, die wir in unseren Breiten- und Längenfeldern benötigen.
Da dies eine Rails 2.3.5-App ist, werden wir die ältere Heroku-Methode zum Installieren von Gems verwenden, indem Sie eine .gems-Datei im Stammverzeichnis unseres Rails-Projekts erstellen. Die meisten von Ihnen werden wahrscheinlich an die Verwendung von Bundler für diese Art von Aufgabe gewöhnt sein. Da das Geokit-Plugin jedoch nicht auf Rails 3.0-kompatibel aktualisiert wurde, müssen wir die älteren Rails 2-Konventionen anwenden.
Wir fügen einfach folgendes zu unserer .gems-Datei hinzu:
Schienen -v 2.3.5 pg Geokit --version '= 1.5.0'
Hier geben wir den Schienenstein und die Version an, die wir für dieses Projekt verwenden, sowie den Postgres-Stein und die Version 1.5.0 des Geokit-Edelsteins.
Jetzt können wir mit der Bereitstellung beginnen! Beginnen wir mit der Erstellung eines lokalen Git-Repositorys in unserem Projekt. Wir müssen lediglich den folgenden Befehl im Stammverzeichnis des Rails-Projekts ausführen:
$ git init
Bevor wir uns auf dieses Repository festlegen, müssen wir unsere App auf der Heroku-Plattform erstellen. Wenn Sie sich noch nicht für ein kostenloses Heroku-Konto angemeldet haben, melden Sie sich einfach unter https://api.heroku.com/signup an. Wenn Sie den Heroku-Edelstein noch nicht auf Ihrem System installiert haben, führen Sie den folgenden Befehl aus:
$ sudo gem install heroku
Sobald der Edelstein installiert ist, führen Sie den folgenden Befehl im Stammverzeichnis des Projekts aus:
$ heroku create --stack bamboo-ree-1.8.7
Hier geben wir den Bamboom-Ree-Stack an, da es sich hierbei um eine Rails 2-App handelt. Falls Sie gerade ein neues Konto erstellt haben, werden Sie möglicherweise aufgefordert, Ihre Anmeldeinformationen für Ihr Heroku-Konto einzugeben. Nach der Eingabe werden diese Anmeldeinformationen für zukünftige Interaktionen mit den Heroku-Servern gespeichert. Wenn alles gut geht, sollte Heroku folgendermaßen reagieren:
Erstellt http://APPNAME.heroku.com/ | [email protected]: APPNAME.git Git Remote Heroku hinzugefügt
Hier habe ich den tatsächlichen Anwendungsnamen und die Subdomain durch einen Platzhalter namens APPNAME ersetzt. Notieren Sie sich diesen APPNAME, da wir ihn später verwenden werden. Jetzt übergeben wir unsere Projektdateien an das lokale git-Repository, das wir zuvor erstellt haben. Es ist so einfach wie das Ausführen dieser zwei Befehle:
$ git add. $ git commit -m "mein erstes Commit"
Nachdem das Projekt vollständig für das lokale Git-Repo festgelegt wurde, müssen wir es in das Remote-Repository verschieben, das erstellt wurde, als wir den Befehl heroku create ausgeführt haben.
$ git Push Heroku-Meister
Mit dem Heroku-Edelstein können Sie Remote-Rake-Befehle mit dem Befehl "Heroku-Rake" auf dem Server ausführen. Um die Bereitstellung abzuschließen, müssen wir unsere Datenbankmigrationen ausführen, um unsere Thumps-Tabelle in der Heroku-Datenbank zu generieren.
$ heroku rake db: migrieren
Glückwunsch! Sie haben unsere Thump-Serveranwendung erfolgreich auf der Heroku-Plattform bereitgestellt. Nun zurück zur mobilen App!
Öffnen wir unsere main.lua-Datei in unserer Corona-App und fügen Sie die folgenden Zeilen oben hinzu:
http = requir ("socket.http") ltn12 = required ("ltn12") url = required ("socket.url") erfordert ("Json")
Wir benötigen einige Bibliotheken, mit denen wir eine Socket-Verbindung zu unserer Server-App herstellen können. Wir werden auch die JSON-Parsing-Bibliothek einschließen, damit wir die Antwortobjekte verstehen können, die der Server zurücksendet.
Erinnern Sie sich an den APPNAME, den Sie bei der Erstellung der Heroku-App erhalten haben? Es ist jetzt an der Zeit, dies zu nutzen:
lokaler appname = "APPNAMEHERE"
Diese Variable wird später mit anderen kombiniert, um unsere Server-URL für die externe Kommunikation zu generieren.
In Teil I hatten wir eine App, in der eine Warnmeldung mit unserer Nachricht angezeigt wurde, als ein "Knall" oder eine Schüttelbewegung festgestellt wurde. Da diese Nachricht an den Server übermittelt werden muss, entfernen Sie die folgende Zeile aus unserer getThump-Funktion:
local alert = native.showAlert ("Thump!", "Location:"? LatitudeText? ","? LongitudeText? "\ r \ nNachricht:"? textField.text, "OK")
Jetzt werden wir dieser getThump-Methode einige Funktionen hinzufügen, um unsere Nachricht an den Server zu senden. Brechen wir das mal auf:
local message = textField.text local post = "thump [deviceid] ="? Geräte ID? "& thump [lat] ="? LatitudeText? "& thump [lng] ="? longitudeText? "& thump [message] ="? lokale Antwort der Nachricht =
Hier generieren wir unsere Variablen, um sie an den Server zu senden. Die Variable "post" wird im Abfragezeichenfolgenformat eingerichtet und unsere "Antwort" wird vorerst als leeres Tabellenobjekt deklariert.
local r, c, h = http.request url = "http: //"? App Name? ".heroku.com / thumps", method = "POST", headers = ["content-length"] = #post, ["Content-Type"] = "application / x-www-form-urlencoded", source = ltn12.source.string (post), sink = ltn12.sink.table (Antwort) local jsonpost = Json.Decode (table.concat (Antwort, "))
Hier führen wir eine HTTP-Anfrage vom Typ POST an unseren Server aus. Wir subben in unserer Variable appname als Subdomain für die URL. Die Kopfzeilen sind Standard für einen typischen Nachruf. Im Feld "content-length" gibt die Lua-Syntax, die ein # vor die Variable einfügt, die Länge in Zeichen dieser Zeichenfolge aus. Da wir die Repsonse unseres Servers in einer Variablen namens "response" speichern möchten, wird diese Variable in unserer letzten Zeile als JSON-Objekt decodiert und ein Lua-Tabellenobjekt erstellt, damit wir auf die darin enthaltenen Felder zugreifen können.
Im Falle eines Kommunikationsfehlers müssen wir den Benutzer darauf aufmerksam machen, dass etwas schief gegangen ist. Wir erstellen eine generische showError () -Methode, um dem Benutzer ein Warnfeld anzuzeigen, wenn dies der Fall ist:
lokale Funktion showError () local alert = native.showAlert ("Error!", "Bitte versuchen Sie es noch einmal!", "OK") ende
Aufgrund der Tatsache, dass Rails von Natur aus Single-Threading ist, können Sie aufgrund der heroku-freien Konten nur einen einzigen Serverprozess ausführen. Sobald die mobile App den POST-Aufruf zum Senden von Daten abgeschlossen hat, werden wir unseren Server abfragen und nach einem Antwortobjekt fragen. Dies ist zwar nicht der ideale Weg, um dies zu planen, ermöglicht es uns jedoch, diese Art von App mit sehr geringen Heroku-Serverressourcen auszuführen.
Hier ist unsere Polling-Logik:
if (jsonpost.success == true), dann native.setActivityIndicator (true); lokale Versuche = 0 Funktion retrieveThump (Ereignis) Wenn 10 == Versuche, dann native.setActivityIndicator (false); timer.cancel (event.source) showError () else local response = lokales r, c, h = http.request url = "http: //"? App Name? ".heroku.com / thumps / search? thump [deviceid] ="? Geräte ID? "& thump [lat] ="? LatitudeText? "& thump [lng] ="? longitudeText, method = "GET", sink = ltn12.sink.table (Antwort) local jsonget = Json.Decode (table.concat (response))) if (jsonget.success == true), dann native.setActivityIndicator (false) timer.cancel (event.source) local alert = native.showAlert ("Thump!", jsonget.message, "OK") Endversuche = Versuche + 1 Timer.performWithDelay (3000, retrieveThump) End-Timer. performWithDelay (1000, retrieveThump) else showError () Ende
Brechen wir es auf:
if (jsonpost.success == true), dann native.setActivityIndicator (true) ;? else showError () Ende
Falls unsere Variable "jsonpost" vom Server "success = true" zurückgibt, setzen wir unseren ActivityIndicator auf dem Gerät auf true. Dadurch wird eine native Schnullerkomponente gestartet, die dem Benutzer signalisiert, dass die App an etwas arbeitet. Wenn wir vom Server kein "success = true" erhalten haben, rufen wir unsere generische Fehlerfunktion auf und zeigen das Fehleralarmfeld an.
lokale Versuche = 0 Funktion retrieveThump (Ereignis)? end timer.performWithDelay (1000, retrieveThump)
In diesem Fall setzen wir eine Versuchvariable außerhalb des Gültigkeitsbereichs unserer Funktion auf 0. Wir werden dies später verwenden, um die Anzahl der Anfragen zu begrenzen, die unsere Abruffunktion "retrieveThump" ausführen kann. Corona verfügt über eine eingebaute Timer-Klasse, mit der wir eine Funktion zeitlich aufrufen können. Die Funktion timer.performWithDelay benötigt eine Anzahl von Millisekunden und eine Funktion als Parameter.
wenn 10 == Versuche, dann native.setActivityIndicator (false); timer.cancel (event.source) showError ()
Zuerst prüfen wir, ob wir diese Funktion zehnmal ausgeführt haben. Wenn dies der Fall ist, stoppen wir unseren ActivityIndicator, indem wir ihn auf false setzen, unsere Timer-Funktion abbrechen und dann unsere Fehlerfunktion aufrufen, um dem Benutzer mitzuteilen, dass ein Fehler aufgetreten ist.
sonst lokale Antwort = Lokale r, c, h = http.request url = "http: //"? App Name? ".heroku.com / thumps / search? thump [deviceid] ="? Geräte ID? "& thump [lat] ="? LatitudeText? "& thump [lng] ="? longitudeText, method = "GET", sink = ltn12.sink.table (Antwort) local jsonget = Json.Decode (table.concat (response))) if (jsonget.success == true), dann native.setActivityIndicator (false) timer.cancel (event.source) local alert = native.showAlert ("Thump!", jsonget.message, "OK") Endversuche = Versuche + 1 Timer.performWithDelay (3000, retrieveThump) Ende
Wenn wir noch keine 10 Versuche erreicht haben, werden wir eine HTTP-Anfrage an unseren Server ausführen, um nach unserem übereinstimmenden "Schlag" zu suchen. Die Funktion sieht ähnlich aus wie der POST-Aufruf, den wir zuvor gemacht haben. In diesem Fall übergeben wir die Methode GET, weil wir versuchen, auf den Server zu lesen und nicht auf ihn zu schreiben.
Wenn Sie sich noch an Teil II erinnern, haben wir auf unserem Rails-Server eine Suchaktion erstellt, die unsere Datenbank nach einem passenden Schlag auf der Grundlage unserer GPS-Koordinaten und eines ähnlichen Zeitstempels durchsucht. Diese Informationen geben wir über die Abfragezeichenfolge in der URL an den Server weiter. Ähnlich wie beim POST-Aufruf analysieren wir das Ergebnis vom Server als JSON-Objekt und speichern es in einer lokalen Lua-Tabellenvariablen mit dem Namen "Jsonget". Wenn wir vom Server ein success = true erhalten, stoppen wir unseren ActivityIndicator, stoppen die Ausführung des Timers und zeigen unsere Nachricht in einem Warnfeld an. Wenn dieser Vorgang fehlschlägt, werden wir den Server für maximal 10 Versuche einfach erneut auf dieselbe Weise abfragen.
Und da hast du es! Dieses Lernprogramm bietet Ihnen eine gute Grundlage zum Erstellen verschiedener Arten von Apps, die Daten über Gesten austauschen. Einige interessante Ergänzungen könnten die Freigabe über ein gleichzeitiges Tippen auf dem Bildschirm sein oder die Anwendung erweitern, um Bilder auszutauschen, die entweder von der Kamera oder der lokalen Fotobibliothek des Geräts aufgenommen wurden. Fröhliches Klopfen!