Android10 开机向导流程

        最近在弄开机向导,网上查了查,基本都是参照系统的​​​​​​Provision应用来做的,而且还要将apk打包到系统目录下的pri-app目录下,打包到其他目录下不行,参照着做是没问题,但是好奇为什么要这么做?调用流程是怎样?这就是接下来要来探究的。

launcher启动

        以如下模拟器为例来看Google首次开机涉及到哪些launcher

       开机时过滤日志ActivityTaskManager

2023-01-29 16:44:03.285 1993-1993/system_process I/ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.settings/.CryptKeeper} from uid 0
2023-01-29 16:44:03.289 1993-1993/system_process I/ActivityTaskManager: Loaded persisted task ids for user 0
2023-01-29 16:44:04.089 1993-2096/system_process I/ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.google.android.setupwizard/.SetupWizardActivity} from uid 0
2023-01-29 16:44:05.129 1993-2347/system_process I/ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.android.settings/.FallbackHome} from uid 0
2023-01-29 16:44:06.212 1993-2032/system_process I/ActivityTaskManager: Displayed com.android.settings/.FallbackHome: +1s80ms
2023-01-29 16:44:14.244 1993-2610/system_process I/ActivityTaskManager: Config changes=3 {1.0 310mcc260mnc [en_US] ldltr sw392dp w392dp h757dp 440dpi nrml long port finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 - 1080, 2280) mAppBounds=Rect(0, 0 - 1080, 2148) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_0} s.6}
2023-01-29 16:44:14.264 1993-2610/system_process I/ActivityTaskManager: Override config changes=3 {1.0 310mcc260mnc [en_US] ldltr sw392dp w392dp h757dp 440dpi nrml long port finger qwerty/v/v dpad/v winConfig={ mBounds=Rect(0, 0 - 1080, 2280) mAppBounds=Rect(0, 0 - 1080, 2148) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=undefined mAlwaysOnTop=undefined mRotation=ROTATION_0} s.6} for displayId=0
2023-01-29 16:44:16.159 1993-2024/system_process I/ActivityTaskManager: Loading recents for user 0 into memory.
2023-01-29 16:44:16.436 1993-3016/system_process I/ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.google.android.sdksetup/.DefaultActivity} from uid 0
2023-01-29 16:44:19.084 1993-2047/system_process I/ActivityTaskManager:   Force finishing activity ActivityRecord{cb6abf3 u0 com.google.android.sdksetup/.DefaultActivity t4}
2023-01-29 16:44:19.086 1993-2047/system_process I/ActivityTaskManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000100 cmp=com.google.android.apps.nexuslauncher/.NexusLauncherActivity} from uid 0
2023-01-29 16:44:19.234 1993-2028/system_process W/system_server: Long monitor contention with owner PackageManager (2047) at void com.android.server.wm.ActivityTaskManagerService$LocalService.cleanupDisabledPackageComponents(java.lang.String, java.util.Set, int, boolean)(ActivityTaskManagerService.java:6820) waiters=0 in void com.android.server.wm.InputMonitor$1.run() for 150ms
2023-01-29 16:44:26.653 1993-2032/system_process I/ActivityTaskManager: Displayed com.google.android.apps.nexuslauncher/.NexusLauncherActivity: +5s191ms

 涉及到应用包括:

1、com.android.settings/.CryptKeeper

2、com.google.android.setupwizard/.SetupWizardActivity

3、com.android.settings/.FallbackHome

4、com.google.android.sdksetup/.DefaultActivity

5、com.google.android.apps.nexuslauncher/.NexusLauncherActivity

 开机涉及到这么多页面,但我们实际能感觉到的就只有FallbackHome和NexusLauncherActivity两个页面,NexusLauncherActivity就是我们最终显示的launcher了,FallbackHome则是开机动画完成后出现的一个加载动画(Pixs is Starting ...)。

        再说launcher启动前,先来看下验证的几个方法:

    fun testApi() {
        val homeIntent = Intent(Intent.ACTION_MAIN)
        homeIntent.addCategory(Intent.CATEGORY_HOME)
        val resolvedType = homeIntent.resolveTypeIfNeeded(contentResolver)
        val queryIntentActivities = AppGlobals.getPackageManager().queryIntentActivities(
            homeIntent, resolvedType,
            PackageManager.GET_SHARED_LIBRARY_FILES, 0
        )
        for (parcelable in queryIntentActivities.list) {
            val toString = (parcelable as ResolveInfo).toString()
            Log.d(ZZQ_TAG, "queryIntentActivities: "+toString)
        }
        val resolveIntent = AppGlobals.getPackageManager().resolveIntent(
            homeIntent, resolvedType,
            PackageManager.GET_SHARED_LIBRARY_FILES, 0
        )
        Log.d(ZZQ_TAG, "resolveIntent: "+resolveIntent.toString())
    }

         queryIntentActivities()查询到的就是当前所有匹配到的activity信息,而resolveIntent()就是获取当前优先级最高的launcher,用这个方法测试时,需要注意这个应用要是系统应用,有系统签名和menifest中需要加android:sharedUserId="android.uid.system",否则拿到的就不全,

        对于launcher启动属性的页面,当页面起来后,调用它的finish()方法,就会重新去启动优先级高的launcher(调用Activity的pause()方法后,系统会重新执行启动launcher),可能会有疑问,重新启动不还是刚finish()点的launcher么,正常来说是的,但是如果调用了如下方法:

        val defaultName = ComponentName("com.android.provision", "com.android.provision.DefaultActivity")
        pm.setComponentEnabledSetting(
            defaultName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP
        )

