Android自启动管控

1. 自启动管控需求来源

自启动、关联启动、交叉启动、推送启动等现象的泛滥除了对个人信息保护带来隐患外,还会导致占用过多的系统CPU和内存资源,造成系统卡顿、发热、电池消耗过快;还可能引入一些包含“恶意代码”的进程在后台隐蔽启动,避开了杀毒软件等的查杀,威胁到用户通信秘密、财产安全。

2. 关联启动现象

2.1 常见的问题

1.全家桶启动现象】原生机器中,打开一个百度地图,放置一段时间后发现百度助手、百度新闻、去哪儿、美团等 APP后台自启动甚至弹出消息提醒?

·除此之外腾讯系、阿里系应用也会有。因为日活率是一款App的核心绩效指标,日活量不仅反应了应用的受欢迎程度,同时反应了产品的变现能力,进而直接影响盈利能力和企业估值。App会利用保活技术尽量可能自启动本身和家族内其他应用。

2.为什么应用可以在用户不知情的情况后台自动运行?

·因为Android的理念是开放的, 应用拥有太多自主权限:前台保活、系统唤醒、推送服务。下文会介绍。

2.2 关联启动的树形图

App启动基础:Android 四大组件Activity\BroadCast\Service\ContentProvid是App启动的基本单元,大部分APP会直接或间接地依赖于这四种方式进行启动。​

启动分为用户知情和用户不知情2种情况:

·用户知情:

1.用户主动在Launcher界面打开APP

2.APP1 点击分享网页到 APP2

3.Android-语音助手打开 APP2

4.Android GCM 推送弹出 APP2 通知

5.等等 对于用户知情的场景,我们不需要进行管控。

·用户不知情:

1.APP1 利用1x1像素点创建很难被看见界面使用startActivity形式来启动 APP-X

2.APP1 利用开机、亮灭屏、解锁、push sdk、网络变化、USB插拔、时区变化、电量变化等广播事件使用sendBroadCast形式启动 APP-X

3.APP1 利用push sdk、同步服务、JobScheduler服务、服务重启等事件使用bindService/startService 启动 APP-X

4.APP1 利用push sdk、账号服务等事件使用contentProvider 启动 APP-X

即1个应用可以在不同事件以多种启动形式关联启动多个应用,像传染病一样在我们不知情的情况下在后台大量启动一些可能没必要启动的应用。这种滥用自启动的行为,危害系统性能,功耗和安全。

3. 自启动管控方案

3.1 方案集成形式

少量framework 插桩事件的patch +策略 jar包+apk 集成到项目

3.2 自启动工作流

自启动管控在AMS中Activity、BroadCast、ConcentProvider、Service等涉及应用启动相关的函数进行事件插桩(目前18处),且每个事件插桩对应一个拦截相关策略,汇合并构成自启动的拦截与放行方案。

拦截的思想:用户可见或可感知或进程优先级高的进程不管控。重点管控不可见且重要度低后台启动或关联启动其他应用的行为。

一些拦截日志

// 拦截 com.chaozh.iReaderFree 利用JobSchedulerService后台自启动

04-24 03:22:42.560  1329  1329 D Smart_Restrictor: restrict:true t=20 t={u:10216 pkg:com.chaozh.iReaderFree com.chaozh.iReaderFree/com.umeng.message.UmengMessageCallbackHandlerService label:job } c=null r=Malicious!

// 拦截 APP1 关联启动 APP2

04-24 03:22:46.844  1329  6418 D Smart_Restrictor: restrict:true t=21 t={u:10203 pkg:com.baidu.BaiduMap com.baidu.BaiduMap/com.baidu.android.pushservice.PushService } c={pkg:com.baidu.netdisk p:27975 u:10202 newj:800 oldj:800 jt:started-services s:false name:com.baidu.netdisk acts:false sers:true sui:false ic:false} r=Malicious!

05-27 20:42:59.511 25315  3864 D Smart_Restrictor: restrict:true t=1 t={com.tencent.karaoke.maindex.legend.Phosphene} c=com.anjuke.android.app r=null

