Android 移动应用性能优化 之 友盟

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
应用实时监控服务-应用监控,每月50GB免费额度
应用实时监控服务-用户体验监控,每月100OCU免费额度
简介: Android 移动应用性能优化 之 友盟

前言


 今天是程序员节,各位朋友们过得好吗?深圳的天气终于变了,现在我也穿起了长袖,距离我的GoodWeather开发已经过去一年多的时间了,这个App我是完全开源,并且把开发的步骤都公布了出来,在开发过程中我遇到过很多问题,刚好借着这个机会来说一下。


正文


 GoodWeather App是一个天气的App,可以实时定位你当前的所在位置,查询到当地的天气,并且提供地图定位模式和语音输入快速查询的方式,项目的源码地址如下:GoodWeather,不方便下载源码的可以直接通过二维码下载安装体验一下:


71a120e2a9494f26b4fcb1a8ef8450da.png


 这个项目我利用工作之余休息的时间陆陆续续的写完了,写的过程中不断的在完善和修改,也会听取读者的建议增加相应的功能,这个过程中也遇到了一些问题,例如:ANR(程序无响应)、NullPointerException(空指针异常)、RunningTimeException(运行时异常)、ArrayIndexOutOfBoundsException(数组索引越界异常)、IllegalArgumentException(非法参数)、NumberFormatException(数字格式异常)等等。


一、问题


 就上述的这些异常你在日常开发中肯定会遇到的,大体说一下。


1. ANR


 ANR(全称:Application Not Responding)程序无响应,要解决问题首先要知道问题出现有哪些可能性,然后在结合你当前应用的实际情况去排查,最终找到解决方法。这是我的思路,那么造成ANR有哪些可能呢?


38faeb7f0cff4e558ab7183a069629c3.png


可能性一:主线程阻塞,在主线程中进行耗时操作过多(数据库读写、文件读写、网络请求、大数据计算等)。


可能性二:内存泄漏,列如App的启动页是一个高清的图片,在有的手机上可以正常运行,有的手机机会闪退。


可能性三:过度绘制,这个说法就是上面两种可能的相结合,首先你在主线程中绘制UI,其次绘制的图比较大或者重复绘制都会有ANR可能。


 实际中的可能性可不止这三点,说说怎么解决的,第一个可能性,主线程阻塞,由于执行了大量的耗时操作造成的,那么这个时候就要使用子线程去进行耗时操作的处理。例如网络请求、数据库读写、文件读写都应该开一个子线程去执行,而不应该在主线程中处理,对于Activity来说UI线程就是主线程,UI线程要负责页面UI的绘制,这里又会引发另一个问题,那就是当你的view由主线程绘制时,在子线程中进行改变时会报错,所以子线程可不可以刷新view呢?是可以的,只不过有一个前提,那就是你的子线程创建了这个view,此时这个子线程就是这个view的UI线程。


 而对于内存泄漏来说,常规情况下是资源处理不当造成的。举个通俗的例子,有两座桥,A和B,A最大承重2吨,B最大承重6吨,有100辆车要过桥,车上载重1吨到6吨不等,正常的分配就是小重量走小桥,大重量走大桥,当资源分配不合理就会出现1吨的车走承重6吨的桥,然后6吨的车走承重2吨的桥,那怕桥质量再好终究会塌,可能例子不是很恰当,但是意思应该说的很清楚了,就是资源合理使用,不用就要回收,回到一个我之前遇到的问题,就是高清图片,国产手机的定制化是很多的,各个厂商都更改了Google的源码变成了定制化系统,这对用户来说没啥,但是对开发者来说就很难受了,因为一个问题你是躲不开的,那就是适配。我之前遇到的问题就是我在启动页用了一个高清图,然后在我的手机上正常运行,然后在一个读者的手机上就直接闪退了。报错的图如下:


4b174706e1c94c5aac128274b0963527.png


 从这个图能看出什么内容呢?


 首先这是一个运行时异常,其次和图片的绘制有关系,那么这么一结合就是过度绘制的问题。


 当时这个读者就找到我,然后我就开始排查,首先是启动App的时候做了什么,这里还会涉及到一个点,那就是App的启动优化,这个点很关键。不过首先要解决bug,经过排查最终定位到是图片的问题,这里就说明了国内厂商对于手机屏幕及自身系统的定制是千差万别的,最终的解决办法就是针对于高清图的文件修改到大分辨率文件夹下,这属于一个比较低级的错误,我之前放置的都是常规的文件夹,吃一堑长一智。


