27 April 2016
Posted by Wojtek Kaliciński, Developer Advocate
Starting with Android N, a device that has been powered on can boot into a new mode called Direct Boot before the user has a chance to unlock it for the first time. In this mode, the operating system is fully operational, but access to private app data is limited and only apps that have been updated to be Direct Boot aware can run.
Not every app should run in Direct Boot mode, so before you start coding check if your app fits these common use cases:
Please note that this is not an exhaustive list and we look forward to seeing what other kinds of apps can benefit from Direct Boot.
In order to let your app run before the user unlocks the device, you have to explicitly mark components as being Direct Boot aware in the manifest:
<activity|provider|receiver|service ...
android:directBootAware=”true”>
You can pick the subset of your app components that need to be Direct Boot aware, but if you are using a custom Application class, it is assumed to be Direct Boot aware if any component inside your app is marked as Direct Boot aware.
For apps that need to run as soon as the system starts in Direct Boot mode, there is a new Intent.ACTION_LOCKED_BOOT_COMPLETED broadcast. All apps will still receive Intent.ACTION_BOOT_COMPLETED after the user unlocks the device.
To support running apps before the user provides the credentials needed to unlock private app data, all Android N devices now provide two storage locations for data:
Components of your app that are marked as Direct Boot aware must rely on device protected storage for any data required for their operation during Direct Boot mode. They may still access credential protected storage after the user has unlocked the device.
To access device protected storage you need to create and use a secondary Context object for all file-related APIs:
Context deviceProtectedContext = context.createDeviceProtectedStorageContext();
deviceProtectedContext.openFileInput( ... )
When your app gets updated to a Direct Boot aware version, you might have previously saved Shared Preferences or databases that need to be migrated to device protected storage. You should use Context.moveSharedPreferencesFrom() and Context.moveDatabaseFrom() before accessing them to make sure the app continues to work properly even when data is backed up and restored from older versions or other devices.
You should think carefully about what you put in the device protected storage. This should be a minimum set of data that will let your app work during Direct Boot. For example, in a messaging app you could store an access token with a narrow scope that only has access to the number of new messages on your server. All sensitive, private information, like the full message history and a read/write access token, should still be saved in credential protected storage.
Another thing to remember is that during Direct Boot apps can only access other Direct Boot aware apps and components. If your app depends on external Services and Activities, make sure you gracefully handle the situation when they’re not available. Intent filters will by default match only components available in the current user state (locked / unlocked). There are two new flags for explicitly telling the Package Manager which components to enumerate: PackageManager.MATCH_DIRECT_BOOT_AWARE and PackageManager.MATCH_DIRECT_BOOT_UNAWARE.
Until devices with Android N that support Direct Boot out of the box are released, you can test your apps using Android N Developer Preview builds. On Nexus 5X and Nexus 6P, you can wipe all user data and enable full Direct Boot mode by using Settings > Developer options > Convert to file encryption. Alternatively, you can reboot into bootloader and issue the appropriate fastboot command:
$ adb reboot-bootloader
$ fastboot --wipe-and-use-fbe
Warning: Both methods will perform a factory reset and delete all user data on your device.
Alternatively, you can use an emulated Direct Boot mode. To enable it, set a lock pattern on the device, choose "No thanks" if prompted for a secure start-up screen when setting a lock pattern, and then use the following adb shell commands to enable and disable emulation:
$ adb shell sm set-emulate-fbe true
$ adb shell sm set-emulate-fbe false
Please note that using these commands will cause your device to reboot. You should only be using emulated Direct Boot mode on test devices, as it may cause data loss.
#BuildBetterApps
Follow the Android Development Patterns Collection for more!