Logcat programmgesteuert innerhalb der Anwendung lesen

Lesezeit: 10 Minuten

Logcat programmgesteuert innerhalb der Anwendung lesen
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.

    – Benutzer1185087

    28. Dezember 2019 um 13:49 Uhr

Mit Koroutinen und dem Beamten lifecycle-livedata-ktx und lifecycle-viewmodel-ktx Bibliotheken ist es einfach so:

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

Logcat programmgesteuert innerhalb der Anwendung lesen
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.

Das Android LogCat “Handbuch”: https://developer.android.com/studio/command-line/logcat.html

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

LogCapture nextCapture = capture.getNextCapture();

Sie können die Erfassung als Zeichenfolge mit erhalten

String captureString = capture.toString();

Oder Sie können die Protokollelemente der Erfassung mit abrufen

String logItem = capture.log.get(itemNumber);

Es gibt keine genaue statische Methode, um fremde Protokollschlüssel zu erfassen, aber es gibt dennoch eine Möglichkeit

LogCapture foreignCapture = Logger.getLogCat("main", null, foreignCaptureKeyList);

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

1646253187 633 Logcat programmgesteuert innerhalb der Anwendung lesen
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

1646253187 323 Logcat programmgesteuert innerhalb der Anwendung lesen
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.

915880cookie-checkLogcat programmgesteuert innerhalb der Anwendung lesen

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy