Android开发一个持久运行的app的一些经验

最近由于项目的需要,需要开发一个监控性质app,功能很简单,就是定时调用服务器的一些接口,如果返回失败就要向相关人员发出警报。需求很简单,重点有两个

1、  一直运行,这需要app没有内存泄漏,否则一直运行的话,肯定会因为系统内存不足而造成程序崩溃的。内存泄漏的现象在app运行的时候倒是没有发生,或者说不严重吧。

2、  尽量不要因为程序发生异常而导致访问失败,造成警报的误发,这里倒是遇见了一个比较有意思的问题,跟大家分享一下。这个问题就是TimeoutExceptions,不知道有没有人和我一样,一开始把这个异常认为和SocketTimeoutException一样,是一种网络超时。

但是在app运行的过程中,访问400多次接口(每2分钟一次),就有三十多次这个异常发出,而网络情况是比较稳定的,如果是网络超时,发生的概率有点太高了吧,我不得不仔细查了查这个异常。原来TimeoutExceptions跟网络没有关系,是一种系统任务超时,其具体的异常详情为

java.util.concurrent.TimeoutException:android.os.BinderProxy.finalize() timed out after 10 seconds

atandroid.os.BinderProxy.destroy(Native Method)

atandroid.os.BinderProxy.finalize(Binder.java:459)

atjava.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:187)

atjava.lang.Daemons$FinalizerDaemon.run(Daemons.java:170)

at java.lang.Thread.run(Thread.java:841

分析一下异常发生的原理,由日志可看出这个异常发生在对象的finalize方法里面,而大家都知道finalize方法是在虚拟机执行GC的时候执行的,finalize方法如果10s内没有运行完,系统就会报TimeoutExceptions。而Finalize方法为什么会耗时超过10s还没有运行完呢,这个主要是因为android系统的休眠机制,android系统休眠会让大部分的进程的线程进入休眠,也包括了GC线程。所以当android系统进入休眠的时候,正巧碰上你的进程的GC进程运行到某个对象的finalize方法,这个异常就产生了。一般的app是不会遇到这种情况的,只有长时间一直运行的app才可能碰到。而什么是系统休眠,本人理解就是设备黑屏了就是进入休眠了。

所以要避免这个异常,就要防止系统进入休眠,这里提供一个经过本人验证的简单有效的方法,就是在app的某个界面的布局文件的跟元素中添加这个属性android:keepScreenOn="true",如下所示

xmlns:android="http://schemas.android.com/apk/res/android"
   
xmlns:app="http://schemas.android.com/apk/res-auto"
   
xmlns:tools="http://schemas.android.com/tools"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent"
   
android:orientation="vertical"
   
android:divider="@color/colorPrimaryDark"
   
android:dividerPadding="10dp"
   
android:keepScreenOn="true">

然后让app停留在该页面上,这样就能保持设备一直处于亮屏状态,应该也就不会休眠了,经过实际测试也的确如此,设备一直亮屏,而且调了1800多次接口(历时大约60小时)也没有发生一次TimeoutExceptions。

这里只是分享一些自己小小的经验,如有不足敬请谅解。

你可能感兴趣的:(Android开发一个持久运行的app的一些经验)