Bine ați venit la partea a III-a din seria "Partajarea datelor cu gesturi". În partea a II-a, am creat procesul nostru server intermediar în Ruby on Rails. Acest proces de server va acționa ca o conductă între două dispozitive care încearcă să comunice cu un gest pe care îl numim "bate". Atunci când două dispozitive sunt "îndoite", serverul se va potrivi prin calcularea apropierii lor prin coordonatele GPS, precum și printr-un timbru de timp aproape identic când se deschide o comunicare cu serverul. Odată ce acest meci a fost efectuat, serverul va schimba mesajele introduse în aplicația mobilă, simulând comunicarea dintre dispozitiv și dispozitiv.
În partea a III-a, vom implementa aplicația serverului nostru pe platforma heroku și apoi vom actualiza aplicația noastră mobilă pentru a comunica cu acesta.
Pentru a începe, vom modifica fișierul de migrare a tabelului thumps pentru a fi compatibil cu Postgres. Puteți găsi acest fișier în directorul "db / migrate" și acesta va fi denumit cum ar fi: TIMESTAMP_create_thumps.rb. Cea mai ușoară modalitate de a implementa o aplicație heroku este utilizarea serviciului de baze de date partajate, care se întâmplă să fie Postgres în loc de MySQL. Vom înlocui următoarele linii:
t.decimal: lat,: precision => 8,: scale => 8 t.decimal: lng,: precizie => 8,: scale => 8
cu aceste linii noi:
t.decimal: lat,: scale => 8 t.decimal: lng,: scale => 8
Postgres-ul gestionează câmpurile zecimale mari în mod diferit față de MySQL, deci este o schimbare necesară pentru a ne asigura că avem precizia datapointului de care avem nevoie în câmpurile latitudine și longitudine.
Deoarece aceasta este o aplicație Rails 2.3.5, vom folosi metoda heroku mai veche de instalare a pietrelor prin crearea unui fișier .gems în rădăcina proiectului nostru Rails. Majoritatea probabil că veți fi obișnuiți să folosiți Bundler pentru acest tip de sarcină, dar de vreme ce pluginul geokit nu a fost modernizat pentru a fi compatibil cu Rails 3.0, trebuie să facem lucrurile cu vechile convenții Rails 2.
Pur și simplu adăugăm următoarele în fișierul .gems:
rails -v 2.3.5 pg geokit - versiune '= 1.5.0'
Aici specificăm galeria șinelor și versiunea pe care o folosim pentru acest proiect, precum și bijuteria postgres și versiunea 1.5.0 a gemului geokit.
Acum putem începe implementarea noastră! Să începem prin crearea unui magazin git local în cadrul proiectului nostru. Tot ce trebuie să facem este să rulați următoarea comandă în directorul rădăcină al proiectului Rails:
$ git init
Înainte de a ne angaja în acest depozit, trebuie să creați aplicația noastră pe platforma heroku. Dacă nu v-ați înscris încă pentru un cont de heroku gratuit, faceți-o prin simpla înregistrare la adresa https://api.heroku.com/signup. Dacă nu aveți încă instalat sistemul de operare heroku în sistemul dvs., puteți face acest lucru executând următoarea comandă:
$ sudo gem instala heroku
După ce ați instalat bijuteria, executați următoarea comandă din interiorul directorului rădăcină al proiectului:
$ heroku creați -stack bamboo-ree-1.8.7
Aici specificăm stiva de bambus-ree din cauza faptului că este o aplicație Rails 2. În cazul în care tocmai ați creat un cont nou, acesta vă poate solicita acreditările contului dvs. heroku. Odată introduse, aceste acreditări vor fi stocate pentru viitoarele interacțiuni cu serverele heroku. Dacă totul merge bine, heroku ar trebui să răspundă cu ceva de genul:
Creat http://APPNAME.heroku.com/ | [email protected]: APPNAME.git Git remote heroku adăugat
Aici am înlocuit numele aplicației și subdomeniului cu un proprietar de locație numit APPNAME. Luați notă de acest APPNAME, așa cum îl vom folosi mai târziu. Acum ne vom angaja dosarele de proiect la depozitul local de git pe care l-am creat mai devreme. Este la fel de simplu ca executarea acestor două comenzi:
$ git add. $ git commit -m "primul meu comitet"
Odată ce proiectul a fost pe deplin angajat la replica git locală, trebuie să-l împingem la depozitul de la distanță care a fost creat atunci când am executat comanda heroku create.
$ git împinge master heroku
Gemul heroku vă permite să executați comenzi rapide la distanță de pe server cu comanda "heroku rake". Pentru a finaliza implementarea, trebuie să rulați migrațiile bazei de date care vor genera tabelul nostru în baza de date heroku.
$ heroku rake db: migrează
Felicitări! Ați instalat cu succes aplicația noastră pentru serverul thump la platforma heroku. Acum, reveniți la aplicația mobilă!
Să deschidem fișierul principal.lua din aplicația noastră Corona și să adăugăm următoarele linii în partea de sus:
http = necesită ("socket.http") ltn12 = necesită ("ltn12") url = necesită ("socket.url"
Trebuie să solicităm câteva biblioteci care ne vor permite să creăm o conexiune socket la aplicația noastră pentru server. De asemenea, vom include biblioteca de parsare JSON pentru a înțelege obiectele de răspuns pe care serverul le va trimite înapoi.
Amintiți-vă APPNAME care a fost dat când am creat pentru prima dată aplicația heroku? E timpul sa folosim asta acum:
local appname = "APPNAMEHERE"
Această variabilă va fi combinată cu alții mai târziu pentru a genera adresa URL a serverului pentru comunicarea externă.
În Partea I, am avut aplicația care arăta o casetă de alertă cu mesajul nostru atunci când a detectat un gest "tâmpit" sau agitat. Deoarece trebuie să comunicăm acest mesaj serverului, vom elimina următoarea linie din interiorul funcției getThump:
alertă locală = native.showAlert ("Thump!", "Locație:"? latitudeText? ","? longitudeText? "\ r \ nMessage:"? textField.text, "OK"
Acum vom adăuga câteva funcționalități pentru această metodă getThump pentru a trimite mesajul nostru către server. Să facem asta:
mesaj local = textField.text post local = "bord [deviceid] ="? identificatorul dispozitivului? "& Thump [lat] ="? latitudeText? "& Thump [lng] ="? longitudeText? "& Tronc [mesaj] ="? mesaj răspuns local =
Aici generăm variabilele noastre pentru a le trimite la server. Variabila "post" este setată în formatul șirului de interogare și "răspunsul" nostru este declarat acum ca un obiect tabel gol.
local r, c, h = http.request url = "http: //"? numele aplicatiei? ".heroku.com / thumps", metoda = "POST", anteturi = ["content-length"] = #post, ["Content-Type"] = "application / x-www-form-urlencoded" source = ltn12.source.string (post), sink = ltn12.sink.table (răspuns) locale jsonpost = Json.Decode (table.concat (răspuns, "))
Aici executam o cerere HTTP de tip POST pe serverul nostru. Vom substitui în variabila noastră de appname ca subdomeniu pentru url. Antetele sunt standard pentru un apel tipic tipic. În câmpul "lungime de conținut", sintaxa lua de a plasa un # în fața variabilei va afișa lungimea în caracterele acelui șir. Din moment ce dorim să stocăm repondsul serverului nostru într-o variabilă numită "răspuns", ultima noastră linie va decoda acea variabilă ca obiect JSON și va crea un obiect de masă pentru a putea accesa câmpurile din el.
În cazul unei erori de comunicare, trebuie să avertizăm utilizatorul că ceva nu a mers bine. Vom crea o metodă generică showError () pentru a afișa o casetă de avertizare utilizatorului dacă are loc acest lucru:
funcția locală showError () alert local = native.showAlert ("Eroare!", "Vă rog încercați din nou!", "OK")
Datorită faptului că Rails este unic filetat de natură și din moment ce conturile gratuite heroku vă permit să executați doar un singur proces server; odată ce aplicația mobilă finalizează apelul POST pentru a trimite date, vom examina serverul nostru, solicitând un obiect de răspuns. Deși acest lucru nu poate fi cel mai ideal mod de a arhitecta acest lucru, ne permite să rulați acest tip de aplicație cu resurse server foarte mici server heroku.
Iată logica noastră de sondare de mai jos:
dacă (jsonpost.success == true), atunci native.setActivityIndicator (true); încercări locale = 0 funcția retrieveThump (eveniment) dacă 10 == încearcă apoi native.setActivityIndicator (false); timer.cancel (event.source) showError () alt local answer = local r, c, h = http.request url = "http: //"? numele aplicatiei? ".Heroku.com / thumps / search? Thump [DeviceId] ="? identificatorul dispozitivului? "& Thump [lat] ="? latitudeText? "& Thump [lng] ="? longitudeText, method = "GET", sink = ltn12.sink.table (răspuns) locale jsonget = Json.Decode (table.concat (răspuns, ")) dacă (jsonget.success == true) ); timer.cancel (event.source) alertă locală = native.showAlert ("Thump!", jsonget.message, "OK") încercări de final = încercări + 1 timer.performWithDelay (3000, retrieveThump). performWithDelay (1000, retrieveThump) altfel showError () final
Să-l distrugem:
dacă (jsonpost.success == true), atunci native.setActivityIndicator (true); altceva arataError () sfarsit
În cazul în care variabila noastră "jsonpost" returnează "success = true" de la server, vom seta ActivityIndicator pe dispozitiv la true. Acest lucru lansează o componentă suveică nativă care semnalează utilizatorului că aplicația lucrează la ceva. Dacă nu am primit un "success = true" de la server, vom apela funcția de eroare generică și vom afișa caseta de alertă de eroare.
încercări locale = 0 funcția retrieveThump (eveniment)? end timer.performWithDelay (1000, retrieveThump)
În acest caz, setăm o variabilă de încercări în afara scopului funcției noastre la 0. Vom folosi acest lucru mai târziu pentru a pune un plafon în numărul de solicitări pe care le poate face funcția de retransmisie de tip "retrieveThump". Corona are o clasă încorporată, care ne permite să sunăm o funcție într-un interval de timp. Funcția timer.performWithDelay are un număr de milisecunde și o funcție ca parametri.
dacă 10 == încearcă apoi native.setActivityIndicator (false); timer.cancel (eveniment.source) showError ()
În primul rând, vom verifica dacă am executat această funcție de 10 ori. Dacă acesta este cazul, vom opri activitatea ActivityIndicator setând-o la false, anulându-ne funcția de timer și apoi sunând la funcția de eroare pentru a spune utilizatorului că ceva nu a mers.
altfel răspuns local = local r, c, h = http.request url = "http: //"? numele aplicatiei? ".Heroku.com / thumps / search? Thump [DeviceId] ="? identificatorul dispozitivului? "& Thump [lat] ="? latitudeText? "& Thump [lng] ="? longitudeText, method = "GET", sink = ltn12.sink.table (răspuns) locale jsonget = Json.Decode (table.concat (răspuns, ")) dacă (jsonget.success == true) ); timer.cancel (event.source) alertă locală = native.showAlert ("Thump!", jsonget.message, "OK") încercări sfârșitul încercărilor + 1 timer.performWithDelay (3000, retrieveThump)
Dacă nu am ajuns încă la 10 încercări, vom executa o solicitare HTTP către serverul nostru pentru a căuta potrivirea noastră "ticăloșie". Funcția arată asemănătoare cu apelul POST pe care l-am făcut mai devreme, numai că trecem prin metoda GET în acest caz deoarece încercăm să citim și să nu scriem pe server.
Dacă vă amintiți din Partea a II-a, am creat o acțiune de căutare pe serverul nostru Rails care caută baza noastră de date pentru o potrivire potrivită pe baza coordonatelor GPS și a amprentei de timp similare. Transmitem aceste informații către server prin șirul de interogări din URL. Similar cu apelul POST, analizăm returnarea de pe server ca obiect JSON și stocarea acestuia într-o variabilă locală de masă numită "jsonget". Dacă vom primi un succes = adevărat înapoi de la server, vom opri activitatea noastră de activitate, vom opri executarea cronometrului și vom afișa mesajul nostru într-o casetă de alertă. În cazul în care acest proces eșuează, vom pur și simplu să sunăm din nou în același mod pentru maximum 10 încercări.
Și acolo aveți! Acest tutorial vă va oferi o bază bună pentru a crea diferite tipuri de aplicații care partajează date prin gesturi. Unele adăugări interesante ar putea fi partajarea printr-o apăsare simultană a ecranului sau extinderea aplicației pentru a face schimb de imagini fie din camera foto, fie din biblioteca foto locală a dispozitivului. Happy Thumping!