Android崩溃治理
目录
概述
现象描述
基本原理
面临的挑战
崩溃率的标准
崩溃的预防
提高代码的整洁性
网络层校验
经验的总结
崩溃的监控
基础SDK
线下检查
线上监控
输出
崩溃的处理
原则
Kotlin
Java常见崩溃
特定机型的崩溃处理
OOM
高级解决方案
总结
概述
现象描述
基本原理
1. public class RuntimeInit {
2. //其他代码
3. private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
4. public void uncaughtException(Thread t, Throwable e) {
5. try {
6. if (mCrashing) return;
7. mCrashing = true;
8. if (mApplicationObject == null) {
9. Slog.e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
10. } else {
11. Slog.e(TAG, "FATAL EXCEPTION: " + t.getName(), e);
12. }
13. // Bring up crash dialog, wait for it to be dismissed
14. ActivityManagerNative.getDefault().handleApplicationCrash(
15. mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
16. } catch (Throwable t2) {
17. try {
18. Slog.e(TAG, "Error reporting crash", t2);
19. } catch (Throwable t3) {
20. // Even Slog.e() fails! Oh well.
21. }
22. } finally {
23. // Try everything to make sure this process goes away.
24. Process.killProcess(Process.myPid());
25. System.exit(10);
26. }
27. }
28. }
29. //其他代码
30. }
面临的挑战
留存率指的是新增用户第一次使用APP后,一段时间后第二次使用APP的比率
崩溃率的标准
崩溃的预防
提高代码的整洁性
代码的整洁性指代码不重复,不过度省略,分割合理,易于查找和管理,可读性强,易于理解。
编写代码的难度,取决于周边代码的阅读难度。阅读之前代码与书写新的代码,花费的时间比例超过10:1。想要快速实现需求,想要快速完成任务,想要轻松的写代码,请先让你书写的代码整洁易读。
2.每一个方法尽量限制在100行以内,每个文件尽量限制在1000行以内,每行代码宽度最好在编辑器的控制线左边,超出的语句可以在表达式逗号或点号处换行。
3.初期可以参考《阿里巴巴Android开发手册》《阿里巴巴Java开发手册》PDF,后期可以结合实际情况制定一套自己的规范
网络层校验
经验的总结
当每一次版本迭代修复一些线上异常后,要及时进行总结归纳,结合网络上的技术资源,找到根本原因和深层次规律,总结成团队技术博客或小提示,以尽量减少同类问题的再次发生
崩溃的监控
目前APP内集成的通付盾和友盟统计都含有部分崩溃统计的功能,但他们都不是专业的崩溃统计供应商,短期可以满足使用要求,长期建议逐步形成以下的崩溃防控体系:
基础SDK
友盟统计主要擅长提供详尽的App运营的统计数据,功能强大,数据统计及时可靠,是国内小APP开发商主要使用的统计工具,它的崩溃统计功能只包含错误趋势,错误列表和错误详情。
通付盾是第三方安全监控工具,主要用于安全漏洞检测,恶意代码检测,内容违规检测和安全修复建议,其中也包含部分崩溃统计的功能,但是详尽度不如友盟。
Bugly是腾讯公司内部崩溃统计框架产品化的产物,它的初衷就是为移动开发者提供专业的异常上报功能,除了包含友盟的所有功能,还包括根据错误堆栈直接搜索相应文档,匹配解决方案的功能和更详细的崩溃统计图表:
LeakCanary:是用于检测Android和Java内存泄漏的开源库,集成此库后在页面中检测到内存泄漏后,会自动弹出造成内存泄漏的相关的对象的信息,如下:
可以用于发布前的内存检查,也可以修改源码实现内存泄漏定时检测和上报的功能。
自有监控SDK:就是自己开发一套崩溃处理的框架,可以实现一些补充的崩溃处理功能,如自动业务降级(应用入口关闭),测试期间错误堆栈直接在APP上显示(类似React Native的错误红屏)等功能。
线下检查
代码规范检查:Android Studio自带Lint工具,可以对代码执行规范检查。
资源重复检查:可以写脚本或利用现有工具检查图片文件中是否有不同名但内容相同的文件,或者未被程序引用的图片。
线上监控
崩溃异常监控:就是普通的应用崩溃时记录代码抛出的Exception信息,并在合适的时机上报,友盟和Bugly都已包含此功能。
业务异常监控:这部分需要结合现有的代码埋点和无痕埋点的统计信息,结合具体业务功能进行分析。
输出
邮件通知:友盟,通付盾和Bugly都自带邮件通知,打开设置即可,可以设置崩溃率超过多少的时候发邮件。
统计图表:即友盟或Bugly提供的后台数据查看页面,有多个维度的统计图表以网页方式呈现
报告:可以每月或季度出一份崩溃方面的报告,或者合并到其他App整体的报告中。
崩溃的处理
原则
- 由点到面。一个崩溃发生了,我们不能只针对这个崩溃去解决,而要去考虑这一类崩溃怎么去解决和预防。只有这样才能使得这一类崩溃真正被解决。
- 异常不能随便吃掉。随意的使用try-catch,只会增加业务的分支和隐蔽真正的问题,要了解崩溃的本质原因,根据本质原因去解决。崩溃的分支,更要根据业务场景去兜底,保证后续的流程正常。
- 预防胜于治理。当崩溃发生的时候,损失已经造成了,我们再怎么治理也只是减少损失。尽可能的提前预防崩溃的发生,可以将崩溃消灭在萌芽阶段。
Kotlin
Java常见崩溃
NullPointerException是我们遇到最频繁的,造成这种崩溃一般有两种情况:
针对第一种情况导致的原因有很多,可能是开发人员的失误、API返回数据解析异常、进程被杀死后静态变量没初始化导致,我们可以做的有:
针对第二种情况大部分是由于Activity/Fragment销毁或被移除后,在Message、Runnable、网络等回调中执行了一些代码导致的,我们可以做的有:
- Message、Runnable回调时,判断Activity/Fragment是否销毁或被移除;加try-catch保护;Activity/Fragment销毁时移除所有已发送的Runnable。
- 封装LifecycleMessage/Runnable基础组件,并自定义Lint检查,提示使用封装好的基础组件。
- 在BaseActivity、BaseFragment的onDestory()里把当前Activity所发的所有请求取消掉。
特定机型的崩溃处理
- 尝试找到造成崩溃的可疑代码,看是否是特殊的API或者调用方式不当导致的,尝试修改代码逻辑来进行规避。
- 通过Hook来解决,Hook分为Java Hook和Native Hook。Java Hook主要靠反射或者动态代理来更改相应API的行为,需要尝试找到可以Hook的点,一般Hook的点多为静态变量,同时需要注意Android不同版本的API,类名、方法名和成员变量名都可能不一样,所以要做好兼容工作;Native Hook原理上是用更改后的方法把旧方法在内存地址上进行替换,需要考虑到Dalvik和ART的差异;相对来说Native Hook的兼容性更差一点,所以用Native Hook的时候需要配合降级策略。
- 如果通过前两种方式都无法解决的话,我们只能尝试反编译ROM,寻找解决的办法。
OOM
- 匿名内部类实现Handler处理消息,可能导致隐式持有的Activity对象无法回收。
- Activity和Context对象被混淆和滥用,在许多只需要Application Context而不需要使用Activity对象的地方使用了Activity对象,比如注册各类Receiver、计算屏幕密度等等。
- View对象处理不当,使用Activity的LayoutInflater创建的View自身持有的Context对象其实就是Activity,这点经常被忽略,在自己实现View重用等场景下也会导致Activity泄漏。
高级解决方案
高级解决方案需要大块时间和对特定领域知识的钻研,建议之后落实
AOP是面向切面编程的简称,在Android的Gradle插件1.5.0中新增了Transform API之后,编译时修改字节码来实现AOP也因为有了官方支持而变得非常方便。
在一些特定情况下,可以通过AOP的方式自动处理未捕获的异常:
- 抛异常的方法非常明确,调用方式比较固定。
- 异常处理方式比较统一。
- 和业务逻辑无关,即自动处理异常后不会影响正常的业务逻辑。典型的例子有读取Intent Extras参数、读取SharedPreferences、解析颜色字符串值和显示隐藏Window等等。
我们可以专门制作一个Gradle插件,只需要配置一下参数就可以将某个特定方法的调用替换成另一个方法:
- WaimaiBytecodeManipulator {
- replacements(
- "android/content/Intent.getIntExtra(Ljava/lang/String;I)I=com/waimai/IntentUtil.getInt(Landroid/content/Intent;Ljava/lang/String;I)I",
- "android/content/Intent.getStringExtra(Ljava/lang/String;)Ljava/lang/String;=com/waimai/IntentUtil.getString(Landroid/content/Intent;Ljava/lang/String;)Ljava/lang/String;",
- "android/content/Intent.getBooleanExtra(Ljava/lang/String;Z)Z=com/waimai/IntentUtil.getBoolean(Landroid/content/Intent;Ljava/lang/String;Z)Z", ...)
- }
- }
总结
Gradle插件(AOP增强辅助)可以和Gradle配置优化单独做为一块内容
1.《Android App为什么发生异常会导致应用崩溃,进程结束》
4.《【《代码整洁之道》精读与演绎】之一 让代码比你来时更干净》
Android崩溃治理相关推荐
- 货拉拉Android稳定性治理
App Crash对于用户来讲是一种最糟糕的体验,它会导致流程中断.app口碑变差.app卸载.用户流失.订单流失等.相关数据显示,当Android App的崩溃率超过0.4%的时候,活跃用户有明显下 ...
- 代码:android崩溃日志收集和处理
用来处理android崩溃日志收集的代码,详情的使用请转:android崩溃日志收集和处理 第一个类 /** * 异常捕捉实现类 */ public class ErrorCaughtimplemen ...
- android 崩溃日志捕获,安卓Java崩溃的捕获和日志记录
Android的两种崩溃 Android 崩溃分为 Java 崩溃和 Native崩溃两种. Java崩溃的知识点 Java崩溃.png Java崩溃的原因 简单来说,Java崩溃就是在Java代码中 ...
- android 崩溃捕获_Android从相机和图库捕获图像
android 崩溃捕获 In this tutorial we'll develop an application that picks an image from camera or galler ...
- android 崩溃捕获_Android使用FileProvider捕获图像相机图库
android 崩溃捕获 In this tutorial, we'll be developing an application which displays images captured fro ...
- Android TimeoutException治理
原创不易,转载请注明出处https://blog.csdn.net/shihongyu12345/article/details/89682645,谢谢! 常见的一种Android崩溃Timeout崩 ...
- Android总是闪退,怎么办?Android崩溃机制。
闪退,程序退出这些都是开发中最常见的了.开发过程中,那还好说,遇到就解决被,主要还是应对上线问题.各大平台的捕获机制不少,用就完事了.但,我还是想知道Android崩溃机制. 所谓的闪退就是Andro ...
- 美团外卖Android Crash治理之路
Crash率是衡量一个App好坏的重要指标之一,如果你忽略了它的存在,它就会愈演愈烈,最后造成大量用户的流失,进而给公司带来无法估量的损失.本文讲述美团外卖Android客户端团队在将App的Cras ...
- Android 崩溃优化之Java篇(二)
声明:本篇文章已授权微信公众号 YYGeeker 独家发布. 博主原创文章,转载请注明出处:小嵩的博客 一.前言 由于Android系统的碎片化.版本差异.厂商定制ROM等诸多原因,我们经常会遇到各种 ...
- android 崩溃搜索 AndroidRuntime
我们看下android 在启动的时候,会设置一个默认的UncaughtExceptionHandler . 名字叫做LoggingHandler .专门负责打印日志: 代码 如下: /** Copyr ...
最新文章
- r shiny内部支持的输入函数
- Scala AKKA入门示例
- 【转载】css3 content 生成内容
- Visaul Studio 常用快捷键的动画演示
- linux检测不到win,c# – 如何正确检测Windows,Linux和Mac操作系统
- Java 字符,整型,字符串三者转换
- java 8 中文API
- sql无法写入mysql_无法通过写入mysql数据库pandas.to\u sql使用sqlalchemy,但不能通过没有pandas的sqlalchemy...
- 基于centos6.5安装ElasticSearch
- 第15章 音乐可视化(《Python趣味创意编程》教学视频)
- python学习之面向对象学习进阶
- 3640 交换机实验的一些摘要【待进一步更新】
- npm 下载为什么很慢?解决方案来了
- sim800L调试问题
- 史上最严重数据泄露:5亿雅虎账户于2014年被盗
- 新手小白做短视频自媒体,入门级教程分享,抓紧收藏
- 如何有效突破微信每天限加20个好友的技巧
- VMware ESXi-虚拟化平台的搭建
- 教你怎么免费升级宝塔企业版和专业版
- SQLyog免费下载地址