JsonXat

De Cacauet Wiki
Revisió de 17:06, 22 maig 2014; Enric (Discussió | contribucions)

(dif) ←Versió més antiga | Versió actual (dif) | Versió més nova→ (dif)
Dreceres ràpides: navegació, cerca

Realitzarem una aplicació de xat a través del mòbil i de la web.

Per permetre una màxima eficiencia i bon disseny utilitzarem serveis web. Et caldrà haver llegit els següents articles:


Introducció[modifica]

Objectius:

  • Treballar web services.
  • Treballar JSON com a format estàndard de comunicació.
  • Establir una API de referència independent de l'implementació.
  • Treballar aplicacions mòbils.

Recursos:

  • Links articles anteriors.
  • curl: (Call URL) utilitat per línia de comandes Unix per testejar serveis web (i d'altres).
  • Pàgina web de test i exemple amb JavaScript:


Passes recomanades[modifica]

  1. Costat servidor: serveis web
  2. Costat client: exemple JavaScript
  3. Aplicació mòbil:


Definint la nostra API dels serveis JSON[modifica]

Aquesta part és important. Si estem fent un projecte que requereix comunicació entre diversos mòduls caldrà que realitzem un document com aquesta secció, indicant:

  1. quins serveis oferim
  2. com s'han de demanar (valors d'entrada)
  3. què ens retornen

Necessitem una interfície per parlar amb el servidor. Ens permetrà definir el protocol per enviar i rebre missatges independentment de la implementació que tinguem al servidor. És a dir que podem tenir el servei muntat sobre el filesystem o sobre una base de dades i que el client no noti la diferència, ja que la interfície és comuna.

Bàsicament volem enviar i rebre missatges. El nostre protocol tindrà, doncs:

  • Demanar llista de canals: xat_get_canals_ws. Prova amb:
    $ curl http://enricus.tk/serveis/xat_get_canals_ws
  • Demanar missatges per un canal: xat_get_canal_ws/<canal>
  • Enviar missatge per un canal: xat_set_missatge_ws

Detalls a continuació...

xat_get_canal_ws[modifica]

xat_get_canal_ws (entrada)
atribut valor (exemple) comentari
canal principal canal de xat del què volem rebre els missatges


xat_get_canal_ws (sortida)
atribut valor comentari
status true/false ens informa si tot ha anat bé
missatges [ {"remitent":"pere","missatge":"hola!"} , {} , {} ] llista de missatges del canal
missatge "canal inexistent"
"error intern"
detalls del status de la comanda

Test (versió JSON amb POST):

$ curl http://enricus.tk/serveis/xat_get_canal_ws -d '{"canal":"principal"}'

Test (simulant JSONP amb GET):

$ curl http://enricus.tk/serveis/xat_get_canal_ws?canal=principal

Prova d'introduir-hi errors per veure el resultat que ens ofereix.

xat_set_missatge_ws[modifica]

xat_set_missatge_ws (entrada)
atribut valor (exemple) comentari
canal principal canal de xat al què volem enviar el missatge
missatge "hola, com anem per aquí?" cos dels missatge a enviar


Cal tenir en compte que potser no us cal tota la informació que el servei ens dóna:

xat_set_missatge_ws (sortida)
atribut valor comentari
servei "xat" nom del servei que estem utilitzant (sempre serà "xat")
canal "principal" canal de xat al què hem volgut enviar el missatge
status true/false si la petició s'ha resolt OK (gravar missatge)
missatge "ERROR: JSON incorrecte"
"missatge enregistrat correctament"
missatge amb detalls de l'execució

Tingueu en compte que les dades es poden enviar per GET (cas del JSONP) o per POST (JSON normal). El servei implementa els dos casos, però si ho feu vosaltres penseu en què us cal comprovar les dades de les 2 fonts (GET i JSON).

Podeu testejar el POST amb: (prova també de variar la clau remitent o missatge per provocar que et retorni error)

$ curl http://enricus.tk/serveis/xat_set_missatge_ws -d '{"remitent":"nuria","missatge":"prova aviam"}'

Per testejar el GET amb JSONP utilitzeu la web: (provoca error si canvies el canal per un d'inexistent)

http://enricus.tk/jsonxat.html


Directiva de seguretat de browsers i JSONP[modifica]

En aquesta pràctica ens convé utiltizar JSONP (wikipedia) enlloc del JSON habitual per solventar un "problema" de seguretat. Bé, no és un problema, sinó una directiva amb molt de sentit:

SOP o Same-Origin Policy: simplement, els navegadors o browsers impedeixen crides a serveis en servidors que no son el què apareix a la URL en curs.

És lògic i convenient, perquè si no, ens poden "robar la cartera" quan naveguem.

Pel desenvolupament, però, ens provocarà certes molèsties. Les alternatives son:

  • Treballem sempre amb el mateix servidor+port amb JSON (important el port, diferents ports el navegador els considera diferents sites).
  • Col·locar un proxy en el nostre servidor perquè ens redirigeixi certes crides al 2n servidor (apache2 mod_proxy).
  • Utiltizar un "truc" anomenat JSONP. Ens permetrà cridar serveis en un altre servidor però només ens funciona a través de GET.

Teniu un exemple de tot plegat (particularment de la part JavaScript) a:

http://enricus.tk/jsonxat.html

Cal implementar JSONP al servidor i al client. La part negativa de tot plegat és que si després volem fer els serveis amb JSON haurem de duplicar codi o bé passar-lo de JSONP a JSON (seria convenient per seguretat).


App mòbil Android[modifica]

Utilitzeu l'article Android per iniciar-vos amb les aplicacions pel SO de Google.

Volem realitzar una app que ens faci la mateixa funció que la web d'exemple anterior. És a dir, que carregui i envii missatges a un servidor seguint el protocol marcat per la nostra API.

Exemples de tractament de dades JSON amb Android:


Procediment recomanat:

  1. Utilitzar llibreria estàndard de HTTP per descarregar-nos el "string" del servidor.
    • Us trobareu que el main thread no permet executar requests HTTP i llança l'excepció NetworkOnMainThreadException. Això ho fa per evitar que el main thread es quedi "penjat" esperant alguna cosa d'internet.
      Solució: utilitzar un thread apart.
      Threads en Java. Feu els exercicis de threads abans de continuar.
  2. Mostrar el string a un textView.
    • S'ha de fer des del GUI (main) thread. Per tant el nou thread que hem creat no pot fer un simple setText. Llegiu la resposta aquí (utiltizar view.post):
      http://stackoverflow.com/questions/9884246/how-to-set-text-of-text-view-in-another-thread
    • Ull quan actualitzeu una View (com el TextView). Perquè s'actualitzi (equival a un REPAINT de Qt):
      • Utilitzeu .invalidate() si esteu al main thread.
      • Utiltizeu .postInvalidate() si esteu a qualsevol altre thread.
  3. "Parsejar" el string obtingut i descodificar les dades dins d'estructures del nostre llenguatge (arrays, diccionaris, etc.). Utilitzar JSONObject
  4. Enviar missatges al xat a través del web service xat_set_missatge_ws