什么是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 属性。
<application
android: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">
<activity
android: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 {
@Override
protected 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。