Android 导出APP日志

Android 导出APP日志

本文介绍如何抓取APP全局日志,并将其保存到私有目录。

1.创建一个抓取日志服务

public class LogcatService extends Service {
	private static final String THIS_FILE = "TMC";
    private boolean stop = false;
    private int maxFileCount = 4;
    private long maxFileSize = 32*1024*1024;
    private static final String BACKUP_PREFIX = "log_backup_";
	
	@Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        boolean success = LogcatUtil.startCapture();
        if (!success) {
            Log.e(THIS_FILE, "Error to start capture logcat!");
        } else {
            // 启动监听线程,因为子进程会被系统回收所以需要监听
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while(!stop) {
                        File logFile = LogcatUtil.getLogFile();
                        if (logFile.length() >= maxFileSize) {
                            Log.d(THIS_FILE, "Log file size exceed! Backup file");
                            LogcatUtil.stopCapture();
                            backupLogFile(logFile);
                            LogcatUtil.startCapture();
                        }
                        Process process = LogcatUtil.getProcess();
                        boolean isAlive = false;
                        try {
                            int exitValue = process.exitValue();
                            if (exitValue != 0) {
                                isAlive = false;
                            }
                        } catch (IllegalThreadStateException e) {
//                            e.printStackTrace();
                            isAlive = true;
                        }
                        if (!isAlive) {
                            Log.e(THIS_FILE, "Logcat thread died!!!");
                            LogcatUtil.resumeCapture();
                        }

                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }
                    Log.d(THIS_FILE, "Logcat thread normal stop!!!");
                }
            }).start();
        }
    }

	private void backupLogFile(File logFile) {
        String logPath = LogcatUtil.getFilePath();
        if (!new File(logPath).exists()) {
            Log.e(THIS_FILE, "Error!! Log file path not exists");
            return;
        }
        for (int index =0;index<maxFileCount;index++) {
            String backupName = logPath + BACKUP_PREFIX + index + ".log";
            File file = new File(backupName);
            if (!file.exists()) {
                Log.d(THIS_FILE, "Backup file " + logFile.getAbsolutePath() + "  to  " + backupName);
                logFile.renameTo(file);
                return;
            }
        }
        Log.d(THIS_FILE, "Backup file is full. Delete first and rename current log file");
        String firstBackupName = logPath + BACKUP_PREFIX + "0.log";
        File firtFile = new File(firstBackupName);
        firtFile.delete();
        for (int index =1;index<maxFileCount;index++) {
            String backupName = logPath + BACKUP_PREFIX + index + ".log";
            File file = new File(backupName);
            file.renameTo(new File(logPath + BACKUP_PREFIX + (index-1) + ".log"));
        }
        // backup current file
        String currentBackupName = logPath + BACKUP_PREFIX + (maxFileCount-1) + ".log";
        logFile.renameTo(new File(currentBackupName));
    }

	@Override
    public void onDestroy() {
        super.onDestroy();
        stop = true;
        LogcatUtil.stopCapture();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }

}

2.日志处理类

包括初始化文件目录、创建文件、抓取日志的指令等相关操作。

public class LogcatUtil {

	private static final String THIS_FILE = "LogcatUtil";

    private static final String TEMP_LOG = "tmclog-" + getFileName() + ".log";

    private static String filePath = "";

    private static File logFile = null;

    private static Process process = null;

    private static boolean running = false;

    public static String getFilePath() {
        return filePath;
    }

    public static void setFilePath(String path) {
        filePath = path;
    }

    public static Process getProcess() {
        return process;
    }

    public static File getLogFile() {
        return logFile;
    }

	/**
     * 初始化目录
     */
    public static void init(Context context) {
        try {
            File sdDir = context.getExternalFilesDir(null);
            filePath = sdDir.getAbsolutePath();

        } catch (Exception e) {
            e.printStackTrace();
            Log.e("CoverCard","创建文件失败!");
        }
    }

	public static String getFileName() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String date = format.format(new Date(System.currentTimeMillis()));
        return date;
    }

    // 清除4天前保存的logcat日志
    public static void cleanHistory() {
        FileUtil.deleteFilesBefore(filePath, 4 * 24 * 60 * 60 * 1000);
    }
    
    public static boolean startCapture() {
        LogcatUtil.cleanHistory();
        if (running) {
            Log.d(THIS_FILE, "Loggcat capture is already running");
            return true;
        }
        File path = new File(filePath);
        if (!path.exists()) {
            path.mkdirs();
        }
        logFile = new File(path, TEMP_LOG);
        try {
            process = Runtime.getRuntime().exec("logcat -c");
            process = Runtime.getRuntime().exec("logcat -f " + logFile);
        } catch (IOException e) {
            Log.e(THIS_FILE, "Trye to capture app logcat failed. IO exception");
            e.printStackTrace();
            return false;
        }
        running = true;
        return true;
    }
    
    /**
     * 继续抓取日志,使用同样的文件
     *
     * @return
     */
    public static boolean resumeCapture() {
        if (logFile != null) {
            try {
                process = Runtime.getRuntime().exec("logcat -c");
                process = Runtime.getRuntime().exec("logcat -f " + logFile);
            } catch (IOException e) {
                e.printStackTrace();
                return false;
            }
        }

        return true;
    }
    
    public static void stopCapture() {
        if (process != null) {
            process.destroy();
        }
        logFile = null;
        running = false;
    }
}

3.调用类

public class LogModule {
	public static void init(Context context) {
        LogcatUtil.init(context);
    }

    /**
     * 应用启动抓取系统全日志
     *
     * @param context
     */
    public static void openCollectSystemLog(Context context) {
        Intent intent = new Intent(context, LogcatService.class);
        context.startService(intent);
    }
    
    /**
     * 停止日志收集
     *
     * @param context
     */
    public static void closeCollectSystemLog(Context context) {
        Intent intent = new Intent(context, LogcatService.class);
        context.stopService(intent);
    }
}

4.使用方法

  1. 首先将服务在AndroidManifest.xml中,进行注册。
<service android:name="com.demo.logutils.LogcatService"
            android:enabled="true"
            android:exported="true" />
  1. 在activity中使用LogModule进行调用。
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		<-----省略部分代码----->
		LogModule.init(this);// 初始化
    	LogModule.openCollectSystemLog(this);// 启动抓取系统全日志

	}

	@Override
    protected void onDestroy() {
        super.onDestroy();
        LogModule.closeCollectSystemLog(this);
    }


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值