1.1 实现 Android 系统的自启动
1.1.1.实现自己的广播接收器,在 onReceive()方法中实现要处理的逻辑
1.1.2. AndroidManifest.xml 中注册该广播接收器,申明接收广播过滤器为Boot_Completed 广播
1.1.3.申明权限
实现 Android 的自启动与一般的广播接收没有很大区别,但是有一些要注意的地方:
1.在使用 BOOT_COMPLETED 广播时,必须要 RECEIVE_BOOT_COMPLETED 权限,这是 4.0 后的修改
2.通过指定 priority 属性可以设置 BOOT_COMPLETED 广播的优先级,让该app 早于其他 app 接收到广播
3.在 4.4 下 BOOT_COMPLETED 广播是有序广播,但是不可中断(指定了FLAG_RECEIVER_NO_ABORT 字段),而在 4.4 以前,BOOT_COMPLETED 广播
是无序的
1.在使用 BOOT_COMPLETED 广播时,必须要 RECEIVE_BOOT_COMPLETED 权限,这是 4.0 后的修改
2.通过指定 priority 属性可以设置 BOOT_COMPLETED 广播的优先级,让该app 早于其他 app 接收到广播
3.在 4.4 下 BOOT_COMPLETED 广播是有序广播,但是不可中断(指定了FLAG_RECEIVER_NO_ABORT 字段),而在 4.4 以前,BOOT_COMPLETED 广播
是无序的
4.由于 4.0 后增加了 Package stopped 标志,因此处于该状态下的 app 无法收到 BOOT_COMPLETED 广播时,该状态由以下情况产生:
a. 通过反射调用隐藏接口 forceStopPackage 接口停止的应用
b.在 setting?application?detail 中点 disable 按钮,被停用的应用
c.新安装完成,从未打开和运行过的应用
a. 通过反射调用隐藏接口 forceStopPackage 接口停止的应用
b.在 setting?application?detail 中点 disable 按钮,被停用的应用
c.新安装完成,从未打开和运行过的应用
1.2 BOOT_COMPLETED 广播发送的时机
要了解 BOOT_COMPLETED 广播的发送时机就必须了解 Android 的启动流程,
简要了解 Android 的启动顺序:
1 系统启动,bootloader
2 SystemServer
3 AMS
4 Send systemReady 信号
5 Launcher start
6 Send finishBooting 信号
7 发送 BOOT_COMPLETED 广播
简要了解 Android 的启动顺序:
1 系统启动,bootloader
2 SystemServer
3 AMS
4 Send systemReady 信号
5 Launcher start
6 Send finishBooting 信号
7 发送 BOOT_COMPLETED 广播
1.3 禁止自启动的原理
通过了解 BOOT_COMPLETED 广播发送的时机和原理,我们大概可以分析出禁止自启动的几种方法:
1. 阻止应用收到 BOOT_COMPLETED 广播,在 4.0 以后,可以通过设置 app 的Package stopped 标志来实现(反射调用隐藏的 forceStopPackage 方法)
2. 通过停用应用的广播接收器来屏蔽 BOOT_COMPLETED 广播,即设置组件的android:enable 属性来停止该接收器的响应
3. 通过 kill 进程来将自启动的 app 结束掉
1. 阻止应用收到 BOOT_COMPLETED 广播,在 4.0 以后,可以通过设置 app 的Package stopped 标志来实现(反射调用隐藏的 forceStopPackage 方法)
2. 通过停用应用的广播接收器来屏蔽 BOOT_COMPLETED 广播,即设置组件的android:enable 属性来停止该接收器的响应
3. 通过 kill 进程来将自启动的 app 结束掉
1.4 禁止自启动的方法
1.4.1 forceStopPackage
通过 forceStopPackage 去禁用,不仅会停用 app 的组件,也会停止他的定时器等,同时需要 system 权限和系统签名。
1.4.2 停用组件方法
Android 文档中对 Android 的组件有如下描述:
The<application> element has its own enabled attribute that applies to allapplication components, including broadcast receivers.
即我们可以设置一个组件是否启用。
PackageManager 中提供以下两个方法:
The<application> element has its own enabled attribute that applies to allapplication components, including broadcast receivers.
即我们可以设置一个组件是否启用。
PackageManager 中提供以下两个方法:
setApplicationEnabledSetting 可以停用应用中所有的组件。
setComponentEnabledSetting 可以停用指定的组件。
该方法有以下几个需要注意的地方:
a.与 forceStopPackage 接口相比,该接口不会清空定时器等,只会启用、停用组件,因此在定时器中发送自定义广播,并且在广播中指定FLAG_EXCLUDE_STOPPED_PACKAGES 是可以唤醒组件。
b.使用 setComponentEnabledSetting 接口必须是 system 程序并具有system 签名
c.需要申明 CHANGE_COMPONENT_ENABLED_STATE 权限
使用方法:
setComponentEnabledSetting 可以停用指定的组件。
该方法有以下几个需要注意的地方:
a.与 forceStopPackage 接口相比,该接口不会清空定时器等,只会启用、停用组件,因此在定时器中发送自定义广播,并且在广播中指定FLAG_EXCLUDE_STOPPED_PACKAGES 是可以唤醒组件。
b.使用 setComponentEnabledSetting 接口必须是 system 程序并具有system 签名
c.需要申明 CHANGE_COMPONENT_ENABLED_STATE 权限
使用方法:
很遗憾,该方法只能对自己的 app 修改,而操作第三方 app 需要 system权限,即使 root 也无法使用,因此,我们需要利用 packagemanager 的cmd 实现,即 PM 命令。
命令需要 root 权限:pm enable/disable package/package.class
命令需要 root 权限:pm enable/disable package/package.class
1.4.3 Kill 进程方法
最常用的方法是通过 ActivityManager 类中的killBackgroundProcesses 接口来杀死进程,通用代码如下:
但是该方法清理的进程等级不是太高,killProcess(pid)是一种能 kill更高优先级的方法,但是该方法并不能保证进程被 kill,因为该方法只是发出 kill process 的信号,具体是否要 kill 是由系统决定的,一般来说,可以被杀死的进程如下:
a. 同包下进程
b. 同 uid 进程
c. 由本 app 在运行时生成的进程
a. 同包下进程
b. 同 uid 进程
c. 由本 app 在运行时生成的进程
1.5 查找开机启动权限的 apk
查找权限的方法有很多,这里只提供一种,即通过 packagemnager 来实现:
1.6 总结
综上,市场上一般的自启动管理 app,大多是通过获取 root 权限后使用 pm命令来禁用包含 Boot_Completed 的接收器来实现的,还有一些则是通过监控后台进程,轮询查找黑名单中的进程来 kill 掉相应的自启动程序,不仅包括开机自启动,还可以监控后台自启动,不过该方法的最大问题就是增加了系统消耗,包括内存消耗和电量消耗。另外还有一些第三方的 ROM 也带有权限管理工具,例如小米的权限管理系统,是在解析接收器的权限的时候,会将所有接收器的优先级减 1,这样其他应用的优先级将永远低于其系统 app 的优先级。
通过调查发现,用户清理进程,控制开机启动的习惯是从 windows 开始的,进程清理或者说是控制开机启动项对于 Android 系统来说并没有很大意义,如果一个 Android 系统不 root,那么第三方 app 对系统方面的控制权限基本没有,使用这些软件,一方面降低了 Android 系统的安全性,另一方面也会消耗很大的系统资源,造成恶性循环,手机越用越慢。
通过调查发现,用户清理进程,控制开机启动的习惯是从 windows 开始的,进程清理或者说是控制开机启动项对于 Android 系统来说并没有很大意义,如果一个 Android 系统不 root,那么第三方 app 对系统方面的控制权限基本没有,使用这些软件,一方面降低了 Android 系统的安全性,另一方面也会消耗很大的系统资源,造成恶性循环,手机越用越慢。