Android应用捕获全局异常自定义处理
[2016-06-30]最新的全局异常处理DRCrashHandler已经集成在DR_support_lib库中
具体请看: https://coding.net/u/wrcold520/p/DR_support_lib/git/tree/master
[2016-06-28] 1 增加log4j的支持
[2016-06-28] 2 增加全局异常处理(可自定义程序崩溃提示消息,自定义发送错误报告到服务器)
[2016-06-28] 3 增加两种应用退出方法:① appExit,结束掉所有Acitivity的生命周期,正常退出;② appKill,结束掉所有Acitivity的生命周期,杀掉程序进程后退出。
[2016-06-29] 4 增加透明状态栏和导航栏(默认开启,蓝色背景)
在Android程序中,我们通常会在可能发生错误的地方加上try {} catch (Exception e) {}语句来捕获异常,但是,我们无法保证程序就一定不会出错,比如,你玩Android游戏的过程中经常会碰到黑屏或者直接退出的情况,那么这些异常就应该是没有被捕获到(一般获取到都会提示用户错误,并提示用户是否将错误上传至服务器),那么现在我们来看下如何捕获全局异常,然后自己处理。
1、新建DRCrashHandler.java(这是一个抽象类,我放在了DR_supprot_lib库中,以便以后再写应用程序的时候直接使用,里面用到了一些变量是DRConstants类中的,这是一个常量类,用来定义常用的常量的)
默认Toast弹窗提示用户(消息可以自定义)
package cn.dr.lib.app; import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map; import org.apache.log4j.Logger; 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.Looper;
import android.widget.Toast;
import cn.dr.lib.common.DRConstants;
import cn.dr.lib.utils.DateUtil;
import cn.dr.lib.utils.FileUtil; /**
* DarkRanger的全局异常处理类
*
* @author DarkRanger
*
*/
public abstract class DRCrashHandler implements UncaughtExceptionHandler { /** log4j **/
private static final Logger log = Logger.getLogger(DRCrashHandler.class); /** 系统默认的UncaughtException处理类 **/
private Thread.UncaughtExceptionHandler mDefaultHandler; /** 程序context **/
private DRApplication mContext; /** 存储设备信息和异常信息 **/
private Map<String, String> mInfos = new HashMap<String, String>(); /** 程序出错提示信息 **/
private String mDRTipMsg = "抱歉,程序异常,3s后退出!"; /** 设置crash文件位置 **/
private String mDRCrashFilePath = DRConstants.CRASH_FILE_PATH; /** 生成的log文件 **/
private File logFile; /** 生成的crash文件 **/
private File crashFile; /**
* 初始化
*
* @param context
*/
public void init(DRApplication context) {
log.info("DRCrashHandler is Ready For Application! "); // 1、上下文
mContext = context; // 2、获取系统默认的UncaughtException处理器
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); // 3、初始化参数
initParams(); // 4、设置当前CrashHandler为默认处理异常类
Thread.setDefaultUncaughtExceptionHandler(this);
} /**
* 3.1 初始化参数 <br/>
* <br/>
*
* {@link #setTipMsg(String)} setTipMsg("this is crash tip msg!!!"); <br/>
* {@link #setCrashFilePath(String)}
* setCrashFilePath(Constants.CRASH_FILE_PATH); <br/>
* <br/>
*
* 如果想使用自己的CrashHandler,则复写initParams()方,然后设置参数<br/>
*
* <code>
* public class MyCrashHandler extends DRCrashHandler {<br/>
* private static final Logger log = Logger.getLogger(MyCrashHandler.class);<br/>
*
* @Override<br/>
* public void initParams() {<br/>
* log.trace("MyCrashHandler: initParams()");<br/>
*
* setDRTipMsg("MyCrashHandler tip msg!!!");<br/>
* setDRCrashFilePath(Constants.CRASH_FILE_PATH);<br/>
* }<br/>
* }<br/>
* </code>
*/
public abstract void initParams(); @Override
public void uncaughtException(Thread thread, Throwable ex) {
log.info("DRCrashHandler dispatcher uncaughtException! "); if (mDefaultHandler != null && !handlerException(ex)) {
mDefaultHandler.uncaughtException(thread, ex);
} else {
// 程序休眠3s后退出
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
} ((DRApplication) mContext.getApplicationContext()).appExit();
} } /**
* 5、处理异常<br>
* <br>
*
* 5.1 收集设备参数信息<br>
* 5.2 弹出窗口提示信息<br>
* 5.3 保存log和crash到文件<br>
* 5.4 发送log和crash到服务器<br>
*
* @param ex
* @return 是否处理了异常
*/
protected boolean handlerException(Throwable ex) {
log.info("DRCrashHandler is handling Exception! "); if (ex == null) {
return false;
} else { // 5.1 收集设备参数信息
collectDeviceInfo(mContext); // 5.2 弹出窗口提示信息
new Thread(new Runnable() {
public void run() {
log.info("DRCrashHandler is ready send crash-info to device!"); Looper.prepare();
Toast.makeText(mContext, getDRTipMsg(), Toast.LENGTH_SHORT).show();
Looper.loop();
}
}).start(); // 5.3 保存log和crash到文件
saveLogAndCrash(ex);
// 5.4 发送log和crash到服务器
sendLogAndCrash(); return true;
} } /**
* 5.1 收集设备信息
*
* @param ctx
*/
protected void collectDeviceInfo(Context ctx) {
log.info("DRCrashHandler is collecting DeviceInfo! "); 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 + "";
mInfos.put("versionName", versionName);
mInfos.put("versionCode", versionCode);
}
} catch (NameNotFoundException e) {
log.error("An error occured when collect package info, Error: " + e);
}
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
mInfos.put(field.getName(), field.get(null).toString());
} catch (Exception e) {
log.error("An error occured when collect crash info, Error: " + e);
}
}
} /**
* 5.3 保存log和crash到文件
*
* @param ex
*/
protected void saveLogAndCrash(Throwable ex) {
log.info("DRCrashHandler is saving Log! "); StringBuffer sb = new StringBuffer(); sb.append("[DateTime: " + DateUtil.date2String(new Date()) + "]\n");
sb.append("[DeviceInfo: ]\n");
// 遍历infos
for (Map.Entry<String, String> entry : mInfos.entrySet()) {
String key = entry.getKey().toLowerCase(Locale.getDefault());
String value = entry.getValue();
sb.append(" " + key + ": " + value + "\n");
}
// 将错误手机到writer中
Writer writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
ex.printStackTrace(pw);
Throwable cause = ex.getCause();
while (cause != null) {
cause.printStackTrace(pw);
cause = cause.getCause();
}
pw.close();
String result = writer.toString();
sb.append("[Excetpion: ]\n");
sb.append(result); // 将异常写入日志文件
log.error(result); // 5.3.1 记录异常到特定文件中
saveToCrashFile(sb.toString()); } /**
* 5.3.1写入文本
*
* @param crashText
*/
protected void saveToCrashFile(String crashText) {
log.info("DRCrashHandler is writing crash-info to CrashFile(" + this.mDRCrashFilePath + ")! "); crashFile = new File(mDRCrashFilePath); // 创建文件(自己写的操作文件相关的工具类)
FileUtil.createFileAndFolder(crashFile); // 追加文本(自己写的操作文件相关的工具类)
FileUtil.appendToFile(crashFile, crashText); } /**
* 5.4 发送log和crash到服务器
*/
protected void sendLogAndCrash() {
logFile = new File(mContext.getDrLogHelper().getLog4jFilePath());
crashFile = new File(getDRCrashFilePath());
// 5.4.1
sendToServer(logFile, crashFile);
} /**
* 5.4.1 将错误报告发送到服务器
*
* @param crashFile
* @param logFile
*/
protected abstract void sendToServer(File logFile, File crashFile); public String getDRTipMsg() {
return mDRTipMsg;
} /**
* 设置程序崩溃提示信息
*
* @param mDRTipMsg
*/
public void setDRTipMsg(String mDRTipMsg) {
this.mDRTipMsg = mDRTipMsg;
} public String getDRCrashFilePath() {
return mDRCrashFilePath;
} /**
* 设置记录崩溃信息的文件位置
*
* @param mDRCrashFilePath
*/
public void setDRCrashFilePath(String mDRCrashFilePath) {
this.mDRCrashFilePath = mDRCrashFilePath;
} }
2、新建DRApplication.java(抽象类,里面用到了Log4j,上一篇有讲到如果在Android中集成Log4j,这里在Application中使用DRLogHelper来初始化log4j)
package cn.dr.lib.app; import java.io.File;
import java.util.LinkedList;
import java.util.List; import org.apache.log4j.Logger; import android.app.Activity;
import android.app.Application;
import cn.dr.lib.log.DRLogHelper;
import cn.dr.lib.ui.DRAcitivity; /**
* DarkRanger的Application
*
* @author DarkRanger
*
*/
public abstract class DRApplication extends Application { // 当前类的log
private static Logger log; // Activity列表
private List<DRAcitivity> mActivityList = new LinkedList<DRAcitivity>(); // drLog实例
public DRLogHelper mDRLogHelper = DRLogHelper.getInstance(); // 全局异常处理类的实例
public DRCrashHandler mDRCrashHandler = new DRCrashHandler() { @Override
public void initParams() { } @Override
public void sendToServer(File logFile, File crashFile) { } }; @Override
public void onCreate() { super.onCreate(); // 1、初始化DRLog参数
initDRLogHelperParam(); // 2、初始化DRLog
initDRLogHelper(); // 3、初始化全局异常处理类
initCrashHandler();
} /**
* 1、初始化DRLog参数,如: <br/>
*
* {@link DRApplication#getDrlog()} DRLog drLog = getDrlog(); <br/>
* {@link DRLogHelper#setLog4jFilePath(String)}
* drLog.setLog4jFilePath(Constants.LOG4J_FILE_PATH); <br/>
* {@link DRLogHelper#setType(cn.dr.lib.log.DRLogHelper.LogType)}
* drLog.setType(LogType.TYPE_LOG4J); <br/>
*
* 只有在子类中完成initDRLogParam参数设置以后才能使用log
*/
protected abstract void initDRLogHelperParam(); /**
* 2、初始化DRLog
*/
private void initDRLogHelper() {
getDrLogHelper().init(); log = Logger.getLogger(DRApplication.class);
} /**
* 3、初始化CrashHandler
*/
private void initCrashHandler() {
log.trace("DRApplication: initCrashHandler()"); // 3.1
setHandler(); // 3.2
getDRCrashHandler().init(this);
} /**
*
* 3.1 调用以下方法为mCrashHandler设置实例<br/>
* <br/>
*
* {@link #setCrashHandler(DRCrashHandler)}
*/
public abstract void setHandler(); /**
* 获取DRLog单例
*
* @return
*/
public DRLogHelper getDrLogHelper() {
return mDRLogHelper;
} public DRCrashHandler getDRCrashHandler() {
return mDRCrashHandler;
} public void setDRCrashHandler(DRCrashHandler mCrashHandler) {
this.mDRCrashHandler = mCrashHandler;
} /**
* 添加activity到App的mActivityList
*
* @param activity
*/
public void addActivity(DRAcitivity activity) {
this.mActivityList.add(activity);
} /**
* 遍历mActivityList,结束每一个activity的声明周期
*/
private void finishActivityList() {
for (Activity activity : mActivityList) {
activity.finish();
}
} @Override
public void onTerminate() {
log.trace("DRApplication: onTerminate()"); super.onTerminate();
appExit();
} /**
* 完全退出程序
*/
public void appExit() {
log.trace("DRApplication: appExit()"); finishActivityList();
// 正常退出
System.exit(0);
} /**
* 出现异常杀掉进程
*/
public void appKill() {
log.trace("DRApplication: appKill()"); finishActivityList();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(1);
} }
3、
首先要说明的是:前面两个类我已经集成在DR_supprot_lib库中,在新的应用程序中只需要继承这两个类,分类初始化一些参数即可。
写个App程序测试:
3.1 新建MyCrashHandler.java继承DRCrashHandler,复写两个抽象方法initParams()和sendToServer()
package cn.darkranger.test; import java.io.File; import org.apache.log4j.Logger; import android.os.Environment;
import cn.dr.lib.app.DRCrashHandler; public class MyCrashHandler extends DRCrashHandler {
private static final Logger log = Logger.getLogger(MyCrashHandler.class); String crashFilePath = Environment.getExternalStorageDirectory() + File.separator + "MyApp" + File.separator
+ "Crash.txt"; @Override
public void initParams() {
// 设置程序崩溃提示信息
setDRTipMsg("this is my msg - -");
// 设置程序崩溃的文件位置
setDRCrashFilePath(crashFilePath);
} @Override
protected void sendToServer(File logFile, File crashFile) {
log.info("logFile: " + logFile + "; crashFile: " + "\naction:sendToServer - -");
// 这里要写上传错误信息到服务器的代码,暂时不写,看需求,自己实现
} }
3.2 新建MyApplication.java继承DRApplication,复写两个抽象方法initDRLogHelperParam()和setHandler()
package cn.darkranger.test; import java.io.File; import org.apache.log4j.Logger; import android.os.Environment;
import cn.dr.lib.app.DRCrashHandler; public class MyCrashHandler extends DRCrashHandler {
private static final Logger log = Logger.getLogger(MyCrashHandler.class); String crashFilePath = Environment.getExternalStorageDirectory() + File.separator + "MyApp" + File.separator
+ "Crash.txt"; @Override
public void initParams() {
// 设置程序崩溃提示信息
setDRTipMsg("this is my msg - -");
// 设置程序崩溃的文件位置
setDRCrashFilePath(crashFilePath);
} @Override
protected void sendToServer(File logFile, File crashFile) {
log.info("logFile: " + logFile + "; crashFile: " + "\naction:sendToServer - -");
// 这里要写上传错误信息到服务器的代码,暂时不写,看需求,自己实现
} }
3.3 新建MainActivity,这里暂时不继承DRActivity,继承AppCompatActivity,两个testview,点击第一个,调用DRApplication的退出,点击第二个,抛出异常,我们自己捕获。
package cn.darkranger.test; import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;public class MainActivity extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); TextView exitTv = (TextView) findViewById(R.id.id_exit);
exitTv.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
((MyApplication) getApplication()).appExit();
}
}); TextView testCrashTv = (TextView) findViewById(R.id.id_testCrash);
testCrashTv.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
throw new IllegalArgumentException("this is an IllegalArgumentException! ");
}
}); } @Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
3.4 更改AndroidManifest.xml(添加读写文件的权限,设置application为:cn.darkranger.test.MyApplication)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.darkranger.test"
android:versionCode="1"
android:versionName="1.0" > <uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application
android:name="cn.darkranger.test.MyApplication"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application> </manifest>
测试:
运行,点击第一个按钮,退出程序,查看log文件:
[2016-06-30 22:19:09][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)]
[Level: INFO ] - Msg: Log4j is Ready For DRApplication! [2016-06-30 22:19:09][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)]
[Level: TRACE] - Msg: DRApplication: initCrashHandler() [2016-06-30 22:19:09][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)]
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application! [2016-06-30 22:19:12][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)]
[Level: TRACE] - Msg: DRApplication: appExit() [2016-06-30 22:19:58][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)]
[Level: INFO ] - Msg: Log4j is Ready For DRApplication! [2016-06-30 22:19:58][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)]
[Level: TRACE] - Msg: DRApplication: initCrashHandler() [2016-06-30 22:19:58][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)]
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application! [2016-06-30 22:20:02][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)]
[Level: TRACE] - Msg: DRApplication: appExit()
运行,点击第二个按钮,抛出异常,查看log文件和crash文件:
Log.txt
[2016-06-30 22:19:09][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)]
[Level: INFO ] - Msg: Log4j is Ready For DRApplication! [2016-06-30 22:19:09][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)]
[Level: TRACE] - Msg: DRApplication: initCrashHandler() [2016-06-30 22:19:09][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)]
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application! [2016-06-30 22:19:12][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)]
[Level: TRACE] - Msg: DRApplication: appExit() [2016-06-30 22:19:58][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)]
[Level: INFO ] - Msg: Log4j is Ready For DRApplication! [2016-06-30 22:19:58][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)]
[Level: TRACE] - Msg: DRApplication: initCrashHandler() [2016-06-30 22:19:58][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)]
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application! [2016-06-30 22:20:02][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)]
[Level: TRACE] - Msg: DRApplication: appExit() [2016-06-30 22:20:48][Class: cn.dr.lib.log.DRLogHelper.initLog4j(DRLogHelper.java:89)]
[Level: INFO ] - Msg: Log4j is Ready For DRApplication! [2016-06-30 22:20:48][Class: cn.dr.lib.app.DRApplication.initCrashHandler(DRApplication.java:87)]
[Level: TRACE] - Msg: DRApplication: initCrashHandler() [2016-06-30 22:20:48][Class: cn.dr.lib.app.DRCrashHandler.init(DRCrashHandler.java:65)]
[Level: INFO ] - Msg: DRCrashHandler is Ready For Application! [2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.uncaughtException(DRCrashHandler.java:109)]
[Level: INFO ] - Msg: DRCrashHandler dispatcher uncaughtException! [2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.handlerException(DRCrashHandler.java:139)]
[Level: INFO ] - Msg: DRCrashHandler is handling Exception! [2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.collectDeviceInfo(DRCrashHandler.java:175)]
[Level: INFO ] - Msg: DRCrashHandler is collecting DeviceInfo! [2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.saveLogAndCrash(DRCrashHandler.java:206)]
[Level: INFO ] - Msg: DRCrashHandler is saving Log! [2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.run(DRCrashHandler.java:151)]
[Level: INFO ] - Msg: DRCrashHandler is ready send crash-info to device! [2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.saveLogAndCrash(DRCrashHandler.java:233)]
[Level: ERROR] - Msg: java.lang.IllegalArgumentException: this is an IllegalArgumentException!
at cn.darkranger.test.MainActivity$2.onClick(MainActivity.java:33)
at android.view.View.performClick(View.java:4792)
at android.view.View$PerformClick.run(View.java:19936)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5595)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:964)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:759) [2016-06-30 22:20:50][Class: cn.dr.lib.app.DRCrashHandler.saveToCrashFile(DRCrashHandler.java:246)]
[Level: INFO ] - Msg: DRCrashHandler is writing crash-info to CrashFile(/storage/emulated/0/MyApp/Crash.txt)! [2016-06-30 22:20:50][Class: cn.dr.lib.utils.FileUtil.createFileAndFolder(FileUtil.java:444)]
[Level: INFO ] - Msg: File[/storage/emulated/0/MyApp/Crash.txt] was created successfully! [2016-06-30 22:20:50][Class: cn.darkranger.test.MyCrashHandler.sendToServer(MyCrashHandler.java:26)]
[Level: INFO ] - Msg: logFile: /storage/emulated/0/MyApp/Log.txt; crashFile:
action:sendToServer - - [2016-06-30 22:20:53][Class: cn.dr.lib.app.DRApplication.appExit(DRApplication.java:152)]
[Level: TRACE] - Msg: DRApplication: appExit()
Crash.txt
[DateTime: 2016-06-30 22:20:50]
[DeviceInfo: ]
supported_64_bit_abis: [Ljava.lang.String;@16d078ef
versioncode: 1
board: mozart
bootloader: unknown
type: user
matchers: [Ljava.lang.String;@3d5b7685
id: HUAWEIM2-801W
time: 1437332391000
brand: HUAWEI
tag: Build
serial: TJF4C15804003585
hardware: hi3635
supported_abis: [Ljava.lang.String;@33767ffc
no_hota: false
cpu_abi: arm64-v8a
radio: unknown
is_debuggable: false
replacements: [Ljava.lang.String;@2dec2cda
manufacturer: HUAWEI
supported_32_bit_abis: [Ljava.lang.String;@3271c1ce
tags: ota-rel-keys,release-keys
cpu_abi2:
unknown: unknown
user: huawei
fingerprint: HUAWEI/M2/HWMozart:5.1.1/HUAWEIM2-801W/C233B009:user/release-keys
host: WUH1000005635
product: M2
versionname: 1.0
display: M2-801WV100R001C233B009
hide_product_info: false
model: HUAWEI M2-801W
device: HWMozart
[Excetpion: ]
java.lang.IllegalArgumentException: this is an IllegalArgumentException!
at cn.darkranger.test.MainActivity$2.onClick(MainActivity.java:33)
at android.view.View.performClick(View.java:4792)
at android.view.View$PerformClick.run(View.java:19936)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5595)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:964)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:759)
Android应用捕获全局异常自定义处理的更多相关文章
- Android捕获全局异常
Android捕获全局异常 程序避免不了出现bug,导致程序崩溃,为了尽量不影响用户体验,可以全局捕获异常 效果图 异常捕获处理前 异常捕获处理后(将程序重新启动) 捕获异常的工具类 package ...
- 在C#代码中应用Log4Net(四)在Winform和Web中捕获全局异常
毕竟人不是神,谁写的程序都会有bug,有了bug不可怕,可怕的是出错了,你却不知道错误在哪里.所以我们需要将应用程序中抛出的所有异常都记录起来,不然出了错,找问题就能要了你的命.下面我们主要讨论的是如 ...
- C# 捕获全局异常
一.在Winform程序中捕获全局异常 在winfrom中我们需要了解Application对象中的两个事件 ①Application.ThreadException 事件--当UI线程中某个异常未被 ...
- SpringBoot捕获全局异常
1.创建GloableExceptionAop类捕获全局异常 package com.cppdy.exception; import org.springframework.web.bind.anno ...
- WebForm 在 Global.asax 中捕获全局异常
/// <summary> /// 捕获全局异常 /// </summary> /// <param name="sender">sender& ...
- SpringBoot学习笔记(二):SpringBoot访问静态文件、捕获全局异常、集成Thymeleaf、集成JSP
SpringBoot访问静态文件 什么是静态文件? 不需要通过web容器去得到的文件,直接通过路径就能得到的文件,比如项目的css,js,img等文件. 所有的资源文件都应该在src/main/res ...
- Android使用UncaughtExceptionHandler捕获全局异常
Android系统的“程序异常退出”,给应用的用户体验造成不良影响.为了捕获应用运行时异常并给出友好提示,便可继承UncaughtExceptionHandler类来处理.通过Thread.setDe ...
- 在Global.asax中 注册Application_Error事件 捕获全局异常
参考于:https://shiyousan.com/post/635813858052755170 在ASP.NET MVC中,通过应用程序生命周期中的Application_Error事件可以捕获到 ...
- C# WinForm捕获全局异常
网上找的C# WinForm全局异常捕获方法,代码如下: static class Program { /// <summary> /// 应用程序的主入口点. /// </summ ...
随机推荐
- 手机APP兼容性测试
兼容性测试方案 兼容性问题 屏幕分辨率兼容性问题 软件(iOS和Android系统版本及不同厂家的定制ROM)兼容性问题 硬件(不同的CPU.内存大小等等)兼容性问题 网络(2G/3G/4G/WIFI ...
- java 异常捕获与异常处理
try{会产生异常的代码 }catch(出现异常的类型 e){ 异常出现后处理的方法 } 一旦异常出现又没有异常处理,程序就会中断. public static void main(String[] ...
- 对于网站,APP开发流程的理解
• 明确产品目标用户,目标市场 • 明确将要开发的产品面世后是要解决什么样的问题 • 梳理产品有哪些功能点,功能点如何按照模块划分 • 站在用户角度思考用户怎样使用这款产品,以故事的情景讲述用户如何使 ...
- 牌型总数——第六届蓝桥杯C语言B组(省赛)第七题
原创 牌型种数 小明被劫持到X赌城,被迫与其他3人玩牌.一副扑克牌(去掉大小王牌,共52张),均匀发给4个人,每个人13张.这时,小明脑子里突然冒出一个问题:如果不考虑花色,只考虑点数,也不考虑自己得 ...
- Jquery hover 事件
hover(over,out)一个模仿悬停事件(鼠标移动到一个对象上面及移出这个对象)的方法.这是一个自定义的方法,它为频繁使用的任务提供了一种“保持在其中”的状态. 当鼠标移动到一个匹配的元素上面时 ...
- Js杂谈-插件包读后感
最近有幸得到了一份项目上的前端封装的插件库代码,花了一个下午时间,仔细地研读了一下.对于我很想做自己的类库,搞自己的组件包很有启蒙意义. 相比较我之前阅过的框架或是类库,这份比较简单. 项目是jQue ...
- "ServiceStack.Redis.RedisNativeClient”的方法“get_Db”没有实现。
解决办法: 1.首先通过nuget程序包管理器将相关依赖项卸载干净 2.检查各项目模块中的package.config里还有没有redis的节点,如果已经存在就删除掉 3.去别的正常的项目中看一下re ...
- Delphi XE8中开发DataSnap程序常见问题和解决方法 (二)想对DBExpress的TSQLDataSet写对数据库操作的SQL语句出错了!
当我们搞定DataSnap后,我们进入客户端程序开发阶段了,我们建立了客户端模块后,打算按照刚才开发服务器的步骤开发客户端程序,随后加入了DBExpress的TSQLDataSet,设定数据库连接后, ...
- 【bzoj4007】[JLOI2015]战争调度 暴力+树形dp
Description 脸哥最近来到了一个神奇的王国,王国里的公民每个公民有两个下属或者没有下属,这种 关系刚好组成一个 n 层的完全二叉树.公民 i 的下属是 2 * i 和 2 * i +1.最下 ...
- 【ExecutorService】概述
初试 今天做一个上传excel,后台异步导入数据功能,使用ExecutorService private final ExecutorService m_longPollingService; pub ...