Vediamo in questo articolo come creare un’app per monitorare il traffico di rete e visualizzare il tutto gramite un grafico.
I punti che andremo ad analizzare per realizzare questa app saranno i seguenti:
- Blocco dell’orientamento dello schermo per un’Activity
- Uso della classe TrafficStats per ottenere le informazioni di ricezione/trasmissione
- Uso della libreria GraphView per creare e aggiornare un grafico
- Comprensione della classe Handler per l’esecuzione di un oggetto Runnable
L’app in questione risulta essere molto semplice. Nella parte superiore 2 contatori visualizzeranno i bytes e pacchetti ricevuti e inviati dal momento in cui abbiamo avviato l’applicazione mentre nella parte sottostante queste informazioni verranno riproposte in un grafico potendo visualizzare in maniera separate bytes e pacchetti e suddividendoli ulteriormente in progressivi (overall) e attuali (live).
Contenuto
Blocco dell’orientamento dello schermo per un’Activity.
Per fare in modo che un’Activity non venga routata assieme allo schermo ma che risulti invece sempre fissa in verticale (portrait) o orizzontale (landscape) sarà sufficiente nel file AndroidManifest.xml aggiungere questo attributo nel suo tag:
[xml gutter=”off”]android:screenOrientation="portrait"[/xml]
In questo caso anche se il dispositivo verrà ruotato in qualsiasi maniera l’Activity non cambierà.
Considerazioni sul ciclo di vita di una activity.
Vale la pena di ricordare che un’Activity viene riavviata ogni qual volta la configurazione cambia. Questi cambiamenti possono essere lanciati dal sistema Android e presi in considerazione dall’applicazione. Un esempio può essere il cambio di orientamento del dispositivo o la visualizzazione/scomparsa della tastiera. In questi casi Android può pensare che le activity necessitino di diverse risorse e quindi vengono riavviate. Se nel nostro caso non avessimo bisogno di far ricreare ogni volta la nostra activity basterà aggiungere questo attributo al suo tag:
[xml gutter=”off”]android:configChanges="orientation|keyboardHidden|screenSize"[/xml]
In particolare facendo ciò, ad esempio, il metodo onCreate() non verrebbe più richiamato per gli eventi specificati ma verrebbe delegato tutto al metodo onConfigurationChanged(Configuration newConfig). E’ bene ricordare però che si sconsiglia l’uso di questo attributo in quanto tipicamente è sempre meglio gestire qualsiasi cambio di configurazione dell’Activity.
La classe TrafficStats.
La classe TrafficStats è preposta all’ottenimento di tutte le statistiche riguardanti il traffico di rete, dati ricevuti e trasmessi, suddivisi per tutte le interfacce, per il mobile e per specifici UID (ad esempio una specifica applicazione). Nel nostro caso andremo a monitorare il traffico su tutte le interfacce nel seguente modo:
[java gutter=”off”]
long rxTotalBytes = TrafficStats.getTotalRxBytes();
long rxTotalPackets = TrafficStats.getTotalRxPackets();
long txTotalBytes = TrafficStats.getTotalTxBytes();
long txTotalPackets = TrafficStats.getTotalTxPackets();
[/java]
Con il prefisso rx andremo ad ottenere i dati ricevuti mentre tx indicherà quelli trasmessi. Nel caso in cui il device non supporti le operazioni di monitoraggio verrà restituito come valore la costante UNSUPPORTED che andremo a gestire in questa maniera:
[java gutter=”off”]
if (startingRXByte == TrafficStats.UNSUPPORTED || startingTXByte == TrafficStats.UNSUPPORTED) {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setTitle("ATTENZIONE");
alert.setMessage("Il device non supporta il monitoraggio del traffico.");
alert.show();
}
[/java]
La libreria GraphView.
Per poter visualizzare e gestire un grafico ci serviremo della libreria GraphView. Come primo passo andiamo quindi a scaricarla dal sito (link nel titolo) e salvarla sul nostro PC. A questo punto dovremo fare in modo che il nostro progetto possa utilizzarla e per fare questo clicchiamo com il tasto destro e dal menu scegliamo Properties –> Java Build Path e nel tab Libraries il pulsante AddExternal Jar. Spostiamoci quindi nella directory dove abbiamo scaricato il file e diamo l’ok.
Tip
Se durante il debug o una volta lanciata l’applicazione verrà sollevata un’eccezione di ClassNotFound riguardante una classe di GraphView sarà sufficiente nel menu Java Build Path, spostarci su Order and Export, selezionare la libreria GraphView e spostarla in cima.
Ora siamo in grado di usare qualsiasi componente di questa libreria e vediamo in dettaglio come.
Creazione del grafico.
Il grafico che abbiamo scelto è di tipo LineGraphView e la mia classe derivata è questa:
[java highlight=”20,21,22″ tabsize=”4″ smarttabs=”true”]
public class TrafficGraphView extends LineGraphView {
public static final int GRAPH_MAX_DATA = 30;
/**
* Crea 2 serie per il grafico, la prima per i dati ricevuti, la seconda per i dati trasmessi.
*
* @return serie create
*/
public static GraphViewSeries[] createSeries() {
return new GraphViewSeries[] {
new GraphViewSeries("Ricevuti", new GraphViewSeriesStyle(Color.RED, 3),
new GraphViewData[] { new GraphViewData(0, 0) }),
new GraphViewSeries("Trasmessi", new GraphViewSeriesStyle(Color.GREEN, 3),
new GraphViewData[] { new GraphViewData(0, 0) }) };
}
public TrafficGraphView(Context context) {
super(context, "");
setViewPort(0, GRAPH_MAX_DATA);
setScrollable(true);
setScalable(true);
}
}
[/java]
I punti che ci interessano sono:
- linea 20 ci permette di visualizzare, nel nostro caso, solo 30 elementi nel grafico in modo tale che con lo scorrere del tempo non avremo così tanti valori da risultare incomprensibili.
- linea 21 ci consente di spostare il viewport del grafico. Per rendere l’idea possiamo pensare al viewport come ad una finestra sul grafico che ci permette, in questo caso, di vedere solo 30 valori. Appena il 31esimo valore viene aggiunto, se indicato, il viewport si “sposta” per visualizzare i valori dal secondo al 31esimo.
- linea 22 ci permette di far riscalare automaticamente gli assi del grafico.
Il metodo statico createSeries() crea automaticamente 2 serie per il grafico, una verde per i dati ricevuti e una rossa per i dati trasmessi. GraphViewSeries è la classe per creare la serie dove possiamo indicare la label e lo style, quest’ultimo attraverso la classe GraphViewSeriesStyle che ne definisce il colore e lo spessore.
Gestione delle serie.
La classe GraphView ci permettere di aggiungesre una serie usando il metodo addSeries(GraphViewSeries series), di rimuoverla con removeSeries(GraphViewSeries series) e di aggiungere dati ad una serie esistente con appendData() della classe GraphViewSeries. In particolare usando l’esempio della nostra app il codice che ci interessa è:
Rimuovere tutte le serie esistenti
[java gutter=”off”]graphView.removeAllSeries();[/java]
Aggiungere una serie ( vedi createSeries() per la creazione )
[java gutter=”off”]
graphView.addSeries(mapSeries.get(pos)[0]);
graphView.addSeries(mapSeries.get(pos)[1]);
[/java]
Aggiunta di nuovi dati ad una serie esistente
[java gutter=”off”]serie.appendData(new GraphViewData(tick, value), true, TrafficGraphView.GRAPH_MAX_DATA);[/java]
Handler ed esecuzione di un oggetto Runnable.
La classe Handler ci permette di inviare e gestire oggetti Runnable ( in questo esempio ma possono essere gestiti anche Message ) su un Thread che viene associato al momento della sua creazione. Gli usi principali di un Handler sono la schedulazione di messaggi o runnable che verranno eseguiti al loro ricevimento e mettere in coda di esecuzione un’azione che verrà eseguita da un thread diverso.
L’Handler usato nella nostra app userà il metodo postDelayed(Runnable, long) per eseguire dopo 1 secondo il runnable che aggiornerà le statistiche con i nuovi dati in questo modo:
[java gutter=”off”]trafficHandler.postDelayed(new UpdateTrafficaRunnable(this), 1000);[/java]
Ricordo come sempre che per provare questa applicazione dovrete abilitare le sorgenti sconosciute ( dal menu Impostazioni –> Sicurezza –> Sorgenti sconosciute ) dato che ho utilizzato una chiave auto generata per firmare l’applicazione. Qui di seguito troverete i link per scaricare il sorgente o per installare l’applicazione.