资讯详情

Android App 链式唤醒分析

Gracker | 作者

承香墨影 | 校对

https://androidperformance.com/2020/05/07/Android-App-Chain-Wakeup/| 原文

MIUI 12 以前一直是应用开发者和 Rom 开发者斗争最激烈的部分向普通消费者展示,让普通消费者知道斗争的细节。 "魔高一尺高一丈",Rom 由于代码修改权限,因为他们有更高的代码修改权限。

App 当然,开发者也不甘示弱, 各种保存拉黑科技层出不穷,甚至 Google 他们都参与了这部分斗争,并制定了各种规则来规范双方。当然,斗争对双方都有好处, 毕竟,任何一方的完全胜利都会导致 狡兔死走狗煮, 鸟尽良弓藏。

然而,双方斗争的受害者无疑是使用手机的消费者,App 如果斗争成功,那么手机上各种后台进程乱跑,杀不掉,占用 CPU 而内存,这不是消费者想看到的。 Rom 开发者斗争成功,App 体验会大打折扣,各位 App 开发者应该有深刻的理解。

从文章的最后一段可以看出,事实上,每个手机制造商都有自己的策略来处理这一套,基本上可以完成自启动和相关启动。至于隐私 ,李彦宏曾说过 “。大家想想在微信上复制一段话,打开淘宝就可以自动跳转到这个项目。不方便吗?好用吗?还想用吗?剪贴板借给我看看?

希望大家不要在隐私问题上打哈哈。技术是一把双刃剑。如果隐私落在别有用心的人手里,后果会很严重,即使不是为了自己和下一代。为什么欧盟要制定《通用数据保护条例》(General Data Protection Regulation,简称 GDPR),只是为了隐私。举个例子 ,许多国内制造商现在需要区分他们是否在欧盟购买产品。如果他们在欧盟销售,他们必须关闭收集用户数据的所有功能 ,否则,如果你抓住它,你将被罚款吐血 。至于中印,随便收集。

本文不涉及隐私,我无条件支持隐私保护 。只从技术的角度来看 ,来讲一下 MIUI 12 应用程序自启动和关联唤醒的问题。

PS: 你可能看不到我在手机上列出的一些例子,因为我用它们 Android 10 的 AOSP 大部分国产代码 Rom 这些行为已经被阻断。

解释技术名称

首先解释几个技术术语,方便大家对号入座

进程启动

在 Android 中 ,一个 App 过程包含六个部分 (必选) Activity (可选) BroadcastReceiver (可选) Service (可选) ContentProvider (可选) 子进程 (可选)

一个必选项加五个可选项,形成一个 App ,其中 Activity(可选) BroadcastReceiver(可选) Service(可选) ContentProvider(可选) 这四个也叫 Android 这四个组件之所以如此特殊,是因为它们可以单独启动。

但在四兄弟开始之前,系统会检查相应的过程是否存在,如果过程不存在 ,然后需要先启动过程,然后启动组件。我们点击桌面上的应用程序图标,实际上是他开始的 Activity ,先创建过程,再启动系统 Activity ,我们可以看到相应的界面。

一般来说,自启动和相关启动不会直接启动 Activity ,因为 Activity 用户可以感知 ,你莫名其妙地在后台给前台开了一个界面,用户每分钟都卸下你 。所以一般自启动和关联启动都是在 BroadcastReceiver (可选) Service (可选) ContentProvider (可选) 以上三篇文章。

自启动

自启动是指通过监控系统中的一些事件或文件变化,通过系统机制,不借助其他应用程序处理事情。

关联启动

关联启动是指借助其他应用程序启动自己,如起点阅读启动作家助手 \ 电信营业厅 \ 百种百词斩。

启动阻断

启动阻断也叫切断唤醒,Rom 开发人员在四个组件开始时添加逻辑判断,合格的组件可以拉动自己的过程 ,不合格组件直接返回 ,这样就达到了启动阻断的目的。

当然,还有很多工作要做,比如判断工作状态,拉合理性判断 ,一旦错误的阻断不可避免地导致用户逻辑断裂,例如,用户在一个 App 支付宝要拉起来支付 ,当你启动支付宝的支付组件时,你会阻止它,你可以想象用户的愤怒。

有了以上简单的概念,让我们简要介绍一下自启动和相关启动的技术分析 。

分析手段

Monkey

要分析应用程序的启动,首先需要安装大量的应用程序,然后执行 Monkey,让大部分过程跑起来。 Monkey 命令如下,跑完自己睡觉。

adbshellmonkey --kill-process-after-error --ignore-security-exceptions --ignore-crashes --pct-appswitch90 --pct-touch10 --throttle10000 --ignore-timeouts --ignore-native-crashes100000000 

EventLog

首先可以用 EventLog 查看过程的启动信息,EventLog 每个过程的启动和死亡信息和死亡信息。我使用以下命令来过滤过程的启动和死亡。

