Web Service Client Android - 4

 

NorthwindProvider

E siamo arrivati a ottenere la risposta SOAP dal server in formato stringa. La stringa viene trasformata in un oggetto di tipo InputSource che viene elaborato tramite un parser SAX per ricostruire le entity presenti nel file XML. Il parser SAX fa uso di una particolare classe che abbiamo implementato (EmployeeParser) che contiene tutti i metodi di callback che vengono eseguiti per elaborare ogni tag (startElement, endElement...). Il provider in questo modo è in grado di restituire il soap result come una Lista generic di Employee. Nel nostro caso facciamo visualizzare solo il numero di Emloyee che costitusicono tale lista

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Per quanto riguarda l'invocazione del secondo metodo in ordine di apparizione sulla UI, il codice si preoccupa di costruire il soap di richiesta inserendo il parametro atteso sotto forma di tag soap (nel nostro caso l'ID dell'employee). Per questo motivo si costruisce l'array di parametri inserendovi (oltre al nome del metodo da invocare) anche il nome e il valore del parametro. In pratica, per riprodurre la corretta invocazione del metodo tramite questo SOAP:

Verrà eseguito questo codice sulla main activity

public void btn_EmployeeOrders_click(View v){
	TextView txt = (TextView)findViewById(R.id.txt_EmployeeID);
	String employeeIDAsString = txt.getText().toString();
	String paramNameEmployeeID = "EmployeeID";
	String paramValueEmployeeID = employeeIDAsString;
	new CallWebServiceTask().execute("GetOrderByIDEmployee", paramNameEmployeeID, paramValueEmployeeID);		
 }
 

Custom Adapter

Nell'ultimo caso di invocazione di metodo di Web Service abbiamo il caso delle Categories. In questo caso, visto che ciascuna category contiene un campo in formato base 64 per l'immagine della categoria, nell'adapter custom viene trasformato il base64 in una bitmap:

public static Bitmap getBitmapFromBase64(String base64) throws Exception {
	byte[] decoded = Base64.decode(base64, DEFAULT);
	return BitmapFactory.decodeByteArray(decoded , 0, decoded.length);
}

A questo punto non resta che fornire il codice di tutto il progetto su Eclipse scaricabile da questo link.

Northwind Web Service

 