2. NullPointerException


 NullPointerException(空指针异常),我相信用Java写Android的朋友肯定遇到过找个问题,那就是null,常说的空对象。这个问题一般来说在开发的时候做得好可以避免90%的出现概率。最大的出现情况就是赋值的时候,只要出现这个,那么对应的就是你的程序闪退了,哦豁!这个月奖金又没了,打工人的辛酸,留下了悔恨的泪水。所以使用Java开发Android的时候要特别注意这一点,注意null。这一点Kotlin就做的很好,因为空安全这个特性。那么假如出现问题了,线上的项目,用户就说会闪退,甚至都不说是什么时候闪退的,你要怎么办呢?怎么去解决呢?通过第三方SDK,例如友盟,你对接SDK之后,发布之后,报错时,平台上会有报错的信息与日志,这样开发者就可以快速定位问题,然后解决问题了,然后对App做一个更新,这就完美化解了,虽然扣的钱回不来了,但是你及时止损了。至于其他的一些异常都是常规的,发现了就能解决,在开发过程中。最麻烦的就是上线之后的问题要怎么去定位和解决。


 其实在实际的App开发中,大部分的问题都能在开发和测试阶段发现并且解决,但是巧的就是在上线之后到了用户手里,就出现了之前没有发现到的问题,这个时候开发和测试就要互相甩锅了,扯皮是常事。扯完之后还是要想办法解决才行,因此对于现在的线上项目来说,上线之前对接一款性能检测,错误收集的SDK是很有必要的,下面我将针对于我的这个GoodWeather进行这个SDK的对接与使用。


二、友盟使用


 点击友盟进入官网,然后注册和登录。


9900e48d29214e1588efe29b0196361e.png


1. 创建平台应用


 登录后点击 进入工作台,这里可以查看应用信息,如果还没有创建过应用就添加新应用。


c72322d1b7424fbb91371c72dac49977.png


 在友盟上创建应用,获取AppKey,


24ae9a7e9adb42769e3e17aaa322f397.png


 注册应用。此时AppKey已经生成了,然后选择需要开通的产品,这里选择应用性能监控U-APM。


dbf411de25ab4441996d6e768ddc3c34.png


 确认开通。


5ef638caf87e46fe8dbb9b66a0892a43.png


 复制这个App Key到自己的项目中,一会儿会用到。打开项目的build.gradle,添加maven库。两处地方,同一句代码:


maven { url 'https://repo1.maven.org/maven2/' }

492a0fdb2e5444049a380da29d6d2753.png

a01c9845b1794b46a7bd8ea8edf08f2b.png



 然后是打开app模块的build.gradle,在dependencies中添加如下代码:


// 友盟基础组件库(所有友盟业务SDK都依赖基础组件库)
    implementation "com.umeng.umsdk:common:9.4.2" //(必选)
    implementation "com.umeng.umsdk:asms:1.4.1" // asms包依赖(必选)
    implementation "com.umeng.umsdk:apm:1.4.2" // U-APM包依赖(必选)

4dbad771c2c24aed8514bdc87a200eca.png


 然后Sync Now,同步一下项目。


 由于友盟的SDK需要获取手机的设备信息和网络状态,因此需要在AndroidManifest.xml中配置相应的权限


<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
  <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
  <uses-permission android:name="android.permission.INTERNET"/>


 其中READ_PHONE_STATE需要动态申请。


 然后就是初始化了,这里要注意一点就是需要在在《隐私政策》中向用户告知使用友盟SDK,参考条款如下: 使用SDK名称:友盟SDK 服务类型:请按SDK功能填写,如应用性能监控平台 U-APM 收集个人信息类型:设备信息(IMEI/MAC/Android ID/IDFA/OpenUDID/GUID/SIM 卡 IMSI 地理位置信息等) 隐私权政策链接:https://www.umeng.com/page/policy

这个隐私协议的弹窗理应做成类似这样的效果。假设这是你之前的隐私政策,


 那么你需要在这个里面加上关于友盟+SDK的使用说明。然后用户同意后才能进行这个初始化的操作,在Application的onCreate中进行。这里有一个预初始化和一个正式初始化,预初始化在程序第一次安装运行时使用。

我们可以通过缓存去做处理,比如下图所示:


