35

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

4

9 回答 9

84

在应用程序的开头使用 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");
于 2016-05-31T09:16:27.557 回答
15
adb shell logcat -t 500 > D:\logcat_output.txt

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

t 是您需要查看的数行

D:\logcat_output.txt 是您的 logcat 将被存储的地方。

于 2013-10-24T12:23:58.750 回答
10

在您的课程中使用 -f 选项和 logcat:

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

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

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

于 2014-03-07T11:01:47.653 回答
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

于 2017-04-18T13:57:49.730 回答
4

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

于 2018-12-22T17:52:57.280 回答
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);
}
于 2013-10-24T13:36:49.900 回答
1

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

Google Play 商店:aLogcat 和 aLogrec

于 2014-01-09T08:19:39.820 回答
1

我将Drunken Daddy 的答案调整为不需要权限并将其迁移到 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"
    ... >
于 2021-03-09T12:23:42.990 回答
0

醉爸爸的答案是完美的。不过我想补充一下,

Environment.getExternalStorageDirectory()

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

context.getExternalFilesDir(null);

返回

/storage/emulated/0/Android/data/com.domain.myapp/files
于 2021-04-10T05:16:22.033 回答