APP开发实战152-Android使用UncaughtExceptionHandler处理异常
来源:互联网 发布:淘宝客服骂人怎么投诉 编辑:程序博客网 时间:2024/05/18 02:37
25.2.2使用UncaughtExceptionHandler处理异常
在使用APP的时候,在任何时候,都可能遇到异常,能够预判到的异常只是极少数,对于不能预判到的异常,可以统一使用UncaughtExceptionHandler接口处理。
如果子线程中出现异常,在主线程代码中,使用try…catch…是无法捕获到异常的,必须使用UncaughtExceptionHandler来进行处理。
在实现UncaughtExceptionHandler时,必须重载uncaughtException(Threadthread, Throwable ex) ,如果没有实现该接口,也就是没有显示捕捉异常,则ex为空,否则ex不为空,thread 则为出异常的线程。
如下代码实现UncaughtExceptionHandler接口,并保存异常日志到本机:
publicclass rwUncaughtExceptionHandler implements
Thread.UncaughtExceptionHandler{
privateThread.UncaughtExceptionHandler mDefaultHandler;
public static final String TAG ="rwUncaught";
private staticrwUncaughtExceptionHandler INSTANCE = new
rwUncaughtExceptionHandler();
private Context mContext;// 程序的Context对象
private Map<String, String>info = new HashMap<String, String>();// 用来存储设备信息和异常信息
private SimpleDateFormat format = new
SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
/** 保证只有一个rwUncaughtExceptionHandler实例 */
private rwUncaughtExceptionHandler(){
}
/** 获取rwUncaughtExceptionHandler实例 ,单例模式 */
public staticrwUncaughtExceptionHandler getInstance() {
return INSTANCE;
}
public void init(Context context){
mContext = context;
//获取系统默认的UncaughtException处理器
mDefaultHandler =Thread.getDefaultUncaughtExceptionHandler();
//设置该rwUncaughtExceptionHandler为程序的默认处理器
Thread.setDefaultUncaughtExceptionHandler(this);
}
@Override
public void uncaughtException(Threadthread, Throwable ex) {
if (!handleException(ex)&& mDefaultHandler != null) {
//如果用户没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
} else {
try {
Thread.sleep(2000);
} catch (InterruptedExceptione) {
Log.e(TAG, "error :", e);
}
Intent intent = newIntent(mContext.getApplicationContext(), ViewPagerDemo.class);
PendingIntent restartIntent =PendingIntent.getActivity(mContext.getApplicationContext(), 0,
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
0);
//退出程序
AlarmManager mgr = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC,System.currentTimeMillis() + 1000,
restartIntent); // 1秒钟后重启应用
//关闭所有的Activity
exceptionHandlerApplication.finishActivity();
}
}
/**
* 自定义错误处理,收集错误信息发送错误报告等操作均在此完成.
*
* @param ex
* @return true:如果处理了该异常信息;否则返回false.
*/
private booleanhandleException(Throwable ex) {
if (ex == null) {
return false;
}
//使用Toast来显示异常信息
new Thread() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(mContext,"很抱歉,程序出现异常,即将退出并重启。",
Toast.LENGTH_SHORT).show();
Looper.loop();
}
}.start();
// 收集设备参数信息
collectDeviceInfo(mContext);
// 保存日志文件
saveCrashInfo(ex);
return true;
}
/**
* 收集设备参数信息
*
* @param context
*/
public void collectDeviceInfo(Contextcontext) {
try {
PackageManager pm =context.getPackageManager();// 获得包管理器
PackageInfo pi =pm.getPackageInfo(context.getPackageName(),
PackageManager.GET_ACTIVITIES);// 得到该应用的信息,即主Activity
if (pi != null) {
String versionName =pi.versionName == null ? "null"
: pi.versionName;
String versionCode =pi.versionCode + "";
info.put("versionName",versionName);
info.put("versionCode", versionCode);
/**
* 获取手机型号,系统版本,以及SDK版本
*/
info.put("手机型号:",android.os.Build.MODEL);
info.put("系统版本",""+android.os.Build.VERSION.SDK);
info.put("Android版本",android.os.Build.VERSION.RELEASE);
}
} catch(PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
Field[] fields = Build.class.getDeclaredFields();
for (Field field : fields) {
try {
field.setAccessible(true);
info.put(field.getName(),field.get("").toString());
Log.d(TAG,field.getName() + ":" + field.get(""));
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch(IllegalAccessException e) {
e.printStackTrace();
}
}
}
private String saveCrashInfo(Throwableex) {
StringBuffer sb = new StringBuffer();
for (Map.Entry<String,String> entry : info.entrySet()) {
String key = entry.getKey();
String value =entry.getValue();
sb.append(key + "="+ value + "\r\n");
}
Writer writer = newStringWriter();
PrintWriter pw = newPrintWriter(writer);
ex.printStackTrace(pw);
Throwable cause = ex.getCause();
// 循环着把所有的异常信息写入writer中
while (cause != null) {
cause.printStackTrace(pw);
cause = cause.getCause();
}
pw.close();// 记得关闭
String result =writer.toString();
sb.append(result);
// 保存文件
long timetamp =System.currentTimeMillis();
String time = format.format(newDate());
String fileName = "crash_"+ time + "_"+ ".log";
if(Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
try {
File dir = new
File(Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator + "crash");
Log.i("CrashHandler", dir.toString());
if (!dir.exists())
dir.mkdir();
FileOutputStream fos =new FileOutputStream(new File(dir,
fileName));
fos.write(sb.toString().getBytes());
fos.close();
return fileName;
} catch(FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
实现Application的子类,初始化异常处理类:
publicclass exceptionHandlerApplication extends Application {
private static ArrayList<Activity>list = new ArrayList<Activity>();
@Override
public void onCreate() {
super.onCreate();
rwUncaughtExceptionHandler.getInstance().init(this);
}
/**
* Activity关闭时,删除Activity列表中的Activity对象*/
public void removeActivity(Activitya){
list.remove(a);
}
/**
* 向Activity列表中添加Activity对象*/
public static voidaddActivity(Activity a){
list.add(a);
}
/**
* 关闭Activity列表中的所有Activity*/
public static void finishActivity(){
for (Activity activity : list) {
if (null != activity) {
activity.finish();
}
}
//杀死该应用进程
android.os.Process.killProcess(android.os.Process.myPid());
}
}
在创建每个Activity时,都需要把当前Activity加入到列表中,以便后续退出应用时关闭:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
exceptionHandlerApplication.addActivity(this);
}
还需在AndroidManifest.xml中增加自定义Application类的声明:
<application
android:name=".exceptionHandlerApplication"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".MainActvity"
android:label="@string/title_activity_view_pager_demo">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".ListActivity">
</activity>
</application>
- APP开发实战152-Android使用UncaughtExceptionHandler处理异常
- APP开发实战97-Android异常处理
- android UncaughtExceptionHandler全局异常处理
- Android中使用UncaughtExceptionHandler来处理未捕获的异常
- APP开发实战151-Android使用try…catch…处理异常
- APP开发实战98-Android异常处理注意事项
- Android使用UncaughtExceptionHandler捕获异常
- Android使用UncaughtExceptionHandler捕获异常
- Android捕获异常处理——UncaughtExceptionHandler
- Android 全局异常处理之UncaughtExceptionHandler
- Android使用UncaughtExceptionHandler捕获全局异常
- Android使用UncaughtExceptionHandler捕获全局异常
- Android使用UncaughtExceptionHandler捕获全局异常
- Android使用UncaughtExceptionHandler捕获全局异常
- Android使用UncaughtExceptionHandler捕获全局异常
- Android使用UncaughtExceptionHandler捕获全局异常
- Android使用UncaughtExceptionHandler捕获全局异常
- Android使用UncaughtExceptionHandler捕获全局异常
- ubuntu16.04 vim-gnome
- windows yii2 advanced默认登录配置
- 树状数组—改段求点
- adb ——shell
- zigbee编译错误汇总(一)
- APP开发实战152-Android使用UncaughtExceptionHandler处理异常
- dubbo的使用2
- sklearn基本用法----SVM
- 30万奖金!还带你奔赴加拿大相约KDD!?阿里聚安全算法挑战赛带你飞起!
- 隐式转换和显式转换及强制转换的区别【转】
- Eclipse下Java Web工程的文件夹结构
- CentOS改IP
- strlen和sizeof的区别
- jqgrid实现子表格