64808eee6e4d443a9658d50bc1c08270.png


这里我通过缓存的方式判断用户是否有同意隐私政策,第一次进来肯定是没有同意的,因此会走else,而我们在同意隐私政策的时候再进行一次正式的初始化就可以了,可以如下图这样写。


027d7dc946894e07b848a0a334db98d5.png


这样就可以了,运行效果如下图所示;


55a838bbf8f1453bb0b48543f048ac4d.gif


 至于改动的源码可以去我的GitHub上去查看,GoodWeather好了,现在基本上就完成了对接的工作,下面就来使用它。


2. 使用


① 日志使用


 当对接了友盟SDK之后,就会打印友盟的相关日志,而上线的时候就不用再打印了。可以通过


UMConfigure.setLogEnabled(boolean)


设置关闭。


② 崩溃分析


 完成了SDK对接之后,即可使用Java、Native崩溃分析、ANR分析功能,无需额外其他接入操作。如果需要对Native进行采集可以这样写:


//针对于Native崩溃信息采集
        final Bundle customInfo = new Bundle();
        customInfo.putBoolean("mCallNativeDefaultHandler",true);
        CrashApi.getInstance().updateCustomInfo(customInfo);


 崩溃回调(自定义字段)


//崩溃回调
        UMCrash.registerUMCrashCallback(new UMCrashCallback(){
            @Override
            public String onCallback(){
                return "App程序崩溃了";
            }
        });


 自定义异常接口


 在开发中通常有自己异常try catch,那么也可以将catch中的异常通过友盟的接口传到后台去,然后开发者去查看。


try {
            // 抛出异常的代码
        } catch (Exception e){
            UMCrash.generateCustomLog(e,"UmengException");
        }


 使用


0794dc2040de4e1a9720f4afe042e9bc.png


③ 自定义版本号


 有时候线上可能有多个版本那么,可以通过自定义版本号API,使SDK所上报数据绑定您指定的App版本信息。


UMCrash.setAppVersion("1.0.0", "release", "0001");


使用


65ffcc56c86b4669ab28436c165d95c2.png


 有了这些,你就可以等着程序报错的日志上传到友盟上了,有了这些,你就可以等着程序报错的日志上传到友盟上了,点击:https://at.umtrack.com/PXPDCu进入U-APM


73b16f475eea4b188cdbfb1fb8923550.png


 立即使用。


a8a15f0ef2f641fca14d3b62e4bb2e6f.png


 下面就可以进行相关的日志查看了,那么先来写一个bug吧。


 比如我在App的启动页的onCreate中写下这样的代码。