adblogcat-bevents|egrep"am_proc_died|am_proc_start" 

Dumpsys

主要用于这里 Dumpsys activity ,每个组件的信息主要用于分析过程

adbshelldumpsysactivity 

自启动是指通过监控系统中的一些事件或文件变化,通过系统机制不使用其他应用程序来处理事情。这些系统事件包括启动广播 / 网络变化 / 扫描媒体库等 (这里只列了一部分) 。

技术分析自启动

开机广播

用户重启手机后,系统会向注册开机广播的应用发送广播。当他们收到广播应用程序时,他们可以拉起自己,开始处理相应的逻辑 (拉起更多的过程) ,相应的广播如下:

android.intent.action.BOOT_COMPLETED 

该应用程序可以监控该广播,在用户重启手机后唤醒自己,处理自己的逻辑 ,例如,继续备份图片 / 继续同步联系人 / 检查是否有固件更新 / 推送最新新闻等操作

案例: 腾讯新闻监听开机广播拉后台进程

典型的广播接受处理记录 : com.tencent.news 的 com.tencent.news.system.BootBroadcastReceiver 组件接收了 android.intent.action.BOOT_COMPLETED 广播 ,处理了 7s ,至于怎么处理,当然是先把 com.tencent.news 拉起过程,然后执行 BootBroadcastReceiver 的 onReceive 方法。这是自启动的典型例子。

网络变化

网络变化包括网络连接 / 断开 / wifi 在移动网络切换等操作中,一旦发生这些事件,系统将向相应注册该事件的应用程序发送广播。相应的广播如下:

android.net.conn.CONNECTIVITY_CHANGE 

应用程序可以监控这个广播来执行相应的逻辑,比如你看直播,突然 wifi 断开切换成 4G 网络,应用程序可以提醒用户是否使用移动网络继续观看,毕竟,网络直播仍然非常耗费流量。

在下图中,我们可以看到五个广播接收器监 (只显示五个 ,其实有 200 多个) ,监听到网络变化后拉起自身

图中 packageName 是应用的包名,name 是启动组件。

android.net.wifi.STATE_CHANGE 

媒体库扫描

系统监听到文件变化或者存储盘变化也会发通知给各个应用,比如说增加了一个图片或者文档,其对于的广播如下。

android.intent.action.MEDIA_SCANNER_STARTED
android.intent.action.MEDIA_SCANNER_FINISHED
android.intent.action.MEDIA_EJECT

下面是一个典型的监听媒体库扫描广播进行自启动的案例:

com.jd.jrapp 的广播接收器 com.jd.jrapp.library.longconnection.receiver.BootReceiver 监听到 android.intent.action.MEDIA_SCANNER_STARTED 广播后,启动自己进程开始处理。

三方 SDK - 个推

个推是各个应用接入的一个三方 SDK,用于消息推送,但其实个推也集成了上面说的哪几种自启动的方式,包括 BOOT_COMPLETED、CONNECTIVITY_CHANGE、USER_PRESENT 这些。

关于个推,由于可定制型比较强,比如在项目源码中添加一个继承自 com.igexin.sdk.PushService 的自定义 Service 就可以 ,所以从 EventLog 和 Dumpsys 没法直接看出来哪个用了个推来保活或者相互唤醒,不过其对于的子进程得设置为 :pushservice ,可以根据这个做判断 (有可能不准)

所以我们直接看个推的配置文档。

<service
    android:
    android:permission="android.permission.BIND_JOB_SERVICE"
    android:exported="false"
    android:label="NotificationCenter"
    android:process=":pushservice"/>
<receiver android: >
    <intent-filter>
        <action android: />
        <action android: />
        <action android: />
        <!-- 以下三项为可选的 action 声明,有助于提高 service 存活率 -->
        <action android: />
        <action android: />
        <action android: />
    </intent-filter>
</receiver>
<activity
    android:
    android:excludeFromRecents="true"
    android:exported="false"
    android:process=":pushservice"
    android:taskAffinity="com.igexin.sdk.PushActivityTask"
    android:theme="@android:style/Theme.Translucent.NoTitleBar" >
</activity>
<activity
     android:
     android:excludeFromRecents="true"
     android:exported="true"
     android:process=":pushservice"
     android:taskAffinity="com.igexin.sdk.PushActivityTask"
     android:theme="@android:style/Theme.Translucent.NoTitleBar"/>

像最前面同提到的 BootComplete ,com.ss.android.ugc.aweme:pushservice 可能就是接入了个推

关联启动的技术分析

关联启动指的是借助其他应用来启动自己 ,比如说很多 App 接入了同一个 SDK ,那么一旦你启动了接入这个 SDK 的应用 ,那么这个 SDK 就可以启动同样接入了这个 SDK 的其他应用,达到关联唤醒的目的

