Diferència entre revisions de la pàgina «JsonXat»

De Cacauet Wiki
Salta a la navegació Salta a la cerca
 
(Hi ha 12 revisions intermèdies del mateix usuari que no es mostren)
Línia 2: Línia 2:
  
 
Per permetre una màxima eficiencia i bon disseny utilitzarem serveis web. Et caldrà haver llegit els següents articles:
 
Per permetre una màxima eficiencia i bon disseny utilitzarem serveis web. Et caldrà haver llegit els següents articles:
 +
* [[Web Services]]
 
* [[Web Services amb Pyramid i Cornice]]
 
* [[Web Services amb Pyramid i Cornice]]
 
* [[Android]]
 
* [[Android]]
Línia 29: Línia 30:
 
#* http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/renderers.html#jsonp-renderer
 
#* http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/renderers.html#jsonp-renderer
 
#* Test amb curl
 
#* Test amb curl
 +
#* Teniu el codi per aquest projecte íntegre (versió Pyramid, utilitzant sistema d'arxius, sense DB):
 +
#*: https://github.com/lacetans/jsonxat_ws
 
# Costat client: exemple JavaScript
 
# Costat client: exemple JavaScript
 
#* http://enricus.tk/jsonxat.html
 
#* http://enricus.tk/jsonxat.html
 
#* Instal·leu l'exemple al vostre domini
 
#* Instal·leu l'exemple al vostre domini
 
# Aplicació mòbil:
 
# Aplicació mòbil:
#* [[Android]]
+
#* [[JsonXat#App_mòbil_Android]] (en aquest article, més avall)
 +
#* [[Android]]: per introduir-se a la programació Android
  
 
<br>
 
<br>
Línia 87: Línia 91:
 
|}
 
|}
  
Podeu testejar-ho amb:
+
Test (versió JSON amb POST):
  $ curl http://enricus.tk/serveis/xat_get_canal_ws
+
$ 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 ===
 
=== xat_set_missatge_ws ===
Línia 141: Línia 150:
 
Per testejar el GET amb JSONP utilitzeu la web: (provoca error si canvies el canal per un d'inexistent)
 
Per testejar el GET amb JSONP utilitzeu la web: (provoca error si canvies el canal per un d'inexistent)
 
  http://enricus.tk/jsonxat.html
 
  http://enricus.tk/jsonxat.html
 +
 +
<br>
  
 
== Directiva de seguretat de browsers i JSONP ==
 
== Directiva de seguretat de browsers i JSONP ==
Línia 162: Línia 173:
  
 
== App mòbil Android ==
 
== App mòbil Android ==
Utiltizeu l'article [[Android]] per iniciar-vos amb les aplicacions pel SO de Google.
+
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.
 
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:
 +
* Robust: teniu codi en la carpeta "android"
 +
* [http://stackoverflow.com/questions/2793150/how-to-use-java-net-urlconnection-to-fire-and-handle-http-requests StackOverflow java i http].
 +
 +
 +
Procediment recomanat:
 +
 +
# 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.
 +
#*: [http://uf.ctrl-alt-d.net/material/mostra/147/threads-en-java Threads en Java]. '''Feu els exercicis de threads abans de continuar'''.
 +
# 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''.
 +
# "Parsejar" el string obtingut i descodificar les dades dins d'estructures del nostre llenguatge (arrays, diccionaris, etc.). Utilitzar JSONObject
 +
# Enviar missatges al xat a través del ''web service'' xat_set_missatge_ws

Revisió de 15:06, 22 maig 2014

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