【问题标题】:Saving Logcat to a text file in Android Device将 Logcat 保存到 Android 设备中的文本文件
【发布时间】:2013-10-24 12:16:01
【问题描述】:

我在 android 设备上运行应用程序时发现了一些崩溃,但没有在模拟器中显示。所以我需要将 Logcat 保存在我设备内存或 SD 卡中的文本文件中。你能建议我这样做的好方法吗?

【问题讨论】:

    标签: java android eclipse logcat android-sdcard


    【解决方案1】:

    在应用的开头使用 Application 类。这允许正确的文件和日志处理。

    下面的代码在以下位置创建一个日志文件:

    /ExternalStorage/MyPersonalAppFolder/logs/logcat_XXX.txt
    

    XXX 是以毫秒为单位的当前时间。每次运行应用时,都会创建一个新的 logcat_XXX.txt 文件。

    public class MyPersonalApp extends Application {
    
        /**
         * Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created.
         */
        public void onCreate() {
            super.onCreate();
    
            if ( isExternalStorageWritable() ) {
    
                File appDirectory = new File( Environment.getExternalStorageDirectory() + "/MyPersonalAppFolder" );
                File logDirectory = new File( appDirectory + "/logs" );
                File logFile = new File( logDirectory, "logcat_" + System.currentTimeMillis() + ".txt" );
    
                // create app folder
                if ( !appDirectory.exists() ) {
                    appDirectory.mkdir();
                }
    
                // create log folder
                if ( !logDirectory.exists() ) {
                    logDirectory.mkdir();
                }
    
                // clear the previous logcat and then write the new one to the file
                try {
                    Process process = Runtime.getRuntime().exec("logcat -c");
                    process = Runtime.getRuntime().exec("logcat -f " + logFile);
                } catch ( IOException e ) {
                    e.printStackTrace();
                }
    
            } else if ( isExternalStorageReadable() ) {
                // only readable
            } else {
                // not accessible
            }
        }
    
        /* Checks if external storage is available for read and write */
        public boolean isExternalStorageWritable() {
            String state = Environment.getExternalStorageState();
            if ( Environment.MEDIA_MOUNTED.equals( state ) ) {
                return true;
            }
            return false;
        }
    
        /* Checks if external storage is available to at least read */
        public boolean isExternalStorageReadable() {
            String state = Environment.getExternalStorageState();
            if ( Environment.MEDIA_MOUNTED.equals( state ) ||
                    Environment.MEDIA_MOUNTED_READ_ONLY.equals( state ) ) {
                return true;
            }
            return false;
        }
    }
    

    您的 .manifest 文件中需要您的应用程序类的正确权限和名称:

    <uses-permission android:name="android.permission.READ_LOGS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    
    <application
        android:name=".MyPersonalApp"
        ... >
    

    编辑:

    如果您只想保存一些特定活动的日志..

    替换:

    process = Runtime.getRuntime().exec("logcat -f " + logFile);
    

    与:

    process = Runtime.getRuntime().exec( "logcat -f " + logFile + " *:S MyActivity:D MyActivity2:D");
    

    【讨论】:

    • 这是最好最完整的答案。
    • 螺母你如何阻止 logcat 写入?还是在调用 onDestroy() 时停止?
    • 此代码特定于您的应用程序。只要您的应用程序正在运行,它就会写入日志。
    • @HeisenBerg 感谢您的回答。我将此添加到我现有的旧应用程序(其主类扩展了 Activity 而不是 Application 类)并注意到至少在它创建重叠日志时,即一个旧的继续运行并创建了一个新的。有没有简单的方法来解决这个问题?
    • 使用标志-d 转储日志而不是连续流式传输。
    【解决方案2】:
    adb shell logcat -t 500 > D:\logcat_output.txt
    

    进入您的终端/命令提示符并导航到其中包含 adb 的文件夹,如果它尚未添加到您的环境变量中并粘贴此命令。

    t 是你需要查看的行数

    D:\logcat_output.txt 是存储 logcat 的位置。

    【讨论】:

    • 当我的电脑没有连接到我的设备时,你能提供一个解决方案来将文件写入我的设备吗..?
    • 我不太明白你的问题,当你没有连接到电脑时,你将如何访问android调试桥?
    • @smophos - 发帖人想要开始这个,断开电缆,让它继续录制。
    • 我发现这个答案居然被问题的作者接受了!
    【解决方案3】:

    在你的类中使用 -f 选项和 logcat:

    Runtime.getRuntime().exec("logcat -f" + " /sdcard/Logcat.txt");
    

    这会将日志转储到文件存储设备。

    请注意,路径“/sdcard/”可能不适用于所有设备。你应该使用standard APIs to access the external storage

    【讨论】:

    【解决方案4】:

    由于我还不能发表评论,所以我会发布这个作为答案

    我按照@HeisenBerg 说的做了,对我来说工作得很好,但是因为从 android 6.0 开始我们必须在运行时 ask for permission,所以我必须添加以下内容:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if(checkSelfPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
        }
    }
    

    然后调用

    process = Runtime.getRuntime().exec("logcat -f " + logFile);
    

    仅在回调onRequestPermissionsResult

    【讨论】:

      【解决方案5】:

      显然 android.permission.READ_LOGS 仅授予最新版本的 Android 系统应用。

      【讨论】:

      • 坏消息以及关于如何将日志写入文件的任何建议?
      【解决方案6】:

      添加清单权限:

      uses-permission android:name="android.permission.READ_LOGS" 
      
      
      private static final String COMMAND = "logcat -d -v time";
      
      
      public static void fetch(OutputStream out, boolean close) throws IOException {
          byte[] log = new byte[1024 * 2];
          InputStream in = null;
          try {
              Process proc = Runtime.getRuntime().exec(COMMAND);
              in = proc.getInputStream();
              int read = in.read(log);
              while (-1 != read) {
                  out.write(log, 0, read);
                  read = in.read(log);
              }
          }
          finally {
              if (null != in) {
                  try {
                      in.close();
                  }
                  catch (IOException e) {
                      // ignore
                  }
              }
      
              if (null != out) {
                  try {
                      out.flush();
                      if (close)
                          out.close();
                  }
                  catch (IOException e) {
                      // ignore
                  }
              }
          }
      }
      
      public static void fetch(File file) throws IOException {
          FileOutputStream fos = new FileOutputStream(file);
          fetch(fos, true);
      }
      

      【讨论】:

      • 如何将日志连续写入某个文件??我猜这段代码会写日志,直到调用这段代码。
      • 上面的代码只是日志在某个时间点的快照。如果您想连续写入日志,请使用带有 FileLogger 的 Java 日志记录并写入。
      【解决方案7】:

      如果您只需要保存 logcat(无需编码),您可以使用来自 Google Play 的 aLogrecaLogcat 应用程序。

      Google Play 商店:aLogcat & aLogrec

      【讨论】:

      • 从 Android Jelly Bean 开始,如果不是系统应用,一个应用无法读取另一个应用的日志。
      【解决方案8】:

      我将 Drunken Daddy's answer 调整为不需要权限并将其迁移到 Kotlin。

      在应用的开头使用 Application 类。这允许正确的文件和日志处理。

      下面的代码在以下位置创建一个日志文件:

      /Android/data/com.your.app/files/logs/logcat_XXX.txt
      

      XXX 是以毫秒为单位的当前时间。每次运行应用时,都会创建一个新的 logcat_XXX.txt 文件。

      import android.app.Application
      import java.io.File
      import java.io.IOException
      
      class MyApplication : Application() {
      
          override fun onCreate() {
              super.onCreate()
      
              getExternalFilesDir(null)?.let { publicAppDirectory -> // getExternalFilesDir don't need storage permission
                  val logDirectory = File("${publicAppDirectory.absolutePath}/logs")
                  if (!logDirectory.exists()) {
                      logDirectory.mkdir()
                  }
      
                  val logFile = File(logDirectory, "logcat_" + System.currentTimeMillis() + ".txt")
                  // clear the previous logcat and then write the new one to the file
                  try {
                      Runtime.getRuntime().exec("logcat -c")
                      Runtime.getRuntime().exec("logcat -f $logFile")
                  } catch (e: IOException) {
                      e.printStackTrace()
                  }
              }
          }
      }
      

      在 AndroidManifest.xml 中设置应用程序:

      <application
          android:name=".MyApplication"
          ... >
      

      【讨论】:

        【解决方案9】:

        Drunken Daddy 的回答很完美。不过我想补充一下,

        Environment.getExternalStorageDirectory()
        

        在 API 级别 29 中已弃用,Android Studio 不会给您任何警告。相反,您需要use

        context.getExternalFilesDir(null);
        

        返回

        /storage/emulated/0/Android/data/com.domain.myapp/files
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-12-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-01-06
          • 1970-01-01
          • 2012-12-26
          相关资源
          最近更新 更多