那么在PackageManager中就会去掉这个Activity的信息,自然重新查找launcher就不是原来的launcher了,按照这个逻辑,除了首次开机会启动所有的launcher,其他时候开机就只剩NexusLauncherActivity了,但是每次打开模拟器时,都会有FallbackHome的加载动画,那就说明FallbackHome并没有从包管理中去掉,那是怎么跳过FallbackHome启动后面的Launcher的呢?那这就要看android:directBootAware="true"了,这个属性的意思是当设备未解锁时是否允许被启动,true表示可以启动,false表示不可以启动,FallbackHome就配置了这个属性,并且FallbackHome是在监听到解锁后finish()掉的,接下来看下这几个页面在menifest的配置:

1、com.android.settings/.CryptKeeper

    <application
        android:directBootAware="true">

        <activity
            android:theme="@ref/0x7f13027a"
            android:name="com.android.settings.CryptKeeper"
            android:process=":CryptKeeper"
            android:excludeFromRecents="true"
            android:launchMode="1"
            android:screenOrientation="5"
            android:configChanges="0x233"
            android:windowSoftInputMode="0x10"
            android:immersive="true"
            androidprv:systemUserOnly="true">

            <intent-filter android:priority="10">
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>

2、com.google.android.setupwizard/.SetupWizardActivity

        <activity
            android:theme="@ref/0x7f1100b0"
            android:label="@ref/0x7f100028"
            android:name="com.google.android.setupwizard.SetupWizardActivity"
            android:excludeFromRecents="true"
            android:launchMode="2"
            android:configChanges="0x4b3"
            android:immersive="true"
            android:directBootAware="true">

            <intent-filter android:priority="5">
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.intent.action.DEVICE_INITIALIZATION_WIZARD" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.SETUP_WIZARD" />
            </intent-filter>
        </activity>

3、com.android.settings/.FallbackHome

    <application
        android:directBootAware="true">

        <activity
            android:theme="@ref/0x7f130104"
            android:label="@string/0x32"
            android:name="com.android.settings.FallbackHome"
            android:taskAffinity="com.android.settings.FallbackHome"
            android:excludeFromRecents="true"
            android:screenOrientation="5">

            <intent-filter android:priority="-1000">
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
    </application>

4、com.google.android.sdksetup/.DefaultActivity

        <activity
            android:name="DefaultActivity"
            android:excludeFromRecents="true">

            <intent-filter android:priority="3">
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

5、com.google.android.apps.nexuslauncher/.NexusLauncherActivity

        <activity
            android:theme="@ref/0x7f12000a"
            android:name="com.google.android.apps.nexuslauncher.NexusLauncherActivity"
            android:enabled="true"
            android:taskAffinity="@string/0x35"
            android:clearTaskOnLaunch="true"
            android:stateNotNeeded="true"
            android:launchMode="2"
            android:screenOrientation="-1"
            android:configChanges="0xdf3"
            android:windowSoftInputMode="0x20"
            android:resumeWhilePausing="true"
            android:resizeableActivity="true">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY" />
                <category android:name="android.intent.category.LAUNCHER_APP" />
            </intent-filter>

            <meta-data
                android:name="com.android.launcher3.grid.control"
                android:value="com.google.android.apps.nexuslauncher.grid_control" />
        </activity>

上面这些就是Pixel 5模拟器所有launcher配置,系统启动选取launcher是通过上面提到的resolveIntent()这个方法解决,感兴趣的可以自己去看看源码,在开机时,系统是没有解锁的,所以只会找到配置了android:directBootAware="true"的Activity,所以这里先找到的是CryptKeeper、SetupWizardActivity、FallbackHome,然后再来看下优先级,CryptKeeper的priority是10、SetupWizardActivity的priority是5、FallbackHome的priority是-1000,优先级高的先执行,CryptKeeper、SetupWizardActivity执行完后通常都是会从包管理中移除,在执行到FallbackHome时,FallbackHome有解锁的监听,解锁完成就直接finish()掉了,但不会从包管理中移除,这也就是每次开机都能看到一个加载的动画,FallbackHome执行完后,再次寻找launcher时,找到是FallbackHome、DefaultActivity、NexusLauncherActivity,同样根据优先级,这时候由于FallbackHome的优先级是-1000,所以是不会执行了,DefaultActivity执行完后会直接从包管理中移除,所以最终显示的就是NexusLauncherActivity了,而在后续的开机中,就只会涉及到FallbackHome和NexusLauncherActivity了,这样开机中涉及到的所有launcher就全了。上面所涉及到的五个Activity,其中SetupWizardActivity、DefaultActivity是开机向导,为什么Pixel 5中会有两个开机向导,这就不是很明白了(个人猜测可能是在设置SetupWizardActivity的过程中,就已经解锁了,而有些设置需要在解锁后设置)。

2、自定义开机向导

        明白了开机流程中的原理,再来弄开机向导就很简单。

        现在就可以来自定义我们的开机向导了,按照网上大部分教程是参照Provision这个应用,这里就会有个问题,如果开机向导中有设置语言,在首次开机时,FallbackHome的加载动画的文本就只能使用系统默认的语言了,而且还延长了开机时间,所以建议参照SetupWizardActivity来配置,这样有几个好处:

1、可以不将包放到系统目录的pri-app目录下;

2、首次开机可以省略掉FallbackHome加载动画(前提是开机向导设置完成时设备已解锁);

如果有些需求需要系统解锁后在进行设置,那就可以参照网上的Provision了,如果你不想将包打包进pri-app目录下(后续手动安装覆盖不掉),也是有解决方案的,那就是重新设置launcher的优先级,不过这里需要注意下,不再pri-app目录下,设置1到1000是无效的,只能设置0到-1000,这样所有问题都可以解决了。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值