05-27 20:43:00.122 25315  3847 D Smart_Restrictor: restrict:true t=1 t={com.cleanmaster.getui.InvokeActivity} c=com.anjuke.android.app r=null

// 拦截推送服务后台自启动

04-24 03:31:07.379  1337  1337 D Smart_Restrictor: restrict:true t=20 t={u:10208 pkg:com.autohome.usedcar com.autohome.usedcar/io.rong.push.rongpush.PushService label:job } c=null r=Malicious!

// 拦截空进程启动

05-27 20:41:30.443 25315 25377 D Smart_Restrictor: restrict:true start application t={com.anjuke.android.app} c=null r=Start empty app

3.3 例子-广播拦截机制

在广播拦截中我们分为应用未启动和应用运行时2种策略

·应用未启动时若存在以下情况会被拦截

1.一些系统发出的广播进行拉起,例如开机关播、网络和硬设变化相关广播、亮灭屏广播、锁屏广播、应用安装卸载等,会被拦截;其实谷歌每次大版本升级其实加强安全的优化,也包含广播使用权限的加强,例如从最开始从不限制任何广播,到限制部分静态广播,到限制部分动态广播。可能是借鉴了中国手机厂商自启动拦截的思路。

2.第三方应用后台关联拉起的行为,会被拦截。

3.白名单的应用不受限制;

·应用已启动且正在运行

1.应用处于不可感知状态,系统的一些广播拉起,会被拦截

2.应用使用自己的广播或stricky类型不受限制;

### Kotlin 实现应用程序自启动及跳转至自启动管理页面 为了使应用程序能够在设备重启后自动启动,在 Android 中通常有两种方式来实现这一功能: #### 方式一:通过广播接收器监听系统启动完成事件 当手机开机完成后会发送 `BOOT_COMPLETED` 广播消息,因此可以在应用中注册一个广播接收者用于监听该广播,并在接收到此广播时启动相应的 Activity 或服务。 ```xml <receiver android:name=".BootReceiver"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> ``` 接着定义对应的 BootReceiver 类处理逻辑[^1]: ```kotlin class BootReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if ("android.intent.action.BOOT_COMPLETED" == intent?.action){ val startIntent = Intent(context, MainActivity::class.java) context?.startActivity(startIntent.apply{ flags = Intent.FLAG_ACTIVITY_NEW_TASK }) } } } ``` 需要注意的是从 Android 8.0 开始引入了后台执行限制政策,这使得直接启动 activity 变得更加困难。对于这种情况可以考虑创建前台服务作为中介间接激活目标组件[^2]。 #### 方式二:引导用户前往权限设置界面开启自启授权 由于不同厂商定制 ROM 对于 App 的管控策略有所差异,部分机型可能不会默认授予新安装的应用程序自启动权限。此时可以通过提供按钮让用户自行打开系统的相应配置项来进行调整。 以下是获取某些品牌(如小米、华为等)自带安全中心内的白名单列表路径的方法之一: ```kotlin fun gotoAutoStartSetting(activity: Activity): Boolean { try { when (Build.MANUFACTURER.toLowerCase()) { "xiaomi" -> { // 小米 val intent = Intent("miui.intent.action.APP_PERM_EDITOR") .setClassName( "com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity" ) activity.startActivity(intent) return true } "huawei" -> { // 华为 val intent = Intent() .setComponent(ComponentName( "com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")) activity.startActivity(intent) return true } // 添加其他品牌的判断... else -> {} } } catch (e: Exception) {} Toast.makeText(activity,"当前设备暂无特殊权限设置",Toast.LENGTH_SHORT).show() return false } ``` 以上代码片段展示了针对特定制造商提供的 API 访问其特有的自启动管理界面的方式。不过鉴于各版本之间可能存在变动以及隐私保护等因素的影响,建议开发者们关注官方文档更新并测试兼容性[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

法迪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值