这个 SDK 可以是 BAT 集团内部自研的通用 SDK ,也可以是三方提供的 SDK ,根据我自己的调试来看 ,大家提到的 xxx 启动了 xxx,大部分都是通过三方 SDK 来实现的 ,大部分是用了极光推送。

下面就以一个案例来看极光推送是怎么利用一个已经启动的 App 来启动另外一个没有启动的 App 的。

首先我们看 EventLog 可以看到进程的启动信息 ,包括进程名,进程 pid ,启动的组件,启动的组件类型。

[0,19428,10195,com.qq.reader,service,{com.qq.reader/cn.jpush.android.service.DaemonService}]

上面这条 Log 解释一下就是:

  1. 启动进程:com.qq.reader(QQ 阅读)

  2. 启动 pid:19428

  3. 启动组件:cn.jpush.android.service.DaemonService

  4. 组件类型:service

执行 adb shell am force-stop com.qq.reader ,强制杀掉 QQ 阅读 ,观察 EventLog,从下面的可以看到 ,QQ 阅读的进程被拉起,拉起的是 Service 这个组件,其具体的内容是 com.qq.reader/cn.jpush.android.service.DaemonService

当然从 Event Log 里面我们看不出来是谁拉起了这个 Service ,这时候就需要 dumpsys activity 的帮助了,由于是 Service 组件被拉起,那么我们可以看 com.qq.reader 的 ServiceRecord ,其内容如下,可以看到其 Connections 一栏,是被 com.qidian.QDReader:pushcore 这个进程拉起的

那么对应的 ,在小米的 MIUI 12 关联启动界面就会显示 : 起点读书 在 8:48 分拉起了 QQ 阅读 (由于没有小米手机,所以没法截图,大家自己看高票答案 https://www.zhihu.com/question/391494145 自己脑补一下就可以了)

极光推送的官方文档其实也说的很清楚,提供了被拉起和拉起别人的功能,看你自己怎么用。

手机厂商应对

最前面的有说到,进程管理是应用开发者和 Rom 开发者斗争最激烈的部分 ,MIUI 选择了将斗争的过程展示给了普通消费者,让普通消费者也知道了这场斗争的细节。其他的厂商也做了相同的事情,否则整个系统基本上是没法用的,就像我手上现在这台测试用的 pixel,不断有进程因为整机内存太小被 LMK 杀掉,然后马上被各种手段重新启动,耗电极快,卡的连娘都不认识了。

我们从极光和个推的官方文档就可以看到各个手机厂商的应对方法和开关的界面,这里列出来是方便大家进去看一下,因为各个手机厂商的白名单配置不一样,或者有时候用户自己改过但是忘记了 ,都可以进去重新设置一下 ,对于那些你退出了就不想让他继续活动的应用 ,果断去掉白名单。

极光推送白名单配置

个推白名单配置

  • 自启动管理:需要把应用加到【自启动管理】列表,否则杀进程或重新开机后进程不会开启,只能手动开启应用

  • 后台应用保护:需要手动把应用加到此列表,否则设备进入睡眠后会自动杀掉应用进程,只有手动开启应用才能恢复运行

  • 通知管理:应用状态有三种:提示、允许、禁止。禁止应用则通知栏不会有任何提醒

  • 自启动管理:需要把应用加到【自启动管理】列表,否则杀进程或重新开机后进程无法开启

  • 通知栏推送:关闭应用通知则收到消息不会有任何展示

  • 自启动管理:需要将应用加入 “i 管家” 中的【自启动管理】列表,否则重启手机后进程不会自启。但强制手动杀进程,即使加了这个列表中,后续进程也无法自启动。

  • 冻结应用管理:需要将应用加入纯净后台,否则屏状态下无法及时收到消息

  • 自启动管理:将应用加入【自启动管理】列表的同时,还需要到设置 - 应用程序 - 正在运行里锁定应用进程,否则杀进程或者开机后进程不会开启,只能手动开启应用

  • 自启动管理:需要把应用加到【自启动管理】列表,否则杀进程或重新开机后进程无法开启

  • 省电策略:需要禁用应用省电策略,否则后台几分钟后会被系统限制联网

  • MIUI 7 神隐模式:允许用户设置后台联网应用,开启后应用即可在后台保持联网,否则应用进入后台时,应用无法正常接收消息。【设置】->【电量和性能】->【神隐模式】

本文对你有帮助吗?是最大的支持,谢谢!


热文推荐

  • ViewGroup 默认顺序绘制子 View,如何修改?什么场景需要修改绘制顺序?

  • OkHttp 支持 WebSocket,鉴权/长连接保活

  • TCP 握手/回收,出现意外,如何处理?

公众号后台回复成长『』,将会得到我准备的学习资料。

标签: jd204u电量变送器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台