try {
            Thread.sleep(1000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }


 然后运行,看AS的控制台日志


653f9e17f92843179b2b3582b09463ff.png


 这个日志就很全面了,不过这是友盟SDK的日志打印,本地调试确实可以使用,那么它有没有传到平台上呢?毕竟线上项目的错误信息日志才是关键。


6e8f779378d04f1788d0886cba88295a.png


 很明显,上传了这个错误,再向下滑动去查看这个错误的详情。


0a07cfa17fee4a3cb05ceb821e2ed84a.png


 点击左边的蓝色报错处


147f149b9dd749bc9fb227262ded15c9.png


 这里告诉你报错的具体代码行,以及下方这里有你报错设备的信息,方便你去排查原因,再往下看。


dd3b6decca1842df8e2808d120cac947.png


 这里告诉你报错的原因是什么?主线程睡眠时间过长,导致的线程阻塞,程序无响应,ANR。


 这里右边的行为日志,也很不错,可以让你知道你在当前这个页面是在做什么。


1a73b919f03041d381b382e37774c2f5.png


 这里对应的是页面浏览,合理,因为我确实还没有做什么。


13ba9d9c50f44c79852c3c796530c82f.png


 而这个内存快照,就是方便你查看报错时的内存使用情况,可以酌情进行优化。


ba4fa28b0a9b432bbd39288bd155ada2.png


 最后这个自定义字段,很明显就是在代码中写的一个崩溃的回调。


d81ad20018f94c47b41f2d1cca64e222.png


 这说明我自己写的日志也上传了。


 通过介绍、接入、使用和日志分析了解到友盟 U-APM的强大,这对于线上项目来说是一个福音,提交的错误信息能够快速上传,定位到,快速解决问题。


 更多的功能使用需要开发者自行去摸索,这里只是起到一个抛砖引玉的效果,这里再次感谢友盟提供的这个机会,我们山高水长,后会有期~


相关实践学习
通过云拨测对指定服务器进行Ping/DNS监测
本实验将通过云拨测对指定服务器进行Ping/DNS监测,评估网站服务质量和用户体验。
相关文章
|
1月前
|
算法 数据处理 Android开发
掌握安卓性能优化的秘诀:电池寿命与运行效率的提升
【10月更文挑战第6天】 本文深入探讨了安卓应用开发中的性能优化技巧,重点分析了影响电池寿命和运行效率的关键因素,并提供了针对性的优化策略。通过代码优化、资源管理、后台任务处理等方法,开发者可以显著提升应用的续航能力和流畅度。同时,结合具体案例,展示了如何在实际开发中应用这些技巧,确保应用在各种场景下都能保持高效运行。本文旨在为安卓开发者提供实用的性能优化指导,助力其打造更优质的应用体验。
41 2
|
3月前
|
IDE 开发工具 Android开发
安卓与iOS开发环境对比:选择哪个平台开始你的移动应用之旅?
【8月更文挑战第12天】在移动应用开发的世界中,安卓和iOS是两个巨头,它们各自拥有独特的开发环境和生态系统。本文将深入探讨这两个平台的开发环境,包括它们的编程语言、工具、社区支持和市场覆盖度等方面。无论你是新手开发者还是有经验的专业人士,了解这些差异都将帮助你做出更明智的决策,选择最适合你项目需求和个人技能的平台。
48 1
|
3月前
|
缓存 监控 Android开发
探索iOS与安卓开发中的性能优化策略
在移动应用开发的竞技场上,iOS和安卓这两大操作系统不断推动着技术的边界。性能优化,作为提升用户体验的关键因素,已成为开发者们关注的焦点。本文将深入探讨两大平台上的性能优化实践,揭示如何通过工具、技术和策略来提升应用的响应速度和流畅度,同时考虑到电池寿命和内存管理等关键指标。
|
4月前
|
存储 Java 编译器
🔍深入Android底层,揭秘JVM与ART的奥秘,性能优化新视角!🔬
【7月更文挑战第28天】在Android开发中,掌握底层机制至关重要。从Dalvik到ART, Android通过采用AOT编译在应用安装时预编译字节码至机器码,显著提升了执行效率。ART还优化了垃圾回收,减少内存占用及停顿。为了优化性能,可减少DEX文件数量、优化代码结构利用内联等技术、合理管理内存避免泄漏,并使用ART提供的调试工具。
115 7
|
6天前
|
Android开发 开发者
Android性能优化——内存管理的艺术
Android性能优化——内存管理的艺术
|
12天前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
25 5
|
12天前
|
缓存 数据库 Android开发
安卓开发中的性能优化技巧
【10月更文挑战第29天】在移动应用的海洋中,性能是船只能否破浪前行的关键。本文将深入探讨安卓开发中的性能优化策略,从代码层面到系统层面,揭示如何让应用运行得更快、更流畅。我们将以实际案例和最佳实践为灯塔,引领开发者避开性能瓶颈的暗礁。
29 3
|
26天前
|
开发工具 Android开发 iOS开发
Android vs iOS:构建移动应用时的关键考量####
本文深入探讨了Android与iOS两大移动平台在开发环境、性能优化、用户体验设计及市场策略方面的差异性,旨在为开发者提供决策依据。通过对比分析,揭示两个平台各自的优势与挑战,帮助开发者根据项目需求做出更明智的选择。 ####
|
30天前
|
存储 缓存 网络协议
5个Android性能优化相关的深度面试题
本文涵盖五个Android面试题及其解答,包括优化应用启动速度、内存泄漏的检测与解决、UI渲染性能优化、减少内存抖动和内存溢出、优化网络请求性能。每个问题都提供了详细的解答和示例代码。
24 2
|
1月前
|
监控 测试技术 Android开发
掌握安卓性能优化的关键策略
【10月更文挑战第7天】 在移动应用开发领域,性能优化是一项至关重要的任务。本文将探讨安卓应用性能优化的重要性、关键策略以及实际操作建议,帮助开发者提升应用的用户体验和竞争力。通过深入浅出的方式,我们将从背景介绍到具体实践,全面解析安卓性能优化的各个维度。