I am looking to acquire some help regarding how a developer should go about creating an out-of-the-box experience (i.e., setup wizard) for AOSP. What is the proper way to utilize the SETUP_WIZARD Intent Category and the USER_SETUP_COMPLETE and DEVICE_PROVISIONED System Settings?
Currently, I have a standalone setup app that declares the SETUP_WIZARD
Intent Category in AndroidManifest.xml. My naive assumption was that on first boot (or after factory reset), if the USER_SETUP_COMPLETE
and DEVICE_PROVISIONED
System Settings were false, the OS would fire the SETUP_WIZARD
Intent Category, and my setup app would then launch. Additionally, I had hoped that if the the USER_SETUP_COMPLETE
and DEVICE_PROVISIONED
System Settings were true, the OS would not fire the SETUP_WIZARD
Intent Category.
My setup app is launching irrespective of the values of the USER_SETUP_COMPLETE
and DEVICE_PROVISIONED
System Settings (0 vs. 1).
Looking at the logs, it seems that my setup app is launching because the OS is firing a MAIN
intent with a HOME
category. Sadly, it seems like a MAIN
intent with a SETUP_WIZARD
category is never fired. What am I missing?
Here's my setup app's AndroidManifest.xml
:
<activity
android:name=".MainActivity"
android:exported="true"
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>
AOSP is a new area for me, so please be nice ;). I find that the AOSP documentation is wildly sparse compared to the documentation for general app devs. Thanks in advance for the help!
I recommend you not mix multiple categories per intent-filter
, see Why is my intent-filter matching URIs it shouldn't? to explain why that is problematic. You should have multiple intent-filter
sections, one for each category. Here is an example setup wizard manifest entry.
To be honest I can't remember if it is necessary to have both filters or only one is needed you can try with one or the other but having both seems fine also.
<activity
android:name=".CustomSetupWizard"
android:excludeFromRecents="true"
android:exported="true"
android:icon="@drawable/ic_launcher"
android:immersive="true">
<intent-filter>
<action android:name="android.intent.action.DEVICE_INITIALIZATION_WIZARD"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.HOME"/>
</intent-filter>
</activity>
When your Setup Wizard has done everything it needs to do it should then disable its entire package. Once disabled it won't show up unless the device is factory reset which clears the settings and re-enables the package which is what you want to happen.
Example code to complete and disable Setup Wizard:
Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
// Disable and kill setup wizard
getPackageManager().setApplicationEnabledSetting(getPackageName(),
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, 0);