This repo contains an Android app implementation that satisfies some relatively uncommon requirements. Although the app behavior would be dangerous or disruptive on a personal device, it is useful in the context of manufacturing, retail, etc. Think of it as a proof of concept.
- GUI fills the primary display completely
- GUI remains in the foreground and blocks other apps from becoming visible
- Starts automatically on boot*
- Recovers from a crash automatically**
* Due to Android-security restrictions, the app must be manually started initially after installation.
** Android OS includes countermeasures against against crash loops (i.e. backoff delay).
Non-Functional Requirements
- Compatible with Android 12L, 13, and 14
- Integrated as a userspace app (as opposed to a privileged system app which is typically built into the Android-based platform itself)
- Discourage the OS from killing the app in the event of memory and/or CPU pressure*
- Implemented in Kotlin
- GUI implemented Jetpack Compose
* Note that 100% availability would require integration as a privileged system app
Functional Requirements
- Fill all available screen real estate on the primary display
- Prevent other apps from becoming visible (even if the other app is launched programmatically)
- Initialize when the system starts
- In the event of a crash, the GUI should reappear within a moment
In order to be open for extension and closed for modification (i.e. open-closed principle), developers are encouraged to change the following files to suite different needs. Note that interfaces and superclasses are provided.
- Change overlay appearance and behavior
CustomComposeView.kt and any composables referenced inside - Change notification appearance and behavior
HoldForegroundService.kt - Change app icon and name
Drawables and String resources
Note that some runtime permissions are required. However, this implementation does not include runtime prompts. Suggestion is to leverage the -g
flag when installing the APK. This ensures that permissions are granted at install time.
Recommendation is to use Android Studio - which can leverage a custom configuration stored in the repo at app.run.xml. Details of how to do this are not the focus of this documentation.
The following user interface is available for testing purposes.
- Start the service
adb shell am start-foreground-service com.example.holdforeground/.DaemonService
- Show the GUI
adb shell am start-foreground-service -a ACTION_SHOW com.example.holdforeground/.DaemonService
- Dismiss the GUI
adb shell am start-foreground-service -a ACTION_DISMISS com.example.holdforeground/.DaemonService
A reference implementation is included to hint at what is possible. In addition to the features mentioned above, it implements the following:
- Briefly describes the app itself
- User can tap a button to "minimize" the size of the overlay, thereby revealing content underneath
- User can tap a button to "maximize" the overlay size to full screen
- While minimized, user can interact with underlying content (within its visible bounds)
A video is available at holdforeground_demo.mp4
Launcher icon | Maximized | Minimized |
---|---|---|
Simulate a crash
adb shell am crash com.example.holdforeground
- On an Android 12L device, when the app loads initially (e.g. after reboot), the system bars may not hide as expected. To recover and hide the system bars, tap one of the navigation icons like Home or the App Drawer. Note that this issue is not present on Android 13.