Dopo aver trattato l'invio e la ricezione degli SMS, possiamo dedicarci all'altra “metà del cielo” in fatto di telefonia: le chiamate. In questo capitolo, non affronteremo ancora l'inoltro e la gestione delle chiamate in arrivo, ma discuteremo l'utilizzo dell'elenco storico delle telefonate inoltrate, ricevute e perse.
I ContentProvider
Come viene gestito questo insieme di informazioni in Android? La discussione che segue si basa su concetti di persistenza già trattati, ed è emblematica in quanto questo tipo di gestione viene adottato anche per altre tipologie di informazioni.
Abbiamo conosciuto l'utilizzo di Sqlite come database naturale per Android e successivamente abbiamo apprezzato le particolarità dei ContentProvider come sistema per condividere dati nel sistema. Inoltre si era già detto che Android fa uso di ContentProvider per gestire l'inserimento e la fruizione di insiemi di dati come i contatti, il calendario o il MediaStore.
Anche i dati delle chiamate vengono fruiti mediante un ContentProvider, ovvero CallLog.
Come funziona CallLog
Come abbiamo già sperimentato, quando ci si vuole interfacciare con un ContentProvider di sistema, il principale problema è imparare a conoscerne la struttura, studiarne le classi e gli Uri disponibili. La buona notizia è che questo è praticamente l'unico problema, perchè l'interfacciamento con i ContentProvider avviene sempre alla stessa maniera.
L'Uri di riferimento – l'indirizzo cui fa capo questo sottosistema informativo – è CallLog.Call.CONTENT_URI. Quindi per recuperare un elenco delle chiamate è sufficiente eseguire questa richiesta:
Cursor crs=getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, null);
Il Cursor ottenuto conterrà moltissimi record, ognuno dei quali si riferisce ad una chiamata effettuata, ricevuta o persa. Gli aspetti che prenderemo in considerazione sono identificati dai seguenti campi:
- CallLog.Calls.NUMBER: il numero di telefono;
- CallLog.Calls.TYPE: il tipo di telefonata (inoltrata, ricevuta o persa). I possibili valori sono
costanti: CallLog.Calls.OUTGOING_TYPE, CallLog.Calls.INCOMING_TYPE e CallLog.Calls.MISSED_TYPE; - CallLog.Calls.DATE: informazione temporale.
Nell'esempio che vedremo, ogni record elaborato sarà mostrato in un layout a tre colonne (file: res/layout/callrow.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:maxLines="10"
android:id="@+id/numero" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="@+id/tipo" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:id="@+id/dataora" />
</LinearLayout>
Per il resto, l'esempio inserisce i dati raccolti all'interno di una ListActivity. Viene utilizzato un CursorAdapter, componente già visto, preparato appositamente per agganciare i risultati di una query al layout:
public class MainActivity extends ListActivity
{
private CursorAdapter adapter=null;
private SimpleDateFormat simple=new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Cursor crs=getContentResolver().query(CallLog.Calls.CONTENT_URI, null, null, null, null);
adapter=new CursorAdapter(this,crs,0)
{
@Override
public View newView(Context c, Cursor crs, ViewGroup vg)
{
View v=LayoutInflater.from(c).inflate(R.layout.callrow, null);
return v;
}
@Override
public void bindView(View v, Context ctx, Cursor crs)
{
TextView numero=(TextView) v.findViewById(R.id.numero);
numero.setText(crs.getString(crs.getColumnIndex(CallLog.Calls.NUMBER)));
TextView tipo=(TextView) v.findViewById(R.id.tipo);
switch(crs.getInt(crs.getColumnIndex(CallLog.Calls.TYPE)))
{
case CallLog.Calls.OUTGOING_TYPE:
tipo.setText("OUT");
break;
case CallLog.Calls.INCOMING_TYPE:
tipo.setText("IN");
break;
case CallLog.Calls.MISSED_TYPE:
tipo.setText("MISSED");
break;
}
TextView dataora=(TextView) v.findViewById(R.id.dataora);
String data=simple.format(new Date(crs.getLong(crs.getColumnIndex(CallLog.Calls.DATE))));
dataora.setText(data);
}
};
setListAdapter(adapter);
}
}
Il risultato prodotto, mostrato nell'immagine seguente, è esattamente ciò che ci aspettavamo: l'elenco storico delle chiamate.