Logcat programmgesteuert innerhalb der Anwendung lesen
Lesezeit: 10 Minuten
David
Ich möchte Logcat-Protokolle in meiner Anwendung lesen und darauf reagieren.
Ich habe folgenden Code gefunden:
try {
Process process = Runtime.getRuntime().exec("logcat -d");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
StringBuilder log=new StringBuilder();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
log.append(line);
}
TextView tv = (TextView)findViewById(R.id.textView1);
tv.setText(log.toString());
}
catch (IOException e) {}
Dieser Code gibt tatsächlich die Logcat-Protokolle zurück, die erstellt wurden, bis die Anwendung gestartet wurde –
Aber ist es möglich, auch neue Logcat-Protokolle kontinuierlich abzuhören?
Die Option -d gibt das Protokoll aus und beendet sich. Entfernen Sie einfach die Option -d und logcat wird nicht beendet.
– Frohnzie
2. Oktober 2012 um 14:56 Uhr
Wie kann ich es löschen? – Ich muss eine bestimmte Zeile zu meiner Bewerbung finden
– David
2. Oktober 2012 um 15:52 Uhr
Kein Root erforderlich.
– Luis
13. April 2017 um 15:32 Uhr
Wenn Root nicht erforderlich ist, kann nur der Entwicklungs-Build auf sein eigenes Protokoll zugreifen? Und wo genau wird dieser Code ausgeführt? mit in der apk-Anwendung?
– Ayyappa
3. Februar 2018 um 7:39 Uhr
Ich habe einen Test versucht. Ich konnte nur die Ereignisse meines eigenen Prozesses lesen. Ich denke, Sie brauchen root, um andere Prozessereignisse zu lesen.
– Yeti99
19. Oktober 2018 um 19:14 Uhr
Sie können die Protokolle weiterlesen, indem Sie einfach das Flag “-d” in Ihrem obigen Code entfernen.
Das “-d”-Flag weist logcat an, den Protokollinhalt anzuzeigen und zu beenden. Wenn Sie das Flag entfernen, wird logcat nicht beendet und sendet weiterhin jede neu hinzugefügte Zeile.
Denken Sie nur daran, dass dies Ihre Anwendung blockieren kann, wenn es nicht richtig gestaltet ist.
viel Glück.
Wenn ich das “-d” entferne, bleibt die Anwendung hängen und ich erhalte den Dialog zum Schließen erzwingen.
– David
2. Oktober 2012 um 15:10 Uhr
Wie ich oben sagte, wäre ein sorgfältiges Anwendungsdesign erforderlich. Der obige Code muss in einem separaten Thread ausgeführt werden (um ein Blockieren der Benutzeroberfläche zu vermeiden), und da Sie die Textansicht in der Benutzeroberfläche mit Protokollinformationen aktualisieren möchten, müssen Sie einen Handler verwenden, um die Informationen an die Benutzeroberfläche zurückzusenden.
– Luis
2. Oktober 2012 um 15:29 Uhr
Hallo Luis, kannst du bitte einen Beispielcode eines separaten Threads posten?
– img.simone
28. November 2017 um 8:27 Uhr
Siehe Antwort stackoverflow.com/a/59511458/1185087. Es werden Coroutinen verwendet, die den UI-Thread nicht blockieren.
class LogCatViewModel : ViewModel() {
fun logCatOutput() = liveData(viewModelScope.coroutineContext + Dispatchers.IO) {
Runtime.getRuntime().exec("logcat -c")
Runtime.getRuntime().exec("logcat")
.inputStream
.bufferedReader()
.useLines { lines -> lines.forEach { line -> emit(line) }
}
}
}
Verwendungszweck
val logCatViewModel by viewModels<LogCatViewModel>()
logCatViewModel.logCatOutput().observe(this, Observer{ logMessage ->
logMessageTextView.append("$logMessage\n")
})
Toller Vorschlag. Ich frage mich, ob es eine Möglichkeit gibt, dies zum Laufen zu bringen WebView anstatt TextView.
– Fatih
28. Mai 2020 um 12:08 Uhr
Aber warum kann ich nicht auf Logcat einer anderen Anwendung zugreifen? Runtime.getRuntime().exec(“logcat irgendeine.andere.app”)
– Arsenius
9. Oktober 2020 um 8:44 Uhr
@Arsenius, welche Version des Android-Betriebssystems befindet sich auf Ihrem Gerät? Ab Android 5/6/7 und höher können Sie keine Informationen über andere Apps lesen, einschließlich Status und Protokolle. Es gibt also absolut keine Möglichkeit, dies zu tun, es sei denn, Sie sind gerootet.
– FEBRYAN ASA PERDANA
30. März 2021 um 13:11 Uhr
Gibt es eine Möglichkeit, dies in einem NonUI-Thread zu tun?
– Eyal Elbas
5. Mai 2021 um 8:51 Uhr
@EyalElbaz Ich glaube, diese Antwort befindet sich in einem Nicht-UI-Thread. liveData(viewModelScope.coroutineContext + Dispatchers.IO) lässt die Logcat-Codes in einem Subthread für IO-Operationen mit Coroutines in Kotlin arbeiten.
– DeXter
13. Juli 2021 um 9:45 Uhr
Sie können Ihren Logcat mit dieser Methode löschen, die ich verwende, um nach dem Schreiben von Logcat in eine Datei zu löschen, um doppelte Zeilen zu vermeiden:
public void clearLog(){
try {
Process process = new ProcessBuilder()
.command("logcat", "-c")
.redirectErrorStream(true)
.start();
} catch (IOException e) {
}
}
Ich habe gerade festgestellt, dass das Löschen des Protokolls einige Zeit dauern kann. Wenn Sie also das Protokoll löschen und es dann sofort lesen, sind einige alte Einträge möglicherweise noch nicht gelöscht. Darüber hinaus können einige neu hinzugefügte Protokolleinträge gelöscht werden, da sie hinzugefügt werden, bevor der Löschvorgang abgeschlossen ist. Es macht keinen Unterschied, selbst wenn Sie process.waitfor() aufrufen.
– Tom Rutschik
3. Juni 2020 um 0:25 Uhr
Hypersoft-Systeme
Hier ist eine schnelle Zusammenstellung/Drop-in, die zum Erfassen aller aktuellen oder aller neuen (seit einer letzten Anfrage) Protokollelemente verwendet werden kann.
Sie sollten dies ändern/erweitern, da Sie möglicherweise einen kontinuierlichen Stream anstelle einer LogCapture zurückgeben möchten.
import android.util.Log;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Stack;
/**
* Created by triston on 6/30/17.
*/
public class Logger {
// http://www.java2s.com/Tutorial/Java/0040__Data-Type/SimpleDateFormat.htm
private static final String ANDROID_LOG_TIME_FORMAT = "MM-dd kk:mm:ss.SSS";
private static SimpleDateFormat logCatDate = new SimpleDateFormat(ANDROID_LOG_TIME_FORMAT);
public static String lineEnding = "\n";
private final String logKey;
private static List<String> logKeys = new ArrayList<String>();
Logger(String tag) {
logKey = tag;
if (! logKeys.contains(tag)) logKeys.add(logKey);
}
public static class LogCapture {
private String lastLogTime = null;
public final String buffer;
public final List<String> log, keys;
LogCapture(String oLogBuffer, List<String>oLogKeys) {
this.buffer = oLogBuffer;
this.keys = oLogKeys;
this.log = new ArrayList<>();
}
private void close() {
if (isEmpty()) return;
String[] out = log.get(log.size() - 1).split(" ");
lastLogTime = (out[0]+" "+out[1]);
}
private boolean isEmpty() {
return log.size() == 0;
}
public LogCapture getNextCapture() {
LogCapture capture = getLogCat(buffer, lastLogTime, keys);
if (capture == null || capture.isEmpty()) return null;
return capture;
}
public String toString() {
StringBuilder output = new StringBuilder();
for (String data : log) {
output.append(data+lineEnding);
}
return output.toString();
}
}
/**
* Get a list of the known log keys
* @return copy only
*/
public static List<String> getLogKeys() {
return logKeys.subList(0, logKeys.size() - 1);
}
/**
* Platform: Android
* Get the logcat output in time format from a buffer for this set of static logKeys.
* @param oLogBuffer logcat buffer ring
* @return A log capture which can be used to make further captures.
*/
public static LogCapture getLogCat(String oLogBuffer) { return getLogCat(oLogBuffer, null, getLogKeys()); }
/**
* Platform: Android
* Get the logcat output in time format from a buffer for a set of log-keys; since a specified time.
* @param oLogBuffer logcat buffer ring
* @param oLogTime time at which to start capturing log data, or null for all data
* @param oLogKeys logcat tags to capture
* @return A log capture; which can be used to make further captures.
*/
public static LogCapture getLogCat(String oLogBuffer, String oLogTime, List<String> oLogKeys) {
try {
List<String>sCommand = new ArrayList<String>();
sCommand.add("logcat");
sCommand.add("-bmain");
sCommand.add("-vtime");
sCommand.add("-s");
sCommand.add("-d");
sCommand.add("-T"+oLogTime);
for (String item : oLogKeys) sCommand.add(item+":V"); // log level: ALL
sCommand.add("*:S"); // ignore logs which are not selected
Process process = new ProcessBuilder().command(sCommand).start();
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
LogCapture mLogCapture = new LogCapture(oLogBuffer, oLogKeys);
String line = "";
long lLogTime = logCatDate.parse(oLogTime).getTime();
if (lLogTime > 0) {
// Synchronize with "NO YEAR CLOCK" @ unix epoch-year: 1970
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date(oLogTime));
calendar.set(Calendar.YEAR, 1970);
Date calDate = calendar.getTime();
lLogTime = calDate.getTime();
}
while ((line = bufferedReader.readLine()) != null) {
long when = logCatDate.parse(line).getTime();
if (when > lLogTime) {
mLogCapture.log.add(line);
break; // stop checking for date matching
}
}
// continue collecting
while ((line = bufferedReader.readLine()) != null) mLogCapture.log.add(line);
mLogCapture.close();
return mLogCapture;
} catch (Exception e) {
// since this is a log reader, there is nowhere to go and nothing useful to do
return null;
}
}
/**
* "Error"
* @param e
*/
public void failure(Exception e) {
Log.e(logKey, Log.getStackTraceString(e));
}
/**
* "Error"
* @param message
* @param e
*/
public void failure(String message, Exception e) {
Log.e(logKey, message, e);
}
public void warning(String message) {
Log.w(logKey, message);
}
public void warning(String message, Exception e) {
Log.w(logKey, message, e);
}
/**
* "Information"
* @param message
*/
public void message(String message) {
Log.i(logKey, message);
}
/**
* "Debug"
* @param message a Message
*/
public void examination(String message) {
Log.d(logKey, message);
}
/**
* "Debug"
* @param message a Message
* @param e An failure
*/
public void examination(String message, Exception e) {
Log.d(logKey, message, e);
}
}
In Ihrem Projekt, das Aktivitätsprotokollierung durchführt:
Logger log = new Logger("SuperLog");
// perform logging methods
Wenn Sie alles erfassen möchten, was Sie über “Logger” protokolliert haben
LogCapture capture = Logger.getLogCat("main");
Wenn Sie hungrig werden und mehr Holzscheite essen möchten
Wenn Sie die oben genannten verwenden, können Sie auch anrufen Logger.this.nextCapture auf die ausländische Gefangennahme.
Das Flag “-c” löscht den Puffer.
-c Löscht (leert) das gesamte Protokoll und beendet sich.
wie man -c im obigen Code verwendet. Wenn etwas im Protokoll gefunden wird, möchte ich es löschen
– yuvaツ
21. April 2013 um 5:32 Uhr
yuva, tun Sie einfach: process = Runtime.getRuntime().exec(“logcat -c”); bufferedReader = new BufferedReader (new InputStreamReader (process.getInputStream()), 1024); line = bufferedReader.readLine();
– DJance
26. Mai 2014 um 20:47 Uhr
Reetpreet Brar
//CLEAR LOGS
Runtime.getRuntime().exec("logcat -c");
//LISTEN TO NEW LOGS
Process pq=Runtime.getRuntime().exec("logcat v main");
BufferedReader brq = new BufferedReader(new InputStreamReader(pq.getInputStream()));
String sq="";
while ((sq = brq.readLine()) != null)
{
//CHECK YOUR MSG HERE
if(sq.contains("send MMS with param"))
{
}
}
Ich verwende dies in meiner App und es funktioniert. Und Sie können den obigen Code in Timer Task verwenden, damit Ihr Hauptthread nicht gestoppt wird
Timer t;
this.t.schedule(new TimerTask()
{
public void run()
{
try
{
ReadMessageResponse.this.startRecord();//ABOVE METHOD HERE
}
catch (IOException ex)
{
//NEED TO CHECK SOME VARIABLE TO STOP MONITORING LOGS
System.err.println("Record Stopped");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally
{
ReadMessageResponse.this.t.cancel();
}
}
}, 0L);
}
wie man -c im obigen Code verwendet. Wenn etwas im Protokoll gefunden wird, möchte ich es löschen
– yuvaツ
21. April 2013 um 5:32 Uhr
yuva, tun Sie einfach: process = Runtime.getRuntime().exec(“logcat -c”); bufferedReader = new BufferedReader (new InputStreamReader (process.getInputStream()), 1024); line = bufferedReader.readLine();
– DJance
26. Mai 2014 um 20:47 Uhr
DeXter
Basierend auf der Antwort von @ user1185087 könnte eine einfache Lösung ohne ViewModel sein:
Starten Sie den Job in einem IO-Thread:
// Custom scope for collecting logs on IO threads.
val scope = CoroutineScope(Job() + Dispatchers.IO)
val job = scope.launch {
Runtime.getRuntime().exec("logcat -c") // Clear logs
Runtime.getRuntime().exec("logcat") // Start to capture new logs
.inputStream
.bufferedReader()
.useLines { lines ->
// Note that this forEach loop is an infinite loop until this job is cancelled.
lines.forEach { newLine ->
// Check whether this job is cancelled, since a coroutine must
// cooperate to be cancellable.
ensureActive()
// TODO: Write newLine into a file or buffer or anywhere appropriate
}
}
}
Brechen Sie den Job aus dem Haupt-Thread ab:
MainScope().launch {
// Cancel the job and wait for its completion on main thread.
job.cancelAndJoin()
job = null // May be necessary
// TODO: Anything else you may want to clean up
}
Diese Lösung sollte ausreichen, wenn Sie die neuen Protokolle Ihrer App kontinuierlich in einem Hintergrundthread sammeln möchten.
9158800cookie-checkLogcat programmgesteuert innerhalb der Anwendung lesenyes
Die Option -d gibt das Protokoll aus und beendet sich. Entfernen Sie einfach die Option -d und logcat wird nicht beendet.
– Frohnzie
2. Oktober 2012 um 14:56 Uhr
Wie kann ich es löschen? – Ich muss eine bestimmte Zeile zu meiner Bewerbung finden
– David
2. Oktober 2012 um 15:52 Uhr
Kein Root erforderlich.
– Luis
13. April 2017 um 15:32 Uhr
Wenn Root nicht erforderlich ist, kann nur der Entwicklungs-Build auf sein eigenes Protokoll zugreifen? Und wo genau wird dieser Code ausgeführt? mit in der apk-Anwendung?
– Ayyappa
3. Februar 2018 um 7:39 Uhr
Ich habe einen Test versucht. Ich konnte nur die Ereignisse meines eigenen Prozesses lesen. Ich denke, Sie brauchen root, um andere Prozessereignisse zu lesen.
– Yeti99
19. Oktober 2018 um 19:14 Uhr