对于任何程序来说,崩溃都是一件很难避免的事情,当然Android程序也不例外。在Android程序中,引起崩溃的多属于运行时异常或者错误,对于这些异常我们很难做到类似Checked Exception那样显式捕获,因而最终导致了程序崩溃。本文讲介绍一些如何处理崩溃的实践,比如收集崩溃的stacktrace,甚至如何避免出现程序已停止的对话框。

如何收集崩溃信息

收集崩溃信息,可以更好的修复问题,增强程序的稳定性。Android中的崩溃收集沿用了Java的收集机制,实现起来比较简单。

1.实现UncaughtExceptionHandler

我们需要实现UncaughtExceptionHandler接口中的uncaughtException方法。该方法体中最常见的操作就是读取崩溃的stacktrace信息,然后上报到服务器数据便于开发者分析。实现代码如下:

public class SimpleUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {

private static final String LOGTAG = "SimpleUncaughtExceptionHandler";

@Override

public void uncaughtException(Thread thread, Throwable ex) {

//读取stacktrace信息 final Writer result = new StringWriter();

final PrintWriter printWriter = new PrintWriter(result);

ex.printStackTrace(printWriter);

String errorReport = result.toString();

Log.i(LOGTAG, "uncaughtException errorReport=" + errorReport);

}

}

除此之外,还建议携带以下信息发送到服务器,帮助更快定位和重现问题。设备唯一ID(基于IMEI或者Android ID等),方便根据用户提供的id,查找崩溃的stacktrace

设备语言与区域 方便重现

应用的版本号

设备的系统版本

设备类型,如平板,手机,TV等

崩溃发生的时间等

注册默认的异常处理

注册默认的异常处理就是最后的一步,很简单,通常建议放在Application的onCreate方法中进行。

public class DroidApplication extends Application {

private static final String LOGTAG = "DroidApplication";

@Override

public void onCreate() {

super.onCreate();

Log.i(LOGTAG, "onCreate");

Thread.setDefaultUncaughtExceptionHandler(new SimpleUncaughtExceptionHandler());

}

}

验证

当我们刻意触发一个NullPointerException时,过滤日志adb logcat | grep SimpleUncaughtExceptionHandler类似如下信息,则说明成功了。

I/SimpleUncaughtExceptionHandler(22469): uncaughtException errorReport=java.lang.NullPointerException

I/SimpleUncaughtExceptionHandler(22469): at com.droidyue.avoidforceclosedemo.MainActivity.causeNPE(MainActivity.java:22)

I/SimpleUncaughtExceptionHandler(22469): at com.droidyue.avoidforceclosedemo.MainActivity.onClick(MainActivity.java:29)

I/SimpleUncaughtExceptionHandler(22469): at android.view.View.performClick(View.java:4470)

I/SimpleUncaughtExceptionHandler(22469): at android.view.View$PerformClick.run(View.java:18593)

I/SimpleUncaughtExceptionHandler(22469): at android.os.Handler.handleCallback(Handler.java:733)

I/SimpleUncaughtExceptionHandler(22469): at android.os.Handler.dispatchMessage(Handler.java:95)

I/SimpleUncaughtExceptionHandler(22469): at android.os.Looper.loop(Looper.java:157)

I/SimpleUncaughtExceptionHandler(22469): at android.app.ActivityThread.main(ActivityThread.java:5867)

I/SimpleUncaughtExceptionHandler(22469): at java.lang.reflect.Method.invokeNative(Native Method)

I/SimpleUncaughtExceptionHandler(22469): at java.lang.reflect.Method.invoke(Method.java:515)

I/SimpleUncaughtExceptionHandler(22469): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)

I/SimpleUncaughtExceptionHandler(22469): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:674)

I/SimpleUncaughtExceptionHandler(22469): at dalvik.system.NativeStart.main(Native Method)

不出现应用崩溃对话框

在Android崩溃的时候,我们都会看到类似这样的对话框

然而,实际上有些情况下是不需要展示这个对话框的,一个常用的例子,我的程序中一个不太重要的推送服务采用了单独的进程,当这个进程崩溃时,实际上是可以允许不让用户感知的。

如果我们采取主进程仍弹出对话框,其他进程不弹出的策略,那么我们的问题,可以总结成如下三个如何判断进程为主进程还是其他进程,或者某个进程

如何在某些进程不弹出应用崩溃对话框

如何在主进程弹出崩溃对话框

既然问题来了,我们就开动挖掘机深挖吧。

进程判定

进行进程判定也比较容易,首先我们需要获得进程名

public static String getProcessName(Context appContext) {

String currentProcessName = "";

int pid = android.os.Process.myPid();

ActivityManager manager = (ActivityManager) appContext.getSystemService(Context.ACTIVITY_SERVICE);

for (ActivityManager.RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) {

if (processInfo.pid == pid) {

currentProcessName = processInfo.processName;

break;

}

}

return currentProcessName;

}

判断主进程,则对比进程名是否和包名相同即可

mAppContext.getPackageName().equals(processName)

判断为某个进程,在mainifest这样这样声明

其对应的完整进程名为com.droidyue.avoidforceclosedemo:service,我们判断可以使用如下代码

"com.droidyue.avoidforceclosedemo:service".equals(processName);

不弹框的处理

不弹框的需要做的就是不调用Android默认的异常处理,当异常出现时,收集完信息,执行进程kill即可。

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

主进程保持弹窗的处理

想要保持弹窗也比较容易,就是调用Android默认的异常处理。

首先需要获得Android默认的异常处理,在设置自定的异常处理之前,将Android默认处理保存起来。如下是在自定义异常处理的构造方法中获取Android默认处理

public DroidUncaughtExceptionHandler(Context context) {

mAppContext = context.getApplicationContext();

mDefaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();

}

