什么是OOBE
就是开机向导,在 Android 设备首次开机的时候,会先进行一系列的初始化,然后再进入主页。
初始化的操作一般有 登录或注册厂商账号、选择时区、选择语言等,TV的话还可能包括搜台等。
初始化的操作只在首次开机和安卓复位后才会出现,普通开关机不会出现。
源码的开机向导
8.0 源码 packages/apps/Provision
。
查看注册文件:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.android.provision"><original-package android:name="com.android.provision" /><!-- For miscellaneous settings --><uses-permission android:name="android.permission.WRITE_SETTINGS" /><uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /><application><activity android:name="DefaultActivity"android:excludeFromRecents="true"><intent-filter android:priority="1"><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.SETUP_WIZARD" /></intent-filter></activity></application>
</manifest>
设置了 android:priority="1"
,值越大优先级越高,取值 -1000 ~~ 1000 。
这个应用也有 android.intent.category.HOME
属性,表明它也是主页应用,且优先级比主页高。为什么比主页高,因为主页没有设置 android:priority 属性,默认0 。
提一下, 6.0 的 Provision 源码并没有
<category android:name="android.intent.category.SETUP_WIZARD" />
。
在 8.0 上不加 <category android:name="android.intent.category.SETUP_WIZARD" />
也没问题。
查看源码的 Launcher2 、Launcher3 ,确实没有配置 android:priority 属性。
<applicationandroid:name="com.android.launcher2.LauncherApplication"android:label="@string/application_name"android:icon="@mipmap/ic_launcher_home"android:hardwareAccelerated="true"android:largeHeap="@bool/config_largeHeap"android:supportsRtl="true"><activityandroid:name="com.android.launcher2.Launcher"android:launchMode="singleTask"android:clearTaskOnLaunch="true"android:stateNotNeeded="true"android:resumeWhilePausing="true"android:theme="@style/Theme"android:windowSoftInputMode="adjustPan"android:screenOrientation="nosensor"><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"/></intent-filter></activity>//其他的省略
源码开机向导只有一个 DefaultActivity, 看看都干了啥。
public class DefaultActivity extends Activity {@Overrideprotected void onCreate(Bundle icicle) {super.onCreate(icicle);// Add a persistent setting to allow other apps to know the device has been provisioned.Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);// remove this activity from the package manager.PackageManager pm = getPackageManager();ComponentName name = new ComponentName(this, DefaultActivity.class);pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,PackageManager.DONT_KILL_APP);// terminate the activity.finish();}
}
首先, 把 DEVICE_PROVISIONED
、 USER_SETUP_COMPLETE
置为 1 ,告诉其他应用初始化完毕。
然后用 PackageManager 把自己 disable 掉,这样此应用就不可用,不会再出现了。
如果要使 Provision 可用,pm.setComponentEnabledSetting 传入 COMPONENT_ENABLED_STATE_ENABLED 即可。
安卓复位后 Provision 会重新可用,为什么,后续分析。
然后,并没有用
按照如上操作开发了 OOBE 后,并没有达到理想效果,出现了选择主页的弹窗,why ?
参考这篇博客 https://juejin.im/post/5cc165946fb9a031ec6d2ab8 ,找到了思路。
我原先把 OOBE 放到 system/app/
目录, 尝试把 OOBE 放到 system/priv-app/
目录,两个目录的差别是 system/priv-app/ 目录权限更高,这样 android:priority=“1” 就有效了。
如何把 OOBE 放到 system/priv-app/ 目录
我用的是源码编译,修改 OOBE 的 Android.mk 文件,添加
LOCAL_PRIVILEGED_MODULE := true
这个表示把这个 app 放到 system/priv-app/
目录;
如果不设置 或者 设为 false ,则是放到 system/app/ .
烧录测试,OK。