【发布时间】:2013-10-24 12:16:01
【问题描述】:
我在 android 设备上运行应用程序时发现了一些崩溃,但没有在模拟器中显示。所以我需要将 Logcat 保存在我设备内存或 SD 卡中的文本文件中。你能建议我这样做的好方法吗?
【问题讨论】:
标签: java android eclipse logcat android-sdcard
我在 android 设备上运行应用程序时发现了一些崩溃,但没有在模拟器中显示。所以我需要将 Logcat 保存在我设备内存或 SD 卡中的文本文件中。你能建议我这样做的好方法吗?
【问题讨论】:
标签: java android eclipse logcat android-sdcard
在应用的开头使用 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");
【讨论】:
-d 转储日志而不是连续流式传输。
adb shell logcat -t 500 > D:\logcat_output.txt
进入您的终端/命令提示符并导航到其中包含 adb 的文件夹,如果它尚未添加到您的环境变量中并粘贴此命令。
t 是你需要查看的行数
D:\logcat_output.txt 是存储 logcat 的位置。
【讨论】:
在你的类中使用 -f 选项和 logcat:
Runtime.getRuntime().exec("logcat -f" + " /sdcard/Logcat.txt");
这会将日志转储到文件存储设备。
请注意,路径“/sdcard/”可能不适用于所有设备。你应该使用standard APIs to access the external storage。
【讨论】:
由于我还不能发表评论,所以我会发布这个作为答案
我按照@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
【讨论】:
显然 android.permission.READ_LOGS 仅授予最新版本的 Android 系统应用。
【讨论】:
添加清单权限:
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);
}
【讨论】:
如果您只需要保存 logcat(无需编码),您可以使用来自 Google Play 的 aLogrec 或 aLogcat 应用程序。
Google Play 商店:aLogcat & aLogrec
【讨论】:
我将 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"
... >
【讨论】:
Drunken Daddy 的回答很完美。不过我想补充一下,
Environment.getExternalStorageDirectory()
在 API 级别 29 中已弃用,Android Studio 不会给您任何警告。相反,您需要use
context.getExternalFilesDir(null);
返回
/storage/emulated/0/Android/data/com.domain.myapp/files
【讨论】: