Servizi REST su Android

13 aprile 2016

Nella lezione precedente, sono state introdotte le basi della libreria Volley, tramite un esempio che mostrava come ottenere un testo da una sorgente remota. Esistono servizi di rete più complessi, e REST è uno dei modelli di scambio dati più diffusi: per questo motivo, in questa lezione vedremo come interagire con servizi REST da Android, utilizzando Volley.

I fondamenti di REST

Molto spesso i servizi web gestiscono database, e le nostre app potrebbero aver bisogno di interagire con questi. In linea di massima, potremo dovere effettuare quattro tipi di operazioni sui dati: creazione, lettura, modifica e cancellazione. Il pattern REST, sfruttando ciò che il protocollo HTTP mette già a disposizione, permette proprio di effettuare tali operazioni da remoto. Un servizio REST si baserà per lo più sull’inoltro di richieste nelle quali si specificheranno almeno tre tipi di elementi:

  • un URL, che rappresenta la risorsa cui dovremo accedere. Il manutentore del servizio predisporrà quindi una serie di URL da contattare;
  • un metodo HTTP che indicherà l’operazione da svolgere sui dati, da scegliere tipicamente tra GET (lettura), POST (inserimento), PUT (modifica) e DELETE (cancellazione). Non tutti gli URL saranno raggiungibili da ogni metodo: anche questo però lo deciderà il gestore del servizio;
  • il corpo delle richieste conterrà dei dati che possono essere espressi in qualunque formato, ma uno dei più utilizzati è JSON, proveniente dal mondo Javascript.
    Il codice seguente mostra un oggetto JSON di esempio, in cui sono definite le tre proprietà nome, cognome ed eta:
    {
    	"nome":"Paolo",
    	"cognome":"Rossi",
    	"eta":35
    }
    
    Inoltre, una sequenza di oggetti JSON separati da virgole e racchiusi tra parentesi quadre costituisce un array JSON:
    [
    {
    	"nome":"Paolo",
    	"cognome":"Rossi",
    	"eta":35
    },
    {
    	"nome":"Enrico",
    	"cognome":"Gialli",
    	"eta": 28
    }
    ]
    

Android dispone già di classi Java per gestire oggetti ed array JSON, rispettivamente JSONObject e JSONArray. La prima permette di gestire le proprietà di un oggetto in modo simile ad una struttura dati di tipo mappa, mentre la seconda rende un array fruibile in un ciclo con i metodi length e getJSONObject.

Servizio REST di prova

Proviamo adesso ad interagire con un servizio REST di esempio: http://jsonplaceholder.typicode.com. Si tratta di API di test, che ricevono richieste per qualsiasi tipo di metodo, eventualmente corredate da oggetti JSON, e restituiscono dei risultati.

Interagiremo con questo servizio in due modi:

  • con una richiesta di tipo GET all’URL http://jsonplaceholder.typicode.com/posts, che restituirà un array di cento oggetti JSON;
  • con una richiesta di tipo POST sempre all’URL http://jsonplaceholder.typicode.com/posts, a cui invieremo un oggetto e ne riceveremo uno identico con l’aggiunta però di un campo id (che dimostrerebbe l’avvenuto inserimento in un database del server).

Volley fornisce due metodi pensati per le richieste basate su oggetti JSON: JSONArrayRequest e JSONObjectRequest. Il primo richiede solo un URL da contattare ed i due listener di successo ed errore. Di default, tale richiesta sarà effettuata con il metodo GET ed il risultato ottenuto sarà un JSONArray. Il secondo metodo permette di specificare il metodo HTTP (indicato tramite apposite costanti definite nella classe), un URL, un oggetto JSON contenente informazioni (opzionale) ed i due soliti listener. Il risultato restituito sarà un JSONObject.

L’esempio

Innanzitutto, dovremo inserire la permission INTERNET nel file AndroidManifest.xml (al di fuori del nodo application) per consentire l’accesso alla rete:

<uses-permission android:name="android.permission.INTERNET"/>

Inoltre useremo un Floating Action Button per il quale si renderà necessaria l’inclusione della seguente direttiva tra le dipendenze del file build.gradle del modulo app:

dependencies {
	...
	...
	compile 'com.android.support:design:23.1.0'
}

Il layout avrà il seguente aspetto:

Figura 1. Layout dell’app (click per ingrandire)

Layout dell'app

