In questa sezione vedremo la gestione delle connessioni in rete da applicazioni mobili e introdurremo il concetto del Generic Connection Framework (GCF) che è alla base di tutte le operazioni di input e output (di rete, file system, ecc.) in J2ME.
L'elemento fondamentale della struttura è la classe Connector
che può essere usata per creare qualsiasi tipo di connessione verso: file, protocollo http, datagramma, socket, ecc, usando un istruzione con sintassi:
Connector.open("protocol:address:parameters");
È cura della struttura del GCF risolvere le complessità relative al riconoscimento del protocollo, dell'url e dei parametri.
Connessione HTTP
Implementiamo una semplice midlet che esegue una connessione HTTP, al sito di Google, e visualizza in un form la stringa HTML che viene ritornata.
Le istruzioni di connessione, siccome possono essere bloccanti a livello di applicazione, devono essere gestite in un thread separato, in modo da consentire all'utente di effettuare, se vuole, altre operazioni:
Listato 17. Connessione HTTP (Vedi codice completo)
..//
conn = (HttpConnection)Connector.open(URL);
rc = conn.getResponseCode();
if (rc == HttpConnection.HTTP_OK)
{
int c;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
is = conn.openInputStream();
while ((c = is.read()) != -1)
{
baos.write(c);
}
String s = new String(baos.toByteArray());
baos.close();
is.close();
conn.close();
displayResult(s);
}
..//
La classe HttpConnector
appena vista utilizza proprio Connector per effettuare la connessione all'URL stesso.
L'oggetto HttpConnection
, che otteniamo, ci permette di vedere se la connessione è avvenuta con successo, grazie al codice di risposta che si può ottenere con il metodo getResponseCode()
. Analizzando questo codice è possibile, inoltre, vedere se il server ci chiede di effettuare un redirect, o se la pagina a cui si sta accedendo è sottoposta ad autenticazione, ecc.
Se la connessione è ok, iniziamo a leggere i caratteri dall'input stream, salvandoli in un oggetto ByteArrayOutputStream
, fino a quando il metodo read ritorna il valore -1, che ci indica la fine dello stream.
Ottenuta la stringa dall'array di byte (con il codice HTML di Google), la si può visualizzare nel Form tramite il metodo displayResult
:
L'avvio della connessione viene fatta dalla Midlet nel seguente modo:
Listato 18. Avvio della connessione
public class HttpDemo extends MIDlet
{
private Display display = null;
public HttpDemo()
{
display = Display.getDisplay(this);
}
protected void startApp() throws MIDletStateChangeException
{
Form f = new Form("Connessione");
f.append("Connessione in corso");
display.setCurrent(f);
HttpConnector con = new HttpConnector(display);
Thread th = new Thread(con);
th.start();
}
..//
}
Nell'esempio, appena visto, abbiamo realizzato la semplice lettura (GET) di dati attraverso una connessione HTTP.
La classe HttpConnection
ci permette anche di inviare dati sulla rete e di realizzare quindi una POST usando il metodo setRequestMethod
:
conn.setRequestMethod(HttpConnection.POST);
e mette a disposizione l'istruzione setRequestProperty
per settare proprietà della richiesta come lo User-Agent, Content-Language, ecc.
Nell'eseguire la POST si possono inviare parametri dal nostro client. Supponiamo di dover fare una post in cui passiamo i nostri dati di login e password; dovendo scrivere qualcosa su uno stream abbiamo bisogno di un OutputStream
:
Listato 19. Invio di username e password tramite post
OutputStream os = conn.openOutputStream();
byte[] data = ("login="+login).getBytes();
os.write(data);
data = ("&password="+password).getBytes();
os.write(data);
os.flush();
La risposta del server può essere letta in maniera analoga al caso precedente.
Quando si ottiene la risposta si possono leggere i dati di header HTTP utilizzando getHeaderField()
, passando, come parametro, il nome dell'header che si vuole leggere.