Diferència entre revisions de la pàgina «JsonXat»
 (Es crea la pàgina amb «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 el…».)  | 
				|||
| (Hi ha 17 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>  | ||
== Definint la nostra API dels serveis JSON ==  | == Definint la nostra API dels serveis JSON ==  | ||
| + | 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:  | ||
| + | # quins serveis oferim  | ||
| + | # com s'han de demanar (valors d'entrada)  | ||
| + | # 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.  | 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: <pre>$ curl http://enricus.tk/serveis/xat_get_canals_ws</pre>  | ||
| + | * Demanar missatges per un canal: '''xat_get_canal_ws/<canal>'''  | ||
| + | * Enviar missatge per un canal: '''xat_set_missatge_ws'''  | ||
| + | |||
| + | Detalls a continuació...  | ||
<br>  | <br>  | ||
| + | === xat_get_canal_ws ===  | ||
| + | |||
| + | {| border="1" class="wikitable" style="border-collapse:collapse;"  | ||
| + | |+ xat_get_canal_ws (entrada)  | ||
| + | ! atribut  | ||
| + | ! valor (exemple)  | ||
| + | ! comentari  | ||
| + | |-  | ||
| + | | canal  | ||
| + | | principal  | ||
| + | | canal de xat del què volem rebre els missatges  | ||
| + | |}  | ||
| + | |||
| + | <br>  | ||
| + | |||
| + | {| border="1" class="wikitable" style="border-collapse:collapse;"  | ||
| + | |+ 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"<br>"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 ===  | ||
| + | |||
| + | {| border="1" class="wikitable" style="border-collapse:collapse;"  | ||
| + | |+ 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  | ||
| + | |}  | ||
| + | |||
| + | <br>  | ||
| + | |||
| + | Cal tenir en compte que potser no us cal tota la informació que el servei ens dóna:  | ||
| + | |||
| + | {| border="1" class="wikitable" style="border-collapse:collapse;"  | ||
| + | |+ 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"<br>"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  | ||
| + | |||
| + | <br>  | ||
== Directiva de seguretat de browsers i JSONP ==  | == Directiva de seguretat de browsers i JSONP ==  | ||
| Línia 63: | Línia 173: | ||
== App mòbil Android ==  | == App mòbil Android ==  | ||
| − | + | 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:
Contingut
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]
- Costat servidor: serveis web
- Es pot realitzar amb el llenguatge/framework de la vostra elecció (en principi Pyramid o PHP).
 - Web Services amb Pyramid i Cornice
 - JSONP en Pyramid: ens resulta més convenient ja que podem cridar la llibreria entre servidors (problema de seguretat dels browsers i la política de "mateix domini" en les crides JSON).
 - http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/renderers.html#jsonp-renderer
 - Test amb curl
 - Teniu el codi per aquest projecte íntegre (versió Pyramid, utilitzant sistema d'arxius, sense DB):
 
 - Costat client: exemple JavaScript
- http://enricus.tk/jsonxat.html
 - Instal·leu l'exemple al vostre domini
 
 - Aplicació mòbil:
- JsonXat#App_mòbil_Android (en aquest article, més avall)
 - Android: per introduir-se a la programació Android
 
 
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:
- quins serveis oferim
 - com s'han de demanar (valors d'entrada)
 - 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]
| atribut | valor (exemple) | comentari | 
|---|---|---|
| canal | principal | canal de xat del què volem rebre els missatges | 
| 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]
| 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:
| 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:
- Robust: teniu codi en la carpeta "android"
 - 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.
 - Threads en Java. Feu els exercicis de threads abans de continuar.
 
 
 - 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.
 - 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):
 - 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