关于BOOT_COMPLETED广播-自启动

文章摘要:
1、BOOT_COMPLETED在ActivityManagerService中由系统发送。
2、应用可以监听该广播,成为自启动权限,但是这样会有很多缺点,最大的缺点就是拖慢开机进度,影响用户体验。
3、开机状态会sys.boot_completed,可以通过该属性状态得到开机状态。

一、BOOT_COMPLETED广播是什么?
1、BOOT_COMPLETED是系统在开机加载完毕后发送的。如下:

/**
     * Broadcast Action: This is broadcast once, after the system has finished
     * booting.  It can be used to perform application-specific initialization,
     * such as installing alarms.  You must hold the
     * {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission
     * in order to receive this broadcast.
     *
     * <p class="note">This is a protected intent that can only be sent
     * by the system.
     */
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";

从注释可以看出,该广播需要权限才能接收,并且只有系统有权限发送它。
2、接收BOOT_COMPLETED广播,需要权限,该权限:android.Manifest.permission#RECEIVE_BOOT_COMPLETED。
如下是系统对该权限的介绍:

    <!-- Allows an application to receive the
         {@link android.content.Intent#ACTION_BOOT_COMPLETED} that is
         broadcast after the system finishes booting.  If you don't
         request this permission, you will not receive the broadcast at
         that time.  Though holding this permission does not have any
         security implications, it can have a negative impact on the
         user experience by increasing the amount of time it takes the
         system to start and allowing applications to have themselves
         running without the user being aware of them.  As such, you must
         explicitly declare your use of this facility to make that visible
         to the user. -->
    <permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"
        android:permissionGroup="android.permission-group.APP_INFO"
        android:protectionLevel="normal"
        android:label="@string/permlab_receiveBootCompleted"
        android:description="@string/permdesc_receiveBootCompleted" />
  • a、从ProtectionLevel来看,应用可以申请该权限。android:protectionLevel=”normal”
  • b、如文中所述,申请该权限,有许多缺点。
    • I、增加系统启动的时间。因为系统启动过程中,广播接收方会收到广播,并可以启动自身或者加载某些资源。
    • II、自启动,不经用户确认。应用都说在用户的点击或者请求发起下启动的,自启动可以绕过用户,自我自动。
    • III、不要想着自己的小行为用户觉察不到,系统会将自启动的应用程序形成一份列表名单,show给用户,并交由用户管理。

《关于BOOT_COMPLETED广播-自启动》 隐私授权

二、如何接收该广播。
1、前面提到了,接收BOOT_COMPLETED广播,需要权限,该权限:android.Manifest.permission#RECEIVE_BOOT_COMPLETED。
在AndroidManifest.xml中增加权限信息:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

2、增加广播注册。
在AndrodManifest.xml中,增加广播注册信息:

<receiver android:name="com.example.androidtest.BootCompleteReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>

三、BOOT_COMPLETED系统如何发送的。
1、在系统启动的过程中,ActivityManagerServie发送的该广播。
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java#finishBooting

if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
    // Start looking for apps that are abusing wake locks.
    Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
    mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);
    // Tell anyone interested that we are done booting!
    SystemProperties.set("sys.boot_completed", "1");

    // And trigger dev.bootcomplete if we are not showing encryption progress
    if (!"trigger_restart_min_framework".equals(SystemProperties.get("vold.decrypt"))
        || "".equals(SystemProperties.get("vold.encrypt_progress"))) {
        SystemProperties.set("dev.bootcomplete", "1");
    }
    for (int i=0; i<mStartedUsers.size(); i++) {
        UserStartedState uss = mStartedUsers.valueAt(i);
        if (uss.mState == UserStartedState.STATE_BOOTING) {
            uss.mState = UserStartedState.STATE_RUNNING;
            final int userId = mStartedUsers.keyAt(i);
            Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED, null);
            intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
            intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
            broadcastIntentLocked(null, null, intent, null,
                    new IIntentReceiver.Stub() {
                        @Override
                        public void performReceive(Intent intent, int resultCode,
                                String data, Bundle extras, boolean ordered,
                                boolean sticky, int sendingUser) {
                            synchronized (ActivityManagerService.this) {
                                requestPssAllProcsLocked(SystemClock.uptimeMillis(),
                                        true, false);
                            }
                        }
                    },
                    0, null, null,
                    android.Manifest.permission.RECEIVE_BOOT_COMPLETED,
                    AppOpsManager.OP_NONE, true, false, MY_PID, Process.SYSTEM_UID,
                    userId);
        }
    }
    scheduleStartProfilesLocked();
}

2、从上面粘贴的代码中,我们可以得出如下结论。

  • a、开机启动广播,是区分多用户的。
  • b、在开机广播发送的流程中,会向系统写入sys.boot_completed,我们依据它可以得出当前系统是否已开机加载结束,这对一些系统服务或者app判断应用状态很有效。
SystemProperties.set("sys.boot_completed", "1");
    原文作者:Android那些事儿
    原文地址: https://www.jianshu.com/p/679dc03ee650
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