安卓软件错误log_Android编程实现捕获程序异常退出时的错误log信息功能详解

本文实例讲述了Android编程实现捕获程序异常退出时的错误log信息功能。分享给大家供大家参考,具体如下:

很多时候我们程序无缘无故的就挂掉了,让我们一头雾水,如果刚好我们在调试,那我们可以通过错误log来查看是什么原因引起的程序崩溃。但是当我们把程序发别人使用时,就没那么好运了,那我们要怎么样才能捕获到那个错误异常呢?还好Android给我们提供了UncaughtExceptionHandler 这个类,我们可以通过实现这个类的接口,来全局捕获那个让程序崩掉的错误log信息。可以将错误的log保存在本地,也可以发送给服务器后台。下面来看下UncaughtExceptionHandler 的实现类CrashHandler吧。

CrashHandler.Java

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

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.SimpleDateFormat;

import java.util.Date;

import java.util.Locale;

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 {

private static final String TAG = CrashHandler.class.getSimpleName();

private static final String SINGLE_RETURN = "\n";

private static final String SINGLE_LINE = "--------------------------------";

private static CrashHandler mCrashHandler;

private Context mContext;

private UncaughtExceptionHandler mDefaultHandler;

private StringBuffer mErrorLogBuffer = new StringBuffer();

/**

* 获取CrashHandler实例,单例模式。

*

* @return 返回CrashHandler实例

*/

public static CrashHandler getInstance() {

if (mCrashHandler == null) {

synchronized (CrashHandler.class) {

if (mCrashHandler == null) {

mCrashHandler = new CrashHandler();

}

}

}

return mCrashHandler;

}

public void init(Context context) {

mContext = context;

// 获取系统默认的uncaughtException处理类实例

mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();

// 设置成我们处理uncaughtException的类

Thread.setDefaultUncaughtExceptionHandler(this);

}

@Override

public void uncaughtException(Thread thread, Throwable ex) {

Log.d(TAG, "uncaughtException:" + ex);

if (!handleException(ex) && mDefaultHandler != null) {

// 如果用户没有处理异常就由系统默认的异常处理器来处理

mDefaultHandler.uncaughtException(thread, ex);

} else {

try {

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

android.os.Process.killProcess(android.os.Process.myPid());

}

}

//处理异常事件

private boolean handleException(Throwable ex) {

if (ex == null) {

return false;

}

new Thread(new Runnable() {

@Override

public void run() {

Looper.prepare();

Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_SHORT)

.show();

Looper.loop();

}

}).start();

// 收集设备参数信息

collectDeviceInfo(mContext);

// 收集错误日志

collectCrashInfo(ex);

// 保存错误日志

saveErrorLog();

//TODO: 这里可以加一个网络的请求,发送错误log给后台

// sendErrorLog();

return true;

}

//保存日志到/mnt/sdcard/AppLog/目录下,文件名已时间yyyy-MM-dd_hh-mm-ss.log的形式保存

private void saveErrorLog() {

if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh-mm-ss", Locale.getDefault());

String format = sdf.format(new Date());

format += ".log";

String path = Environment.getExternalStorageDirectory().getPath()+"/AppLog/";

File file = new File(path);

if (!file.exists()){

file.mkdirs();

}

FileOutputStream fos = null;

try {

fos = new FileOutputStream(path+format);

fos.write(mErrorLogBuffer.toString().getBytes());

fos.flush();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} finally {

if (fos != null) {

try {

fos.close();

fos = null;

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

}

//收集错误信息

private void collectCrashInfo(Throwable ex) {

Writer info = new StringWriter();

PrintWriter printWriter = new PrintWriter(info);

ex.printStackTrace(printWriter);

Throwable cause = ex.getCause();

while (cause != null) {

cause.printStackTrace(printWriter);

cause = cause.getCause();

}

String result = info.toString();

printWriter.close();

//将错误信息加入mErrorLogBuffer中

append("", result);

mErrorLogBuffer.append(SINGLE_LINE + SINGLE_RETURN);

Log.d(TAG, "saveCrashInfo2File:" + mErrorLogBuffer.toString());

}

//收集应用和设备信息

private void collectDeviceInfo(Context context) {

//每次使用前,清掉mErrorLogBuffer里的内容

mErrorLogBuffer.setLength(0);

mErrorLogBuffer.append(SINGLE_RETURN + SINGLE_LINE + SINGLE_RETURN);

//获取应用的信息

PackageManager pm = context.getPackageManager();

try {

PackageInfo pi = pm.getPackageInfo(context.getPackageName(),

PackageManager.GET_ACTIVITIES);

if (pi != null) {

append("versionCode", pi.versionCode);

append("versionName", pi.versionName);

append("packageName", pi.packageName);

}

} catch (NameNotFoundException e) {

e.printStackTrace();

}

mErrorLogBuffer.append(SINGLE_LINE + SINGLE_RETURN);

//获取设备的信息

Field[] fields = Build.class.getDeclaredFields();

getDeviceInfoByReflection(fields);

fields = Build.VERSION.class.getDeclaredFields();

getDeviceInfoByReflection(fields);

mErrorLogBuffer.append(SINGLE_LINE + SINGLE_RETURN);

}

//获取设备的信息通过反射方式

private void getDeviceInfoByReflection(Field[] fields) {

for (Field field : fields) {

try {

field.setAccessible(true);

append(field.getName(), field.get(null));

} catch (IllegalArgumentException e) {

e.printStackTrace();

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

}

//mErrorLogBuffer添加友好的log信息

private void append(String key, Object value) {

mErrorLogBuffer.append("" + key + ":" + value + SINGLE_RETURN);

}

}

在application中的使用非常简单,只要init就好了,之后我们就只要等异常出现吧。

CrashApplication.java

import android.app.Application;

public class CrashApplication extends Application{

@Override

public void onCreate() {

super.onCreate();

CrashHandler.getInstance().init(this);

}

}

不要忘记在AndroidManifest.xml声明我们的CrashApplication 。

AndroidManifest.xml

android:allowBackup="true"

android:name=".CrashApplication"

android:icon="@drawable/ic_launcher"

android:label="@string/app_name"

android:theme="@style/AppTheme" >

android:name="com.example.crashtestdemo.MainActivity"

android:label="@string/app_name" >

希望本文所述对大家Android程序设计有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/505025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android 模拟长按菜单键_如何采用PLC梯形图实现单键启动程序

“PLC是一种专门为在工业环境下应用而设计的数字运算操作的电子装置。它采用可以编制程序的存储器,用来在其内部存储执行逻辑运算、顺序运算、计时、计数和算术运算等操作的指令,并能通过数字式或模拟式的输入和输出,控制各种类型的机械或生产…

android 日期对话框,Android日期选择器对话框DatePickerDialog使用详解

调用Android原生日期选择器对话框就是DatePickerDialog,具体内容如下在Android4.4系统上效果如图:在Android5.0以上效果如图:1、Activity的onCreate方法中获取当时的年,月,日Calendar ca Calendar.getInstance();mYea…

c#endread怎么打印出来_NetworkStream.EndRead(IAsyncResult) 方法 (System.Net.Sockets) | Microsoft Docs...

处理异步读取的结束。Handles the end of an asynchronous read.public:override int EndRead(IAsyncResult ^ asyncResult);public override int EndRead (IAsyncResult asyncResult);override this.EndRead : IAsyncResult -> intPublic Overrides Function EndRead (asyn…

wp自定义帖子没标签_ofollow标签的作用有重大变化

nofollow标签的历史经典的nofollow标签作用和使用方法以前的帖子写过,详情读者可以参考以前帖子。nofollow标签(准确说是属性,不过约定俗成,还是叫标签吧)是Google和Yahoo等搜索引擎2005年推出的,目的是告诉…

android电视视频播放器,智能电视如何播放本地视频?当贝市场分享几款播放器...

原标题:智能电视如何播放本地视频?当贝市场分享几款播放器对视频清晰度要求更高的用户普遍会自己下载视频,然后通过本地播放的方式观影,那么,下面就给大家介绍几款智能电视的本地视频播放软件,包你好用。当…

c 复杂的前置后置面试题_你被哪些C语言面试题坑过?

最近在《深入理解计算机系统》上看到一道题,分享一下:假设我们在对有符号值使用补码运算的32位机器人运行代码。对于有符号值使用的是算术右移,而对于无符号值使用的是逻辑右移。变量的声明和初始化如下:int x foo(); //任意值in…

python 三引号_Python 简明教程 --- 4,Python 变量与基本数据类型

微信公众号:码农充电站pro 个人主页:https://codeshellme.github.io任何一个人都会写出能够让机器理解的代码,只有好的程序员才能写出人类可以理解的代码。 —— Martin Fowler 1,什么是变量计算机的本质是处理数据,数…

鸿蒙系统手机9月11日,鸿蒙系统9月11日,将有望正式成为国际第三大手机操作生态系统...

原标题:鸿蒙系统9月11日,将有望正式成为国际第三大手机操作生态系统众所周知,当时华为鸿蒙系统还处于1.0版本的时候,这项技术就已经被运用到了荣耀智能屏上,目前该系统也已经过渡到了华为的手表上,经过这一…

lisp 所在图幅号计算_地图标准分幅与编号计算(二)新图幅号

新图幅号1991年制订了新的《国家基本比例尺地形图分幅和编号》(GB/T 13989-92 )的国家标准,并给出了不同标准比例尺地形图的编给规范及图式。新测和更新的地图,照此标准进行分幅和编号。我国基本比例尺的地形图包括1:5000、1:1万、1:2.5万、1:5万、1:10万…

高德地图画带箭头的线_现代汽车把艺术展览搬到线上,邀您逛全景获奖展

Hyundai Blue Prize 2019获奖展“游戏社会:狼、猞猁和蚁群”(Play societies:wolves, lynx and ants)线上展览正式上线。《游戏社会: 狼、猞猁和蚁群》,以 “信息高速公路上的荒原狼”、“猞猁安全岛”和“蚁群游戏厅” 三段隐喻文本展开展览…

python实训名片管理程序_python3学生名片管理v2.0版

python学生名片管理vv2.0是在1.0的基础上增加部分功能,实现将数据存入文件保存,以便于程序停止后还能再次取到数据。具体实现请看如下部分:card_main.pyimport sysfrom One.card_func2 import *def head():print(* * 30)print(学生信息管理系…

ssm 项目cannot resolve package_前端工程化之创建项目

前言在我们团队,刚开始创建项目,是直接使用框架的 cli 进行创建项目,并修改相关配置。随着项目的增多,沉淀了两套模板,平台端及移动端。后来,我们自己写了一个简单的 cli,并提供了 create 及 li…

android_secure写权限,android.permission.WRITE_SECURE_SETTINGS权限报错

在做Android的GPS这一块时,根据原生代码写的Widget,运行时总是会报错说需要android.permission.WRITE_SECURE_SETTINGS权限,于是便在Manifest.xml中添加该权限,但是保存时会报错提示该权限仅用于系统的app查看了很多资料都说需要将…

解析mysqlbinlog日志_mysqlbinlog日志分析 日志挖掘 违规操作

案例:客户数据库,某关键配置表被修改,需查找操作记录及和操作时间1:mysqlbinlog读取如果binlog formatstatement 可以直接通过mysqlbinlog查看如果binlog formatrow 需要添加 -vv --base64-outputdecode-rows/usr/local/mysql/bi…

python打印长方形_利用python打印出菱形、三角形以及矩形的方法实例

前言 本文主要给大家介绍了关于利用python打印出菱形、三角形以及矩形的相关内容,分享出来供大家参考学习,话不多说,来一起看看详细的介绍: 实例代码 #coding:utf-8 rows int(raw_input(输入列数: )) i j k 1 #声明…

百度seo排名规则_百度关键词seo优化排名如何上首页

无涯孤客百度关键词seo优化排名快速上首页,是通过使用多种百度算法优化,让网站在搜索引擎上排名更好,我们做百度关键词排名的话,要比市面上绝大公司做的要稳定,也希望各位可以相信我们,我们可以将百度关键词…

数学难题html5小游戏答案,小学数学难题讲解及答案

第一讲速算与巧算例1 计算9+99+999+9999+99999解:在涉及所有数字都是9的计算中,常使用凑整法.例如将999化成1000—1去计算.这是小学数学中常用的一种技巧.9+99+999+9999&…

华为做raid5步骤_华为RH2288V5服务器做RAID 0(官方推荐做法)

华为RH2288V5服务器采用的Avago SAS3408阵列卡,RAID做法跟RH2285 RH1285不一样,今天薇晓兰就带各位了解下如何给RH2288V5服务器做RAID!由于Avago SAS3408不支持Legacy配置,支持UEFI配置;支持Legacy和UEFI启动。所以开机…

distinct过滤掉重复记录并且显示所有字段_MySQL的所有姿势,我都帮你准备好了...

mysql登录远程登录方式本地登陆方式mysql:mysql -h 主机名 -P 端口号 -u 用户名 -p密码 mysql:mysql -uroot -p密码数据库操作命令创建数据库、删除数据库、展示所有数据库名。查看当前数据库名、查看所有表、查看其他数据库的表。查看数据库的版本、表结…

HTML5海报生成器源码,原生js小项目 - canvas海报生成器

1.背景之前做过一个营销类移动端h5项目-海报生成器,上传用户本地图片合成海报并支持下载,这次有时间了整理整理。2.几个重点上传本地图片并支持预览处理ios照片翻转使用canvas对图片等比拉伸缩放并居中裁剪使用canvas绘制图片以及文本输出base64并支持下…