Il codice che lo realizza (file: /res/layout/activity_main.xml) è questo:

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/parentLayout">

    <ListView
        android:layout_width="match_parent" android:layout_height="match_parent"
        android:id="@+id/listview"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_gravity="end|bottom"
        app:backgroundTint="#ff6600"
        android:src="@android:drawable/ic_input_add"
        android:layout_margin="16dp"
        android:clickable="true"/>

</android.support.design.widget.CoordinatorLayout>

Ciò che vedremo apparire nella ListView sono dati fasulli forniti come array di oggetti JSON, simulando degli articoli. Alla pressione del pulsante flottante si apre una finestra di dialogo tramite la quale potremo inserire titolo e descrizione di un articolo che invieremo al servizio REST.

Figura 2. Finestra di dialogo (click per ingrandire)

Finestra di dialogo

L’inserimento tramite metodo HTTP POST sarà finto, ma restituirà un oggetto JSON con un codice id pari a 101, che mostreremo nella SnackBar:

Figura 3. Risultato nella SnackBar (click per ingrandire)

Risultato nella SnackBar

Per usare Volley istanzieremo la coda delle richieste e avvieremo subito una JsonArrayRequest che richiederà l’elenco degli articoli disponibili. Nel metodo onCreate è anche presente l’inizializzazione del Floating Action Button che dopo la chiusura della finestra di dialogo inoltrerà una richiesta in POST, questa volta di tipo JsonObjectRequest:

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        /*
                OMISSIS: inizializzazione layout e adapter
	*/
        mRequestQueue= Volley.newRequestQueue(this);

        JsonArrayRequest request=new JsonArrayRequest(REMOTE_ADDR, getListener,errorListener);
        mRequestQueue.add(request);

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final AlertDialog.Builder dialog=new AlertDialog.Builder(MainActivity.this);
                dialog.setTitle("Nuovo inserimento");
                final View v=getLayoutInflater().inflate(R.layout.insert, null);
                dialog.setView(v);
                dialog.setPositiveButton("Salva", new Dialog.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface d, int which) {
                        TextView txt_title= (TextView) v.findViewById(R.id.title);
                        TextView txt_body= (TextView) v.findViewById(R.id.body);
                        JSONObject nuovo=new JSONObject();
                        try {
                            nuovo.put("title", txt_title.getText());
                            nuovo.put("body", txt_body.getText());
                        } catch (JSONException e) {
                        }
                        JsonObjectRequest request=new JsonObjectRequest(REMOTE_ADDR, nuovo, postListener, errorListener);
                        mRequestQueue.add(request);
                        d.dismiss();
                    }
                });
                dialog.show();
            }
        });

    }

Le richieste avranno il medesimo ErrorListener che non farà altro che mostrare un Toast di avviso:

private Response.ErrorListener errorListener=new Response.ErrorListener()
    {
        @Override
        public void onErrorResponse(VolleyError err)
        {
            Toast.makeText(MainActivity.this, "Errore di rete", Toast.LENGTH_SHORT).show();
        }
    };

I listener di successo saranno invece diversi:

  private Response.Listener<JSONArray> getListener = new Response.Listener<JSONArray>()
    {
        @Override
        public void onResponse(JSONArray response) {

            for (int i=0; i<response.length(); i++)
            {
                try {
                    JSONObject j=response.getJSONObject(i);
                    adapter.add(j.getString("title"));
                }
                catch (JSONException e) {
                }
            }
        }

    };

    private Response.Listener<JSONObject> postListener= new Response.Listener<JSONObject>()
    {
        @Override
        public void onResponse(JSONObject response) {

            try {
                String id=response.getString("id");
                Snackbar.make(findViewById(R.id.parentLayout), "Elemento registrato con id "+id, Snackbar.LENGTH_LONG).show();
            } catch (JSONException e) {
            }
        }
	};

Il primo listener – in risposta alla GET che ottiene la lista di articoli – itererà lungo tutto l’array dei risultati ed aggiungerà i titoli così ottenuti all’adapter. Il secondo, in risposta all’inserimento fasullo, restituirà tramite la SnackBar il codice rinvenuto: sempre pari a 101.

Tutte le lezioni

1 ... 35 36 37 ... 81

Se vuoi aggiornamenti su Servizi REST su Android inserisci la tua e-mail nel box qui sotto:
Tags:
 
X
Se vuoi aggiornamenti su Servizi REST su Android

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy