app在执行过程中。为了后期的维护升级,记录日志是一个很好的方法。

为了读取到app执行时的日志,一般的作法是单独开一个线程,在app执行的启动线程。然后app退出时停掉线程。

然而我们更好的方法是开启一个service,然后在里面做日志记录。代码例如以下:

package com.hai.logcat;import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.Service;
import android.content.Intent;
import android.os.Environment;
import android.os.IBinder;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;public class MyLogcat extends Service {Thread thread;boolean readlog = true;@Overridepublic IBinder onBind(Intent intent) {return null;}@Overridepublic void onCreate() {super.onCreate();Log.d("hhp", "onCreate");thread = new Thread(new Runnable() {@Overridepublic void run() {log2();//个人认为这种方法更有用}});}@Overridepublic void onStart(Intent intent, int startId) {thread.start();Log.d("hhp", "onStart");super.onStart(intent, startId);}/*** 方法1*/private void log2() {Log.d("hhp", "log2 start");String[] cmds = { "logcat", "-c" };String shellCmd = "logcat -v time -s *:W "; // adb logcat -v time *:WProcess process = null;Runtime runtime = Runtime.getRuntime();BufferedReader reader = null;try {runtime.exec(cmds).waitFor();process = runtime.exec(shellCmd);reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line = null;while ((line = reader.readLine()) != null) {if (line.contains(String.valueOf(android.os.Process.myPid()))) {// line = new String(line.getBytes("iso-8859-1"), "utf-8");writeTofile(line);}}} catch (Exception e) {e.printStackTrace();}Log.d("hhp", "log2 finished");}/*** 方法2*/private void log() {Log.d("hhp", "log start");String[] cmds = { "logcat", "-c" };String shellCmd = "logcat -v time -s *:W ";// //adb logcat -v time *:WProcess process = null;InputStream is = null;DataInputStream dis = null;String line = "";Runtime runtime = Runtime.getRuntime();try {runtime.exec(cmds);process = runtime.exec(shellCmd);is = process.getInputStream();dis = new DataInputStream(is);// String filter = GetPid();String filter = android.os.Process.myPid() + "";while ((line = dis.readLine()) != null) { //这里假设输入流没断。会一直循环下去。line = new String(line.getBytes("iso-8859-1"), "utf-8");if (line.contains(filter)) {int pos = line.indexOf(":");Log.d("hhp2", line + "");writeTofile(line);}}} catch (Exception e) {}Log.d("hhp", "log finished");}private void writeTofile(String line) {String content = line + "\r\n";File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+ "/logcat/myLog.txt");if (!file.exists()) {try {file.createNewFile();} catch (Exception e) {e.printStackTrace();}}FileOutputStream fos;try {fos = new FileOutputStream(file, true);fos.write(content.getBytes());fos.flush();fos.close();} catch (Exception e) {e.printStackTrace();}}@Overridepublic void onDestroy() {super.onDestroy();stopSelf();}
}

代码比較简单,所以没怎么注视了。说下大概思路:在service开启的时候。就开启线程不停地从logcat中读取输入流,

把读到的信息存入文件里,service停止的时候线程stop,就这么简单。

当然要读入系统日志还须要加入权限:

<uses-permission android:name="android.permission.READ_LOGS" />

以下是我记录的測试日志,信息记录的有点多。实际中能够运用正则过滤掉一些信息。

上面的代码基本能够记录本app执行中的日志,但假设中途有未捕获的异常导致app奔溃,那么这个未捕获的异常导致的奔溃上面代码就记录不到了。

由于这个异常导致app奔溃,虚拟机挂掉,那当然记录日志的线程也停了。那怎么捕获这类我们未捕获的异常(执行时异常)呢,幸好android这样

一个接口UncaughtExceptionHandler,当app奔溃前。它会先通知这个接口。这样我们就能够在app奔溃前做点自己想做的事了。

关于怎么捕获奔溃异常。我认为这位哥们的一片博客写的不错http://blog.csdn.net/liuhe688/article/details/6584143#。 我借鉴着改了下:

package com.hai.logcat;import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;public class CrashHandler implements UncaughtExceptionHandler {public static final String TAG = "CrashHandler";// 系统默认的UncaughtException处理类private Thread.UncaughtExceptionHandler mDefaultHandler;// CrashHandler实例private static CrashHandler INSTANCE = new CrashHandler();// 程序的Context对象private Context mContext;// 用来存储设备信息和异常信息private Map<String, String> infos = new HashMap<String, String>();// 用于格式化日期,作为日志文件名称的一部分private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss  ");/** 保证仅仅有一个CrashHandler实例 */private CrashHandler() {}/** 获取CrashHandler实例 ,单例模式 */public static CrashHandler getInstance() {return INSTANCE;}/*** 初始化* * @param context*/public void init(Context context) {mContext = context;// 获取系统默认的UncaughtException处理器mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 设置该CrashHandler为程序的默认处理器Thread.setDefaultUncaughtExceptionHandler(this);}/*** 当UncaughtException发生时会转入该函数来处理*/@Overridepublic void uncaughtException(Thread thread, Throwable ex) {if (!handleException(ex) && mDefaultHandler != null) {// 假设用户没有处理则让系统默认的异常处理器来处理mDefaultHandler.uncaughtException(thread, ex);} else {try {Thread.sleep(3000);} catch (InterruptedException e) {Log.e(TAG, "error : ", e);}// 退出程序android.os.Process.killProcess(android.os.Process.myPid());System.exit(1);}}/*** 自己定义错误处理,收集错误信息 发送错误报告等操作均在此完毕.* * @param ex* @return true:假设处理了该异常信息;否则返回false.*/private boolean handleException(final Throwable ex) {if (ex == null) {return false;}// 使用Toast来显示异常信息new Thread() {@Overridepublic void run() {Looper.prepare();ex.printStackTrace();Toast.makeText(mContext, "非常抱歉,程序出现异常,即将退出.", Toast.LENGTH_LONG).show();Looper.loop();}}.start();// 收集设备參数信息collectDeviceInfo(mContext);// 保存日志文件saveCrashInfo2File(ex);return true;}/*** 收集设备參数信息* * @param ctx*/public void collectDeviceInfo(Context ctx) {try {PackageManager pm = ctx.getPackageManager();PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);if (pi != null) {String versionName = pi.versionName == null ? "null" : pi.versionName;String versionCode = pi.versionCode + "";infos.put("versionName", versionName);infos.put("versionCode", versionCode);}} catch (NameNotFoundException e) {Log.e(TAG, "an error occured when collect package info", e);}Field[] fields = Build.class.getDeclaredFields();for (Field field : fields) {try {field.setAccessible(true);infos.put(field.getName(), field.get(null).toString());Log.d(TAG, field.getName() + " : " + field.get(null));} catch (Exception e) {Log.e(TAG, "an error occured when collect crash info", e);}}}/*** 保存错误信息到文件里* * @param ex* @return 返回文件名称称,便于将文件传送到server*/private String saveCrashInfo2File(Throwable ex) {StringBuffer sb = new StringBuffer();for (Map.Entry<String, String> entry : infos.entrySet()) {String key = entry.getKey();String value = entry.getValue();sb.append(key + "=" + value + "\n");}Writer writer = new StringWriter();PrintWriter printWriter = new PrintWriter(writer);ex.printStackTrace(printWriter);Throwable cause = ex.getCause();while (cause != null) {cause.printStackTrace(printWriter);cause = cause.getCause();}printWriter.close();String result = writer.toString();String time = formatter.format(new Date());sb.append(time + result);try {long timestamp = System.currentTimeMillis();String fileName = "crash.log";if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {String path =Environment.getExternalStorageDirectory().getAbsolutePath()+ "/logcat/";File dir = new File(path);if (!dir.exists()) {dir.mkdirs();}FileOutputStream fos = new FileOutputStream(path + fileName, true);fos.write((sb.toString()).getBytes());fos.close();}return fileName;} catch (Exception e) {Log.e(TAG, "an error occured while writing file...", e);}return null;}
}

上面我们实现了这个接口。然后在奔溃前做了一些友优点理。如存储奔溃日志,主动杀死进程,不让弹出系统的强制关闭对话框。

然后我们在Application中这样引用就可以

package com.hai;import android.app.Application;import com.hai.logcat.CrashHandler;public class MyApplication extends Application {CrashHandler handler = null;@Overridepublic void onCreate() {super.onCreate();handler = CrashHandler.getInstance();handler.init(getApplicationContext());}
}

android app记录执行日志 捕获奔溃异常 ,存储日志到文件相关推荐

  1. Android APP代码执行历史漏洞与攻击面分析

    文章目录 前言 错误的反射调用 漏洞根源分析 漏洞防御建议 反射调用思考 CVE-2020-8913 漏洞根源分析 动态加载Dex "寄生兽"漏洞 TikTok APP漏洞 代码执 ...

  2. nginx php 错误日志,PHP 错误与异常的日志记录

    提到 Nginx + PHP 服务的错误日志,我们通常能想到的有 Nginx 的 access 日志.error 日志以及 PHP 的 error 日志.虽然看起来是个很简单的问题,但里面其实又牵扯到 ...

  3. exception日志 php_PHP 错误与异常的日志记录

    提到 Nginx + PHP 服务的错误日志,我们通常能想到的有 Nginx 的 access 日志.error 日志以及 PHP 的 error 日志.虽然看起来是个很简单的问题,但里面其实又牵扯到 ...

  4. Android 捕获异常,上报异常日志,捕获奔溃日志,bugly使用实例

    1.登录腾讯bugly平台创建应用 腾讯Bugly - 一种愉悦的开发方式 _android anr_android anr分析_iOS崩溃日志分析平台 2.1加载依赖 /*崩溃处理 */ imple ...

  5. intellij IDEA debug android app之前执行adb命令

    2019独角兽企业重金招聘Python工程师标准>>> run/debug菜单项: "edit configuration" 点了图中凸显的"+&quo ...

  6. python try: except: 捕获到的异常输出到 log文件

    import logging # 默认__name__ ,可更改 logging.basicConfig(filename='../LOG/'+__name__+'.log',format='[%(a ...

  7. android app实现轮播的图片视频播放video,仿淘宝商品详情的视频播放(android)

    这段时间在学习开发android app 记录一下实现仿淘宝图片视频切换的功能,直接拿来用即可,大家有什么问题可以共同交流 先看一下目录结构吧 思路: ViewPager 分别实现三个类型的滑动–fr ...

  8. Android Studio执行出现“应用程序安装异常(-15)

    Android Studio执行出现"应用程序安装异常(-15) gradle.propeities文件,在最底下加入: android.injected.testOnly=false 我的 ...

  9. Android App Bundle基础入门

    一.前言 重要提示:从 2021 年 8 月起,新应用需要使用 Android App Bundle 才能在 Google Play 中发布.现在,Play Feature Delivery 或 Pl ...

  10. NORDIC Thing:52 Android App 学习之一:THINGY 52 节点与手机的蓝牙识别、过滤及通信建立

    Android App 蓝牙扫描功能页面, SCAN 按键触发蓝牙扫描 XML 文件:      app\res\layout\activity_configuration.xmlJAVA 文件:   ...

最新文章

  1. wordpress php 7 速度优化,WordPress优化提速必做的6种操作代码篇
  2. 惯性积计算实例_第2课:自定义函数|计算思维在于必要的复用?!
  3. 【PC端vue ui框架学习】vue项目如何使用基于vue的UI框架Element
  4. Android项目技术总结:项目中选择任务的联系人引出android的spinner的监听问题
  5. 26. 删除排序数组中的重复项
  6. typecho除了首页其他大部分网页404怎么办?
  7. 【README2】动态规划之斐波那契数列说明重叠子问题如何解决
  8. ICCV NAS Workshop 最佳论文提名:通过层级掩码实现高效神经网络架构搜索
  9. 数据分析学习笔记-数据分析预备知识
  10. 【RobotStudio学习笔记】(九)坐标偏移设置
  11. [转][python] 常用正则表达式爬取网页信息及分析HTML标签总结
  12. 程序员必备,C#各类项目、开源项目插件资料收藏
  13. 简单方法去除图片水印图文教程
  14. CentOS7图形界面与命令行界面切换的快捷键
  15. 神经网络能用来干什么_秒懂神经网络---震惊!!!神经网络原来可以这么简单!...
  16. 好玩又有趣的Python实例小游戏代码,我能在电脑上琢磨一天
  17. cents7配置gradle4
  18. 2022年阿里云双十二服务器活动内容汇总及价格表
  19. 32蜂鸣器天空之城代码_GitHub宣布已将所有代码永久封存!
  20. bootscript部署到服务器后图标不显示

热门文章

  1. 2011年国庆老家记录
  2. Zsh和oh my zsh的安装和使用
  3. 添加css单词换行连字符
  4. 02-JAVA语法基础
  5. 删除Flex Builder中没用的工作空间
  6. 转载:浅谈程序员的数学修养
  7. java的线程池的基础类
  8. 关于hadoop HDFS进行读写文件操作的问题
  9. [HDU5739]Fantasia(圆方树DP)
  10. springSession框架来实现sso单点登陆