然后在异常处理方法uncaughtException中调用如下方法

mDefaultExceptionHandler.uncaughtException(thread, ex);

注意,如果你的应用崩溃后,不调用Android默认的异常处理,也不进行杀死进程,则进程处于不可交互,即UI点击无响应状态。

源码

本示例源码,存放在Github,地址为AvoidForceCloseDemo

知乎 Live 推荐

我将要在知乎上进行我的第二场 Live,题为《我学安卓的那些套路》,来分享我学习安卓的经验与心得。覆盖的内容如下:Android 需要打好哪些编程基础?

除了编程基础,我们还需要补充哪些能力?

作为 Android 程序员,如何把握好技术的宽度和深度?

Android 每块知识学到什么程度,怎么做到?

如何从日常的工作中获取最大的收益?

Android 那么多库,我该选择哪些,怎么学,学到什么程度?

对于初学者或大学生的建议有哪些?

如果你想听一听我的经验或者有疑惑,欢迎参与。

android 弹出框崩溃_Android处理崩溃的一些实践相关推荐

  1. android弹出框自定义按钮,安卓(kotlin)自定义弹出框

    在安卓开发中,我们经常会遇到这种情况,就是可爱的UI们设计了一套属于我们自己风格的弹出框,为了彰显我们自己的风格,使用自动的dialog当然满足不了我们的需求,所以还是得这基础上写出我们自己的提示框, ...

  2. android点击按钮弹出输入框,android 弹出框(输入框和选择框)

    1.输入框: final EditText inputServer = new EditText(this); inputServer.setFilters(new InputFilter[]{new ...

  3. android 弹出框崩溃_Android:一个弹Toast导致系统崩溃问题分析

    我日 现象:点击弹出Toast,然后系统就崩溃了.我晕

  4. android 弹出框带标题栏,Android微信右上角弹出的对话选择框实现

     Android微信右上角弹出的对话选择框实现 我在之前的文章中曾给出了一个开源的微信UI大体实现方案具体代码实现,参见附录文章1.本文单单挑出一个微信的UI实现点:微信右上角弹出的选择对话框.如 ...

  5. android 弹出框带标题栏,Android开发靠标题栏的弹框

    一.效果图 title_dialog.png 二.思路 首先它是一个弹框,只是弹框的布局做些处理,布局占满屏幕,只有需要白色的布局的背景设为白色.其他没设置背景颜色,自然用dialog的style的w ...

  6. Android弹出框的学习

    2019独角兽企业重金招聘Python工程师标准>>> Activities提供了一种方便管理的创建.保存.回复的对话框机制,例如 onCreateDialog(int), onPr ...

  7. android 弹出框 list,android - 如何实现点击listpreference 后,弹出一个dialog?

    小皮2017-04-17 13:21:011楼 android.preference.ListPreference 源码如下: @Override protected void onPrepareDi ...

  8. android 蒙版图片带拖动_Android实现蒙版弹出框效果

    本文实例为大家分享了android蒙版弹出框效果的具体代码,供大家参考,具体内容如下 自定义 package cn.lxsdb.yyd.app.dialog; import cn.lxsdb.yyd. ...

  9. android 弹窗有边框_Android 多种简单的弹出框样式设置代码

    简介 这是一个基于AlertDialog和Dialog这两个类封装的多种弹出框样式,其中提供各种简单样式的弹出框使用说明.同时也可自定义弹出框. 特性 1.使用链式开发代码简洁明了 2.所有的弹出框样 ...

最新文章

  1. 技术分享:什么是CDN鉴权(by光网烈火)
  2. CodeForces: 360(div1)361(div2)
  3. realme GT大师版核心参数曝光:同样一亿像素主摄
  4. Java中的锁(转)
  5. 现在这个时代变了,区块链,数字货币才是最火的项目
  6. Jupyter Lab——使用tqdm.notebook.tqdm时没有出现进度条,提示“HBox(children=(FloatProgress……”
  7. LINUX获取当前用户及信息的命令
  8. IDC 机房空调问题解决方案
  9. SSM社区医院卫生所病人患者随访信息管理javaweb网站系统设计与实现
  10. springboot项目基础骨架搭建并完成基本增删改查及多种形式分页
  11. Android Studio | 5种Log | android.util.Log
  12. 【python机器学习】线性回归--梯度下降实现(基于波士顿房价数据集)
  13. 制作PDF文件全攻略
  14. ece计算机科学硕士,CS、CE、ECE硕士项目:看起来差不多,就能随便乱选吗?
  15. 【计算机网络】HTTPS的基础知识
  16. 磁盘分区方式——MBR与GPT之学习笔记
  17. AC1082带标准程序的版本说明_2.硬件以及参数说明
  18. HTML5+CSS期末大作业:明星主页网站设计—— 鹿晗明星(7页)带留言带音乐表格 HTML+CSS+JavaScript 学生dreamweaver网页设计作业成品
  19. 核电站仪控系统的测试系统ETest
  20. matlab几何体,[原创]利用MATLAB绘制管状几何体

热门文章

  1. Midjourney —— AI绘图工具能取代设计师吗?
  2. AppUploader教程:如何注册账号并激活AppUploader
  3. HTTP 错误 401.2 - Unauthorized
  4. ERA5 积雪 降雪 区别_漠河降雪量已达入秋最大级别 本轮降雪将持续到28日白天...
  5. (四)SpringCloud代码实战之hystrix熔断器
  6. “本地游戏管理程序” 源码分享
  7. iOS推送证书(开发环境)(生成环境)创建教程
  8. 抽象之美——万物皆可设计
  9. 【博学谷学习记录】超强总结,用心分享 | 软件测试 性能测试工具
  10. 测试工程师提前做什么才能避免35岁危机?