Skip to content

Android(9): 国产机的那些坑

clarkehe edited this page Aug 14, 2016 · 13 revisions

oppo r7手机在开启省电模式时,后台服务进程会挂起

最近遇到三个Bug, 都是在一台oppo r7手机上出现。提取了日志分析分析,代码逻辑没有什么问题。计划是这三个问题先放一放,但今天从测试那拿到了这台手机。立马安装Debug包,操作并还原了现场。

看日志发现服务进程(服务进程是App的私有独立进程)中的一个线程好像挂起了。服务进程中有个线程是每隔0.5秒输出一个日志,在服务进程所在App退到后台后,过几秒钟日志就停止了输出。会不会是服务进程被回收了呢?adb shell ps命令查看,服务进程还在。

启动服务进程对应App,日志输出就恢复了。另外,观察到在停止输出日志后,服务进程的状态发生了变化:由S变成了T

查询了Linux进程状态管理的相关资料,S与T代表的进程的不同状态。

S Interruptible sleep (waiting for an event to complete)
T Stopped, either by a job control signal or because it is being traced.
参考资料:Linux 进程状态 说明

状态T,除了因为进程被调试,还有个原因,是被强制挂起。这里服务进程为什么会被强制挂起呢?经过分析,发现是开启了Oppo手机的省电模式,就会出现这个问题,关了省电模式就正常了。

看来Oppo手机省电模式其中的一策略就是将非活动App的相关进程挂起,不抢占CPU时间片。

既然进程可能被强制挂起,也能被恢复。在有Root权限的情况,我们可写一个Native的程序对服务进程的状态进程检查,发现被挂起了,可进行恢复。恢复的方式也简单,调用一个系统命令就可以了:

kill -CONT [pid]
参考资料:How to suspend and bring a background process to foreground

将服务进程强制恢复后,服务进程中的线程就开始执行了,开始有日志输出。

微信也是多进程的App(参考:微信Android客户端后台保活经验分享),为了防止微信的CoreService(push)进程也被挂起而收不到消息,oppo手机默认对微信加了白名单。

如果被挂起的进程有UI,如有悬浮窗口,这个UI的刷新也会停止。

小米手机收不到静态广播

在Manifest中注册的静态广播,即使app没有运行,也应该能收到,系统会在收到广播时,启动注册广播的app。

由于项目需要,需要监听app安装与卸载时的广播,可在小MI手机上app没有运行时,就收不到广播。测试发现,小米手机有一个app自启动的管理功能,如果app没有设置为请允许自启动,在有注册系统广播时,app不会被启动,也就收不到广播了。

        <!--监听系统广播现在只加了应用安装和卸载其他的也可以加在这个里面-->
        <receiver android:name=".screen.SystemBroadcastReceiver">
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_ADDED"/>
                <action android:name="android.intent.action.PACKAGE_REMOVED"/>
                <data android:scheme="package"/>
            </intent-filter>
        </receiver>
W/BroadcastQueueInjector: Unable to launch app com.xx.xx/10095 for broadcast Intent { act=android.intent.action.PACKAGE_REMOVED dat=package:com.ishehui.X1015 flg=0x4000010 (has extras) }: process is not permitted to autostart

广播不可靠,于是改为每次全量扫描app,然后比较差异的方法来解决。

小米、OPPO、华为等悬浮窗权限

小MI手机是最早对悬浮窗进行管理的系统了(当然,这也跟app滥用悬浮窗,给用户造成很大干扰有关)。后来android系统也自带了悬浮窗的管理,但没有开放出来;OPPO、华为等手机,就在android系统基础上加了管理的入口。

Clone this wiki locally