DisclaimerQuesto post fonda ufficialmente il
Gruppo AndDev.it LOGTFO (Logcat or GTFO) di cui allego alla fine del post il manifesto (che ho copiato da Ricky`).
Invito
tutti gli utenti del forum a leggere questo post.
La comprensione di questo post richiede almeno un'ora del tuo tempo una tantum ma che ti farà risparmiare giorni interi nello sviluppo del software, tempo a tutte le altre persone che frequentano questo forum e tanti post inutili o incompleti.
Appena un membro del
Gruppo AndDev.it LOGTFO legge un post con problematiche risolvibili in questo post (come ad esempio: post senza logcat, domande tipo "cosa è/dove si trova il logcat", ecc..." ha il seguente compito da seguire:
- Se qualcun'altro non lo ha già fatto, rispondere con soltanto il link a questo post (guarda il formato dei Link TFO proposti nell'apposito paragrafo);
- Ignorare tutte le richieste di aiuto dell'autore fino a quando non renderà conforme il suo topic a questo post.
Per fare parte del
Gruppo AndDev.it LOGTFO ti basta
leggere, comprendere e rispettare questo post.
Cosa è ed a cosa serve il LogcatIl termine
Log indica
la registrazione cronologica delle operazioni man mano che vengono eseguite (
Wikipedia).
Il termine
Cat indica
un comando dei sistemi operativi Unix e Unix-like che che legge i file che gli sono specificati come parametri (o lo standard input) e produce sullo standard output la concatenazione del loro contenuto (
Wikipedia).
I due termini uniti formano
Logcat, che indica quindi
il tracciamento cronologico delle operazioni con la relativa visualizzazione sullo standard output del sistema.
Facciamo un esempio banale di Logcat nel mondo reale:
Vostra madre vi chiama e vi dice "Figlio mio, questa sera abbiamo degli invitati a cena ed avrei voglia di fare la pasta al forno che a te piace tanto! Potresti passare dal market e comprare gli anelletti di pasta, la passata di pomodoro e la mozzarella. Grazie 1000!";
Perfetto, tu prendi un foglio di carta e scrivi:
Spesa
Anelletti
Passata pomodoro
Mozzarella
Ovvero, da tutte le informazioni che ti ha dato tua madre (invitati a cena, il fatto che lei sappia che a te piace la pasta al forno, ecc...), tu stai salvando soltanto alcune informazioni che per te sono importanti (Anelletti, Passata pomodoro, Mozzarella) e li stai raggruppando logicamente sotto un nome (Spesa).
Appena arrivi al market ti basta controllare la tua lista per sapere cosa acquistare!
Complimenti, hai fatto un ottimo logcat: tutte le informazioni importanti sono state scritte in ordine cronologico sul tuo pezzo di carta e raggruppate sotto il nome Spesa!
Un altro esempio più vicino al mondo smartphone è il registro delle chiamate! Tutte le chiamate sono loggate in ordine cronologico e visualizzate sullo schermo raggruppate secondo il tipo di chiamata (tutte, in uscita, in entrata).
Ti basta consultare il registro delle chiamate per sapere chi ti ha chiamato (o chi hai chiamato) e a che ora.
In generale, quindi, il logcat non è altro che un insieme di informazioni che ci aiutano a ricordare o tracciare eventi nel passato.
Ad ogni informazione può essere associato un livello (o meglio filtro), in modo da organizzare in modo gerarchico le informazioni. In particolare i livelli sono i seguenti:
- V — Verbose (lowest priority)
- D — Debug
- I — Info
- W — Warning
- E — Error
- F — Fatal
- S — Silent (highest priority, on which nothing is ever printed)
Quando effettuo il log di una informazione devo quindi anche associare il
livello di log dell'informazione stessa. E' molto importante assegnare il giusto livello all'informazione per rendere il logcat finale il più leggibile possibile. Nei prossimi paragrafi spiegherò meglio come usare questi livelli durante il log.
N.B.: sul Framework Android non è possibile loggare a livello Fatal. Questo livello è infatti riservato al sistema.
Visualizzare e scrivere il LogcatPer visualizzare il logcat prima di tutto dovete avere un dispositivo connesso o un emulatore funzionante, dopodiché avete due possibilità:
1. Da terminale del tuo sistema operativo (controlla il path di installazione dell'sdk):
cd C:\android-sdk-windows\platform-tools
adb logcat2. Direttamente da eclipse:
Menu Windows -> Show View -> Other... -> Android -> LogCatQuello che vedrete è il LogCat del dispositivo collegato via usb o dell'emulatore.
Per rendere più semplice la spiegazione ho creato un piccolo progetto Android che genera dei log. Scaricate il progetto
Tutorial Logcat allegato al post, caricatelo su Eclipse e fatelo partire (per icona del progetto bisogna ringraziare bradipao).
Per scrivere sul logcat, inserite una frase nell'area di testo, premete il tasto "Log" e decidete il livello di logging.
Ad esempio io ho loggato queste frasi:
- Ciao a tutti (livello info)
- io sono MarcoDuff (livello verbose)
- questo è il tutorial del LogCat (livello debug)
Guardando il LogCat sul terminale o su eclipse mi ritrovo (potrebbero anche esserci altri messaggi di altre applicazioni nel mezzo, per il momento ignorateli):
I/TutorialLogcat( 713): Ciao a tutti
V/TutorialLogcat( 713): io sono MarcoDuff
D/TutorialLogcat( 713): questo è il tutorial del LogCatLa prima lettera della riga del debug indica il livello (I per info, V per verbose e D per debug), poi abbiamo il TAG associato (quello che negli esempi di sopra era la "Spesa" o le chiamate "In ingresso" o "in uscita", un numero che possiamo ignorare (indica il thread) ed il messaggio loggato.
Molto importante è anche notare che il log viene scritto in modo cronologico, ovvero seguendo esattamente l'ordine con cui sono state inviate le richieste di log.
Vediamo adesso quale codice serve per creare un log. Niente di più semplice! Basta usare la classe
Log ed i suoi metodi statici v, d, i, w, e (al solito, il nome del metodo indica il livello di debug: v per verbose, d per debug, ecc...).
Tutti i metodi di debug accettano due parametri: il Tag e il messaggio da loggare.
Per intenderci, il logcat di sopra è stato fatto richiamando questi metodi:
Log.i("TutorialLogcat","Ciao a tutti");
Log.v("TutorialLogcat","io sono MarcoDuff");
Log.d("TutorialLogcat","questo è il tutorial del LogCat");Tutti i metodi hanno due overload, uno che al posto del messaggio accetta un Throwable ed un'altro che in aggiunta ha un Throwable. Come facilmente intuibile, questi metodi sono molto utili in caso di eccezioni (il codice del progetto contiene anche un esempio su come gestire e loggare in modo corretto un errore, guardate il metodo
onNumberFormatExceptionClick)!
Filtrare il LogcatMolto spesso siamo interessati soltanto ad alcune porzioni di logcat, quindi è molto importante capire come filtrare i messaggi in esso contenuto. Gli esempi si riferiscono all'uso del logcat da terminale, per eclipse i comandi sono simili.
Alla stringa di comando adb logcat possiamo concatenare vari filtri. In particolare l'espressione dei filtri è la seguente:
<TAG>:<LIVELLO>esiste un TAG particolare che è * ed indica tutto. Facciamo degli esempi di comandi:
Comando per vedere i log solo a partire dal livello Error per tutti i tag possibili:
adb logcat *:eComando per vedere i log solo a partire dal livello Debug per il tag TutorialLogcat e a partire dal livello Warnig per tutti gli altri:
adb logcat TutorialLogcat:d *:wComando per vedere i log solo a partire dal livello Verbose per il tag TutorialLogcat e niente da altri tag:
adb logcat TutorialLogcat:v *:sFaccio partire adesso quattro comandi sul nostro caso esempio:
Caso 1
C:\>adb logcat TutorialLogcat:v *:s
I/TutorialLogcat( 713): Ciao a tutti
V/TutorialLogcat( 713): io sono MarcoDuff
D/TutorialLogcat( 713): questo è il tutorial del LogCatCaso 2
C:\>adb logcat TutorialLogcat:d *:s
I/TutorialLogcat( 713): Ciao a tutti
D/TutorialLogcat( 713): questo è il tutorial del LogCatCaso 3
C:\>adb logcat TutorialLogcat:i *:s
I/TutorialLogcat( 713): Ciao a tuttiCaso 4
C:\>adb logcat TutorialLogcat:w *:sBisogna notare che quando si indica un livello, quello indica il
livello di partenza di visualizzazione. Se indico il livello D (Caso 2) verranno visualizzati tutte le informazioni associate al livello D e tutte le altre con un una priorità più alta (I, W, E, F). Ecco perché nel caso 2 oltre ad essere visualizzata la frase "questo è il tutorial del LogCat" (livello D) viene visualizzata anche la frase "Ciao a tutti) (livello I) e non viene visualizzata la scritta "io sono MarcoDuff" (livello V).
Capire gli errori dal LogcatLo scopo principe del LogCat è proprio questo: capire cosa ha fatto andare in crash la nostra applicazione.
Premiamo il tasto "Genera NullPointerException" sull'applicazione e... Yikes! (cit. Monkey Island) la nostra cara applicazione va in Force Close. Cosa avrà causato il crash???
Guardando tutti gli errori del logcat tramite comando
C:\>adb logcat *:wnotiamo alla fine:
E/AndroidRuntime( 1895): FATAL EXCEPTION: main
E/AndroidRuntime( 1895): java.lang.IllegalStateException: Could not execute method of the activity
E/AndroidRuntime( 1895): at android.view.View$1.onClick(View.java:2072)
E/AndroidRuntime( 1895): at android.view.View.performClick(View.java:2408)
E/AndroidRuntime( 1895): at android.view.View$PerformClick.run(View.java:8816)
E/AndroidRuntime( 1895): at android.os.Handler.handleCallback(Handler.java:587)
E/AndroidRuntime( 1895): at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime( 1895): at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 1895): at android.app.ActivityThread.main(ActivityThread.java:4627)
E/AndroidRuntime( 1895): at java.lang.reflect.Method.invokeNative(NativeMethod)
E/AndroidRuntime( 1895): at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime( 1895): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
E/AndroidRuntime( 1895): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
E/AndroidRuntime( 1895): at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime( 1895): Caused by: java.lang.reflect.InvocationTargetException
E/AndroidRuntime( 1895): at com.marcoduff.tutorial.logcat.HomeActivity.onNullPointerExceptionClick(HomeActivity.java:59)
E/AndroidRuntime( 1895): at java.lang.reflect.Method.invokeNative(NativeMethod)
E/AndroidRuntime( 1895): at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime( 1895): at android.view.View$1.onClick(View.java:2067)
E/AndroidRuntime( 1895): ... 11 more
E/AndroidRuntime( 1895): Caused by: java.lang.NullPointerException
E/AndroidRuntime( 1895): ... 15 moreLeggendo lo stacktrace ci rendiamo conto che...
il problema è un
java.lang.NullPointerException (lo capiamo dalla riga
E/AndroidRuntime( 1895): Caused by: java.lang.NullPointerException)
il problema è avvenuto alla riga 59 del file HomeActivity.java mentre veniva eseguito il metodo onNullPointerExceptionClick (lo capiamo dalla riga
E/AndroidRuntime( 1895): at com.marcoduff.tutorial.logcat.HomeActivity.onNullPointerExceptionClick(HomeActivity.java:59))
Che nel mio codice equivale al comando
nullObject.toString();:
public void onNullPointerExceptionClick(View view) {
Object nullObject = null;
nullObject.toString();
}Magico vero?
Adesso non avete più scuse:
dovete conoscere il LogCat!
That's all!
Formato dei Link TFO propostiLogCat, o lo conosci o ti uccido!
Hasta el LogCat siempre!
Io faccio parte del
Gruppo AndDev.it LOGTFO, tu no? Allora GTFO!
Manifesto