在Android设备上将Logcat保存到文本文件

37

在 Android 设备上运行应用程序时,我发现了一些崩溃情况,这些情况在模拟器中没有显示。因此,我需要将 Logcat 保存到设备内存或 SD 卡的文本文件中。请问您有什么好的方法可以做到这一点吗?

9个回答

87

在您的应用程序开头使用一个 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");

1
这是最好的和最完整的答案。 - Bruno Morais
4
如何停止logcat的输出?或者在调用onDestroy()时会自动停止吗? - RedHat
2
这段代码是针对你的应用程序特定的。只要你的应用程序在运行,它就会写入日志。 - Drunken Daddy
1
@HeisenBerg 感谢您的回答。我将这个添加到了我的旧应用程序中(其主类扩展了 Activity 而不是 Application 类),并注意到至少一次它创建了重叠的日志,即旧的日志继续运行,而新的日志被创建。有没有简单的方法来解决这个问题? - biggvsdiccvs
2
使用标志“-d”转储日志而不是连续流式传输。 - Ryan R
显示剩余16条评论

15
adb shell logcat -t 500 > D:\logcat_output.txt

打开终端/命令提示符并导航到带有adb的文件夹,如果它还没有添加到您的环境变量中,请粘贴此命令。

t是您需要查看的行数

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


9
你能否提供一种方法,在设备未连接到计算机时将文件写入设备中? - Nithin Michael
我不太明白你的问题,当你没有连接电脑时,你打算如何访问Android调试桥? - smophos
4
@smophos - 这位张贴者希望启动录制后,拔掉电缆仍能继续录制。 - Chris Stratton
10
我发现这个答案竟然被提问者接受了,这真是令人惊讶! - Antonio
显示剩余3条评论

10

在你的类中使用logcat命令时,请使用-f选项:

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

这将把日志转储到存储设备上的文件中。

请注意,路径“/sdcard/”可能并非所有设备都可用。您应使用标准API来访问外部存储


1
这篇博客文章可能会有所帮助- http://www.journal.deviantdev.com/android-log-logcat-to-file-while-runtime/ - Gulshan

7

由于我还不能评论,所以我将其发布为答案。

我按照 @HeisenBerg 的说法操作,对我来说很好用,但自从 Android 6.0 开始,我们必须在运行时请求权限,因此我不得不添加以下内容:

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中,android.permission.READ_LOGS只授予系统应用程序。


坏消息和如何将日志写入文件的任何建议? - flankechen
@flankechen 对于你的应用程序日志,你需要使用自己的Logger类并将日志重定向到你的文件中。对于一般设备日志,请尽量联系设备制造商并询问如何启用此功能。我知道有些品牌会提供这样的功能,比如三星。 - Pablo Valdes

3
我调整了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"
    ... >

文件位置在/Android/data/目录下没有任何内容。我正在使用Android 12。 - prat

2

添加清单权限:

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);
}

如何连续将日志写入某个文件?我猜这段代码会在调用此代码之前一直写入日志。 - Shridutt Kothari
上面的代码只是某个时间点的日志快照。如果你想要持续写入日志,可以使用Java的Logging功能,并将日志写入文件中。 - d3n13d1

1
如果你只需要保存logcat(不包含你的编码),你可以使用来自Google Play的aLogrec或aLogcat应用程序。
Google Play商店:aLogcat & aLogrec

2
从Android Jelly Bean开始,一个应用程序如果不是系统应用程序,则无法读取另一个应用程序的日志。 - neteinstein

0

醉爸爸的回答非常完美。不过我想补充一点,

Environment.getExternalStorageDirectory()

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

context.getExternalFilesDir(null);

它返回

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接