Come promesso sono riuscito a pubblicare il DB Northwind tramite un Web Service che si appoggia a sua volta su Entity Framework (4). L'indirizzo del file .asmx è il seguente http://www.svservices.it/SVNorthwindService.asmx il quale fornisce la lista dei metodi consumabili dall'esterno. La lista (con nomi abbastanza espliciti è la seguente ed è descritta un pò più dettagliatamente in un mio precedente post

 

Di seguito invece riportiamo un esempio per un semplicissimo codice client implementato tramite un progetto console in C# in cui, dopo aver fatto il corretto "add service reference" per scaricare il WSDL, usa il proxy così generato per invocare il metodo "GetAllEmployees".

namespace TestSoapClient
{
    class Program
    {
        static void Main(string[] args)
        {
            SVNorthwindService proxy = new SVNorthwindService();
            LightEmployee[] arrayOfEmployees = proxy.GetAllEmployees();

            foreach (LightEmployee employee in arrayOfEmployees)
            {
                Console.WriteLine(employee.FirstName + " " + employee.LastName);
            }
        }
    }
}

Risultato del codice precedente è semplicemente questo:

Web Service Client Android - 3

 

Using AsyncTask

Dopo aver visto come è strutturata la classe (CallWebServiceTask) per eseguire l'invocazione del Web Service Method in maniera asincrona, diamo il via al tutto inserendo nel metodo button_click relativo al click del bottone sulla UI la seguente riga di codice

 public void btn_GetEmployees_Click(View v){ new CallWebServiceTask().execute("GetAllEmployees"); }

 Questo da il via alla creazione del worker thread e l'invocazione del metodo doInBackground il quale dopo aver ricavato dai parametri il metodo da invocare, ricostruisce la SOAPAction che ricordiamo essere costituita dal namespace concatenato al metodo da invocare separato dallo "/" cioè: http://sandrovecchiarelli.com/Services/SVNorthwind/GetAllEmployees.

Northwind Proxy

Al nostro proxy è demandato il compito di costruire correttamente il file XML SOAP, in particolare la SOAP Request. Ricordiamo che lo schema SOAP impone di racchiudere nel tag "envelop" il tag soap:header e soap:body. Abbiamo cercato di rendere la costruzione del proxy in maniera totalmente parametrizzata così da poter riusare facilmente il codice nel caso volessimo applicare il tutto alla invocazione di un altro web service.

In un altro metodo della stessa classe NorthwindProxy, il metodo getHttpPost, viene utilizzato il metodo per costruire la SOAP response (come spiegato sopra) per inserire quest'ultima in un HttpRequest (httpPost) da inviare al server. L'httpPost è corredata quindi dei vari headers (quali per esempio il content/type).

Invio HttpPost

Dopo aver costruito l'HttpRequest contenente il SOAP di richiesta si invia il tutto e si attende l'HttpResponse in un metodo di callback in cui si ricostruisce il SOAP di risposta inserendolo in una String. A questo punto quando tutto è completato si costruisce l'oggetto OprationResult che nelle sue due proprietà contiene sia la stringa appena costruita, sia il metodo chiamato (GetAllEmployees). A seguito viene invocato il metodo "void onPostExecute(OperationResult operationResult)" che elabora la stringa di risposta.

Vedremo in seguito come elaborare la risposta.

Web Service Client Android - 2

Abbiamo a disposizione quindi un Web Service Northwind (come descritto nel precedente post) e quindi siamo in grado di partire con un nuovo progetto Eclipse per costruire un client che consumi i metodi del nostro WS. Creiamo quindi un nuovo progetto Android che chiameremo NorthwindClient...ovviamente. In figura la struttura del progetto completo nella versione finale:

Concentriamoci per ora sulla main activity il cui layout è costituito da alcuni bottoni e una textbox. Riproducete il layout come in fgura così da avere un bottone per ottenere la lista degli employees, un bottone per gli ordini del singolo employee il cui id viene inserito nella textbox ed infine un bottone per ottenere tutte le category di Northwind che visualizzeremo in un'altra activity dove visualizzeremo una Listview custom per renderizzare le immagini contenute in un campo base64 di category.

 

 

 

 

 

 

Ecco la main activity:

Per invocare il Web Service, faremo utilizzo delle tecniche di accesso alla rete asincrone. Come sappiamo in Android si utilizza una classe che estende AsyncTask<T1,T2,T3> generic. La nostra classe si chiama CallWebServiceTask e si occuperà di eseguire la chiamata al web service in maniera asincrona. Tale classe fornisce almeno due metodi (per la documentazione completa rimandiamo alla documentazione ufficiale di Android): uno che viene invocato per eseguire la chiamata in maniera asincrona su un thread differente rispetto allo UI-Thread (cioè quello che si occupa della renderizzazione della UI) e un altro per eseguire le operazioni di visualizzazione del risultato non appena il worker-thread ha ottenuto la risposta dal Web Service.

Lo scheletro della classe  (una inner class della classe Main) è il seguente:

 private class CallWebServiceTask extends AsyncTask<String, Void, OperationResult> {
   @Override
   protected OperationResult doInBackground(String... params) {
//..... } @Override protected void onPostExecute(OperationResult operationResult) { //...... } }

Come si vede il codice descrive la classe e i tipi coinvolti nell'operazione asincrona. Quando verrà invocato il metodo doInBackground questo in input si aspetta una o più stringhe(T1), ritornando in output un oggetto di tipo OperationResult (T3). Il secondo tipo T2 è di tipo void perchè non lo usiamo, ma sta a rappresentare il tipo utilizzato per restituire i valori parziali che illustrano il progresso dell'operazione in background.

OperationResult

Questo tipo di dato è un semplice oggetto con due proprietà:

 public class OperationResult {	
	private String actionName;
	private String result;

	public OperationResult() {
		super();
	}
	public OperationResult(String soapAction, String responseString) {
		// TODO Auto-generated constructor stub
		this.actionName = soapAction;
		this.result = responseString;
	}
	public String getActionName() {
		return actionName;
	}
	public void setActionName(String actionName) {
		this.actionName = actionName;
	}
	public String getResult() {
		return result;
	}
	public void setResult(String result) {
		this.result = result;
	}
}

La prima proprietà rappresenta il nome del metodo che noi abbiamo invocato, mentre la seconda contiene il SOAP di risposta proveniente dal Web Service. Questo sarà anche il tipo che si aspetta in input il metodo onPostExecute. Quest'ultimo rappresenta la callback che verrà invocata (ed eseguita sullo UI thread) appena il worker-thread avrà terminato l'invocazione del Web Service ed avrà ottenuto il SOAP di risposta.

Web Service Client Android - 1

Intro

Partiamo subito da una considerazione: quando le cose le facciamo noi...c'è più soddisfazione :-). Nel senso che in giro ci sono varie librerie per implementare un client Web Service che giri su Android, ma spesso tali librerie danno un pò di problemi e il codice che viene presentato non è mai del tutto chiaro o completo. In questa serie di post, vogliamo fornire una spiegazione esaustiva del meccanismo di implementazione di un service client Android corredando il tutto con codice sorgente scaricabile e funzionante.

Northwind Web Service

Veniamo prima di tutto alla parte server. Ho implementato un Web Service (che è disponibile anche da un indirizzo web pubblico) che si basa sul DB Northwind in esecuzione sul mio SQL Server e che espone una serie di metodi abbastanza significativi che vi espongo in questa figura:  

Vediamo per esempio "GetAllEmployees" che restituisce una collection di oggetti di tipo Employee (in realtà ho costruito delle entities più semplici per rendere più agevole l'elaborazione lato client. Infatti il nostro metodo restituirà una lista di LightEmployee. Altro metodo significativo è "GetOrderByIDEmployee" che restituisce una serie di LightOrder a seguito di un parametro di input di tipo intero. Infine "GetAllCategories" che restituisce una lista di LightCategory. Tale ultima entity contiene un campo string che rappresenta un base64 relativo ad un'immagine, così vediamo come si ricostruiscono le immagini su un Android ListView.

Infine ho sostituito il namespace all'interno del SOAP per rendere univoci i nomi dei metodi. Vediamo un esempio di transazione request-response a seguito dell'invocazione del metodo "GetAllEmployees":

 

La figura sopra rappresenta come noto la HttpRequest composta dalla request-line (POST /Services....), alcuni headers (Host, Content-Type,....SOAPAction) e il body contenente il SOAP XML. Da sottolineare tra gli headers "SOAPAction" il cui valore comprende il nome del metodo che vogliamo invocare (GetAllEmployees) preceduto dal namespace che abbiamo deciso di utilizzare. Due parole su tale namespace. In XML i namespace servono per rendere univoci i nomi dei tag. Si usano quindi dei nomi di dominio semplicemente perchè sono delle stringhe che, in quanto nomi appunto di dominio, sono di per sè univoche. E' chiaro quindi che il mitico "tempuri.org" (il namespace di default di MS Web Service) viene sostituito nel mio caso con "http://sandrovecchiarelli.com/Services/SVNorthwind".

Vediamo invece la Http-Response: 

Qui vediamo la struttura della entity LightEmployee contenente campi stringa, Data ed interi. Il valore di ritorno è una lista di tali entità che verrà ricostruita dalla parte di Android effettuando un parsing del SOAP XML.

Benvenuti!

 

Blog sweet blog

Questo blog vuole essere uno spazio in cui un "developer" vuole condividere tutte le proprie 'conquiste' avute sul campo nel risolvere alcune problematiche spinose riguardanti molte delle tecnologie più interessanti che ruotano intorno al mondo embedded e non solo. Vi saranno molte sezioni riguardanti tecnologia Microsoft, ma anche Android, iOS, Google, Java e tutto quello che per piacere...o per dovere :-) sono costretto ad affrontare. Qualunque sia la tecnologia affrontata, cercherò sempre di rendere il più facile possibile la comprensione degli argomenti e corredare il post con codice sorgente testato e funzionante.....stay tuned 

Calendar

<<  June 2013  >>
MoTuWeThFrSaSu
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

View posts in large calendar

Page List

RecentComments

None