====== Comunicacions en Android ======
{{ android:android-networking-intro.png?400 }}
Referències:
* [[Android]]: article general d'Android
* [[Android Threads]]: s'hi treballa connexions REST HTTP
* [[Android ListView]]
{{tag> #Dam #DamMp08 #DamMp08Uf01 #DamMp08Uf1 #DamMp08Uf02 #DamMp08Uf2 #DamMp09 #DamMp09Uf02 #DamMp09Uf2 android threads mobile java kotlin }}
===== Comunicacions REST HTTP =====
Les comunicacions de les APIs habituals es solen fer amb HTTP/HTTPS. El problema habitual sol ser que aquestes crides de xarxa bloquegen el fil d'execució fins que es reben les dades. Això no es pot fer al fil d'execució principal, main o UI Thread. Serà imprescindible, doncs, emprar les llibreries de //threading// per executar les operacions de xarxa en un fil paral·lel.
A l'article [[Android Threads]] s'explica com realitzar aquest tipus d'accés HTTP a APIs externes.
\\
===== Android i WebSockets =====
Per a WebSockets, la implementació de la llibreria ja és asíncrona, pel què podem cridar el mètode ''connect()'' i aquest ja gestiona l'execució d'un //thread// paral·lel que cridarà les //callbacks// en cas d'arribada de missatges ''onMessage()'' o finalització de la comunicació ''onClose()''.
Per poder emprar la [[https://github.com/TooTallNate/Java-WebSocket|biblioteca de codi Java WebSockets]] en Android caldrà afegir algunes línies als arxius:
dependencies {
...
implementation(libs.websocket)
...
}
[versions]
...
websocket = "1.5.7"
[libraries]
...
websocket = { group = 'org.java-websocket', name = "Java-WebSocket", version.ref = "websocket" }
Recordem que per poder-se connectar a internet, cal [[https://developer.android.com/training/basics/network-ops/connecting|activar el permís Android d'accés a Internet]]:
Un cop fet tot això podrem emprar les biblioteques WebSockets al nostre codi:
class MainActivity : AppCompatActivity() {
// "inner" és important per accedir als mètodes de MainActivity
inner class MyWebSocketClient(serverUri: URI) : WebSocketClient(serverUri) {
override fun onOpen(handshakedata: ServerHandshake?) {
println("✅ Connectat al servidor")
println("🔗 Codi d'estat: ${handshakedata?.httpStatus}")
println("📝 Descripció: ${handshakedata?.httpStatusMessage}")
}
override fun onMessage(message: String?) {
println("📥 Rebut: $message")
// crides segures a la GUI (main thread)
runOnUiThread {
val tv = findViewById(R.id.textView)
tv.text = "Nou missatge: $message"
}
}
override fun onClose(code: Int, reason: String?, remote: Boolean) {
println("🔌 Connexió tancada")
println("📋 Codi: $code, Raó: $reason, Remote: $remote")
}
override fun onError(ex: Exception?) {
println("❌ Error: ${ex?.message}")
ex?.printStackTrace()
}
}
fun connectaWS() {
val uri = URI("ws://server.domini.tld") // utilitzeu wss:// si va sobre HTTPS
var wsclient = MyWebSocketClient(uri)
wsclient.connect()
}
}
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;
...
WebSocketClient client = null;
URI location = "ws://mywsserver.com";
try {
client = new WebSocketClient(new URI(location), (Draft) new Draft_6455());
client.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
System.out.println("Error: " + location + " no és una direcció URI de WebSocket vàlida");
}
client.send("Hola! M'acabo de connectar");
...
**Main thread i network thread**
Recordeu (com s'explica a [[Android Threads]]) que no es poden dur a terme accions de xarxa en el //main thread// que és el de la GUI.
L'objecte ''WebSocketClient'' facilita la gestió del //thread// de comunicació alternatiu o //network thread// (no caldrà que el creem explícitament i podem emprar directament les //callbacks// com ''onMessage'').
Per actuar, en canvi, sobre la GUI cal fer-ho des del //main thread// de nou. En aquest cas ho resolem amb la funció ''runOnUiThread''.
Teniu més explicacions i exemples de WebSockets a la pàgina [[WebSockets Java]] d'aquesta wiki.