# App Suggestions (/docs/app-suggestions) ## 1. App Lock [#1-app-lock] In case your device credentials is bypassed or compromised, you may find it worthwhile to add another protection layer for sensitive applications. For example, using [App Lock](https://github.com/PranavPurwar/AppLock), an Open Source Android App Locker & Privacy Guard. ## 2. FMD Android [#2-fmd-android] In case the Kiosk device is lost or stolen, having a way to trace its location ("Find My Device") can prove useful. Using [FMD Android](https://gitlab.com/fmd-foss/fmd-android), you can find your device via SMS, instant messengers, or a web interface using [FMD Server](https://gitlab.com/fmd-foss/fmd-server) which you can either self-host or use the hosted server linked on the [official site](https://fmd-foss.org). FMD allows you to locate, ring, wipe and issue other commands to your device when it's lost. It aims to be a secure open source alternative to [Google's Find Hub](https://play.google.com/store/apps/details?id=com.google.android.apps.adm). ## 3. Stay Put [#3-stay-put] [Stay Put - Unplug Alert](https://codeberg.org/y20k/stayput) deters casual theft by triggering a loud alarm if someone unplugs your device, and requires biometrics or device credentials to "disarm" it. This can be useful if you need to leave your Kiosk device temporarily unattended. ## 4. Termux [#4-termux] While Webview Kiosk supports uploading local HTML files to the Android Webview, for web applications that heavily utilises JavaScript/routing, e.g. a single-page app built with React or Angular, this may not suffice. In these advanced use cases, we recommend installing an android terminal emulator such as [Termux](https://github.com/termux/termux-app), which can be used to host local web servers accessible at `http://localhost:`. ## 5. Shizuku [#5-shizuku] You can use [shizuku](https://github.com/RikkaApps/Shizuku) to run `adb` commands (e.g. together with termux) to set Webview Kiosk as a Device Owner. For more information, see the Device Owner section under [security](/docs/security). ## 6. Dhizuku [#6-dhizuku] Android only allows for a single device owner application to be set. With [Dhizuku](https://github.com/iamr0s/Dhizuku) you can share the device owner privileges with Webview Kiosk together other applications such as * [OwnDroid](https://github.com/BinTianqi/OwnDroid), * [Hail](https://github.com/aistra0528/Hail) * [Amarok Hider](https://github.com/deltazefiro/Amarok-Hider) * [Alliance Shield](https://play.google.com/store/apps/details?id=com.rrivenllc.shieldx) ## 7. Local Send [#7-local-send] [Local Send](https://github.com/localsend/localsend) is an open-source cross-platform alternative to AirDrop It allows you to securely share files, folders and messages with nearby devices over your local network. ## 8. KDE Connect [#8-kde-connect] [KDE Connect](https://kdeconnect.kde.org) lets you connect your desktop and kiosk device over the same network. This can be useful for copying settings or APKs to multiple devices, using your desktop as a keyboard or mouse during setup, or triggering an alert tone to find a misplaced kiosk tablet. ## 9. OwnDroid [#9-owndroid] [OwnDroid](https://github.com/BinTianqi/OwnDroid) uses Android's DevicePolicyManager API to manage your device. This is similar to Google's [android-testdpc](https://github.com/googlesamples/android-testdpc) project, but with a more user-friendly UI and can run in various modes (including [Shizuku](https://github.com/RikkaApps/Shizuku) and [Dhizuku](https://github.com/iamr0s/Dhizuku)). Using OwnDroid, you can add Webview Kiosk to the allowlist of applications that can utilise [Lock Task Mode](https://developer.android.com/work/dpc/dedicated-devices/lock-task-mode). ## 10. AdAway [#10-adaway] [AdAway](https://github.com/AdAway/AdAway) is an open source ad blocker for Android, which operates either through a local VPN (non-root) or by editing host files (root). This can be used to block trackers and unwanted ads in Webview Kiosk, which currently does not have an in-built ad blocker. # Overview (/docs) Webview Kiosk is a free and open-source Android application for secure, kiosk-style web browsing. It can function as digital signage, a kid-friendly restricted browser, an immersive web reader, an interactive sign-up form, a home assistant dashboard, or simply a wall clock. Designed for small businesses and device owners who are looking for a simple and standalone Kiosk solution. ## 1. Features [#1-features] ### 1.1. Core / Standalone [#11-core--standalone] * Lock Task Mode (Pin): prevent access to your device's home screen, apps and status bar * Secure Settings: configurations are protected by biometrics, device credentials or custom password * URL Filtering: use regular expressions to control web access through a URL blacklist and whitelist * Export/Import: backup and restore user settings in Base64 or JSON format * Local files: display images, audio, video, HTML or PDF (using Mozilla's PDF.js) in kiosk mode * Default Launcher: use as the home app and launch other apps in lock task mode (kiosk) * JS Scripts: supports NFC (Near Field Communication), Eruda console, Dark Reader and custom scripts ### 1.2. Remote Management / Enterprise [#12-remote-management--enterprise] 1. MQTT (Message Queuing Telemetry Transport) * Monitor events, update settings, execute commands and build custom automations using the API * Requires an MQTT broker (e.g. Mosquitto, EMQX, HiveMQ, or their HomeAssistant integrations) 2. UnifiedPush * Send commands and update settings via a decentralised push notification system * Requires a distributor application (e.g. sunup, ntfy, gCompat-UP) 3. Managed Configurations (App Restrictions) * For fully-managed (company-owned) devices, settings can be remotely configured via an MDM/EMM provider * Advanced users using a device policy controller (e.g. Test DPC or OwnDroid) can also enforce configurations locally ## 2. Permissions [#2-permissions] * INTERNET: for general web browsing * ACCESS\_NETWORK\_STATE: to refresh web pages when network connectivity is restored * CAMERA: (optional) for use with web apps that requires photo/video capture * RECORD\_AUDIO: (optional) for use with web apps that requires audio capture * MODIFY\_AUDIO\_SETTINGS: for routing audio (microphone will not work without this) * ACCESS\_FINE\_LOCATION: (optional) for web apps that needs precise geolocation * ACCESS\_COARSE\_LOCATION: (optional) for web apps that needs approximate geolocation * NFC: for reading and writing NFC tags using the device's NFC hardware * INSTALL\_SHORTCUT: for adding home screen launcher shortcuts on Android 7.1 and below * QUERY\_ALL\_PACKAGES: to find launchable apps, device owners and lock task packages * POST\_NOTIFICATIONS: (optional) for lock task mode (kiosk) launches and MQTT * FOREGROUND\_SERVICE: for persistent notification and management with lock task and MQTT * FOREGROUND\_SERVICE\_SPECIAL\_USE: provides a return mechanism for opening apps in kiosk * USE\_BIOMETRIC: replaces USE\_FINGERPRINT from Android 9.0 onwards * USE\_FINGERPRINT: use fingerprint hardware when accessing settings or unlocking kiosk * WAKE\_LOCK: to optionally wake the screen when receiving MQTT commands * WRITE\_EXTERNAL\_STORAGE: for downloading files in Android 9.0 and below * API (Dhizuku): to request shared device owner privileges ## 3. Contact [#3-contact] ### 3.1. Questions/Feature Requests [#31-questionsfeature-requests] Create a `Q&A` for questions and `Ideas` for feature requests on [GitHub discussions](https://github.com/nktnet1/webview-kiosk/discussions). ### 3.2. Bugs/Issues [#32-bugsissues] Report bugs by creating a [GitHub issue](https://github.com/nktnet1/webview-kiosk/issues) describing the problem and how it can be reproduced. Please also include your device model, app version and android version. ### 3.3. Other [#33-other] For all other enquiries, please reach out to [support@webviewkiosk.nktnet.uk](mailto:support@webviewkiosk.nktnet.uk) ## 4. Alternatives [#4-alternatives] * [Fully Kiosk Browser Lockdown](https://www.fully-kiosk.com) (feature-rich, but not a free kiosk solution) * [Web Kiosk](https://github.com/screenlite/web-kiosk) (developed by Screenlite) * [FreeKiosk](https://github.com/RushB-fr/freekiosk) (developed by Rushb-fr) * [Kite AOS](https://github.com/andrew-malitchuk/kite-aos) (developed by andrew-malitchuk) # Installation (/docs/installation) Google's new developer verification requirements for 2026-2027 will mean the end for side-loading and many alternate stores and projects such as F-Droid and New Pipe. For more information, please refer to the following sources: * F-Droid: [https://f-droid.org/en/2025/10/28/sideloading.html](https://f-droid.org/en/2025/10/28/sideloading.html) * Keep Android Open: [https://keepandroidopen.org](https://keepandroidopen.org) * Video context: [https://www.youtube.com/watch?v=wRvqdLsnsKY](https://www.youtube.com/watch?v=wRvqdLsnsKY) ## 1. Google Play [#1-google-play] From [v0.17.0](https://github.com/nktnet1/webview-kiosk/releases/tag/v0.17.0), Google Play's [automatic protection](https://support.google.com/googleplay/android-developer/answer/10183279) has been intentionally **disabled** to allow installations from the Aurora Store ([context](https://gitlab.com/AuroraOSS/AuroraStore/-/issues/1088)). Get it on Google Play While the app is available on the Google Play Store, **we strongly recommend that you install from Obtainium, F-Droid or IzzyOnDroid instead** for faster updates, enhanced privacy and a stronger assurance that the APK was built directly from the source code. ### 1.1. Aurora Store [#11-aurora-store] You can use the [Aurora Store](https://auroraoss.com/aurora-store), a FOSS client for Google Play that works without needing Google Play Services or MicroG, starting from [v0.17.0](https://github.com/nktnet1/webview-kiosk/releases/tag/v0.17.0). While installation methods with reproducible builds and no involvement from Google is preferred, this method still provides better privacy than using the Google Play Store. ## 2. GitHub [#2-github] As of [v0.15.7](https://github.com/nktnet1/webview-kiosk/releases/tag/v0.15.7), the package name has changed from `com.nktnet.webview_kiosk` to `uk.nktnet.webviewkiosk` for all installation sources except for the Google Play Store and its derivatives. Get it on IzzyOnDroid Signed APKs are available for download on the GitHub Releases page. To build the application from source, clone the GitHub repository, open the project in Android Studio and follow the [official documentation](https://developer.android.com/studio/run). ### 2.1. Obtainium [#21-obtainium] Get it on Obtainium [Obtainium](https://obtainium.imranr.dev) can be used to manage installations and updates of Webview Kiosk on GitHub release page, with the added bonus of notifications when new releases are made available. ### 2.2. F-Droid [#22-f-droid] Get it on F-Droid With [F-Droid reproducible builds](https://f-droid.org/docs/Reproducible_Builds) enabled, F-Droid will publish the same APK as the GitHub releases after confirming that it was generated from the same source code. ### 2.3. IzzyOnDroid [#23-izzyondroid] Get it on IzzyOnDroid Similar to F-Droid, the [IzzyOnDroid reproducible builds](https://android.izzysoft.de/articles/named/iod-rbs-mirrors-clients) criteria is also met. ## 3. QR Code Provisioning [#3-qr-code-provisioning] This is the recommended installation method for full device owner capabilities. On a new or factory-reset device, tap the screen 6 times on the same spot. You may be prompted to connect to a Wi-Fi network on some devices to download a QR scanner. Go to the Webview Kiosk Provision Device page to generate a QR code. Scan the QR code with device and follow the setup wizard instructions. If you do not want to factory reset your device, refer to the [security](/docs/security#33-device-owner-mode) guide for a different method. # Security (/docs/security) ## 1. Settings Authentication Session [#1-settings-authentication-session] The settings page is locked using the device's biometrics or credentials (if set). Once unlocked, it will not prompt for login for the next 5 minutes. This persisting session duration reset each time a settings page is accessed. When the device is locked, or the app is exited or placed in the background, the authentication session will be revoked. ## 2. Default Launcher [#2-default-launcher] By setting Webview Kiosk as the default launcher (home screen) app, any attempts to leave the app will simply re-open it. To do this, use the `Launcher` option in [Setting Actions](/docs/setting-actions). ## 3. App Pinning / Lock Task Mode [#3-app-pinning--lock-task-mode] ### 3.1. User-owned Devices [#31-user-owned-devices] On regular user-owned devices, to improve security, enable **Ask for PIN/pattern/password before unpinning** in your device settings. On some devices, it may be shown as **Lock device when unpinning** or equivalent. This setting is accessible by first finding **App Pinning**, then clicking into the item (instead of the toggle/switch) to see additional options. This will ensure that users cannot unpin (and thus unlock) the kiosk view without the device first locking itself and requiring your biometrics or credentials. For more on Android App Pinning ([screen pinning](https://developer.android.com/about/versions/lollipop/android-5.0#ScreenPinning)), refer to: 1. [Google Official Documentation](https://support.google.com/android/answer/9455138) 2. [Samsung Guide for Unpin Lock](https://www.samsung.com/sg/support/mobile-devices/pin-an-app-to-your-phone-screen-so-that-it-cant-be-closed) When in screen pinning mode, you will not be able to launch other applications. See the `Device Owner Mode` section for further details. ### 3.2. Device Policy Controller [#32-device-policy-controller] If you have access to your [Device Policy Controller (DPC)](https://developer.android.com/work/dpc/build-dpc), or your MDM/EMM has provided an interface to do so, it is recommended that you add Webview Kiosk to the allowlist of apps for lock task packages. This has the benefits of: 1. removing warnings and instructions when you "lock" the app (as it is no longer [screen pinning](https://developer.android.com/about/versions/lollipop/android-5.0#ScreenPinning) like in user-owned devices) 2. stopping users from triggering the "unpin" action using gestures or holding the back and overview button, thus removing the side-effect of the device getting locked when users attempt to "unpin" In [Lock Task Mode](https://developer.android.com/work/dpc/dedicated-devices/lock-task-mode), the only way to unlock Webview Kiosk would be using a methods provided in-app, which are always configurable and can be disabled. The supported methods are currently: 1. Opening the Kiosk Control Panel by either * holding the back button * tapping the screen 10 times in quick succession at your configured region (e.g. Top Left quadrant) 2. Adding a custom unlock shortcut (requires a physical keyboard or a method of that sending key combinations, e.g. `CTRL+1`) There are also standalone applications that, when set as the device owner, can perform the duties of a DPC. Below are instructions for two popular applications: 1. Google's [Test DPC](https://github.com/googlesamples/android-testdpc) * Go to `Lock Task -> Manage lock task list` and enable Webview Kiosk. 2. [OwnDroid](https://github.com/BinTianqi/OwnDroid) * Go to `System -> Lock Task Mode -> Applications` and add Webview Kiosk's package name, which you can find in the [Settings -> About](/docs/settings/about) screen. Finally, if you are writing your own DPC, the kotlin code to achieve this would be: ```kt val APP_PACKAGES = arrayOf( // Choose one depending on your installation method: "uk.nktnet.webviewkiosk", // GitHub, F-Droid, IzzyOnDroid, etc "com.nktnet.webview_kiosk", // Aurora Store, Google Play Store ) val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager val adminName = getComponentName(context) dpm.setLockTaskPackages(adminName, APP_PACKAGES) ``` For more information, see [Android's official documentation](https://developer.android.com/work/dpc/dedicated-devices/lock-task-mode#allowlist_apps). ### 3.3. Device Owner Mode [#33-device-owner-mode] When set as the device owner, Webview Kiosk can act as a DPC and automatically adds itself to the [allowlist for lock task packages](https://developer.android.com/work/dpc/dedicated-devices/lock-task-mode). It is also possible for Webview Kiosk to add other applications in settings, thus allowing it to launch other apps in Lock Task Mode (kiosk). The easiest way is to factory reset your device and use the [QR Code installation method](/docs/installation#3-qr-code-provisioning). However, if this isn't possible, you can try the following: Remove all [additional users](https://source.android.com/docs/devices/admin/multi-user) on your device. Find all [accounts](https://source.android.com/docs/automotive/users_accounts/accounts) on your device, e.g. in your device settings or using an application like [AndroidAccounts](https://github.com/iamr0s/AndroidAccounts). Freeze all applications that uses accounts, e.g. Whatsapp. You can do this using [Hail](https://github.com/aistra0528/Hail/blob/master/README_EN.md). Remove all accounts. Set Webview Kiosk as the device owner using Android Debug Bridge (ADB) on a computer: ```sh adb shell dpm set-device-owner uk.nktnet.webviewkiosk/.WebviewKioskAdminReceiver ``` Alternatively, you can use [Shizuku](https://github.com/RikkaApps/Shizuku) with wireless debugging and [Termux](https://github.com/termux/termux-app) to gain ADB access (thus skipping the PC requirement). Refer to [GitHub Discussion #33](https://github.com/nktnet1/webview-kiosk/discussions/33#discussioncomment-14672999) for a video demonstration. Webview Kiosk also supports [Dhizuku](https://github.com/iamr0s/Dhizuku), a tool that can share device owner permissions. If you encounter any troubles with the setup, it is worth taking a look at the [Dhizuku activation guide](https://github.com/iamr0s/Dhizuku/discussions/19), which includes helpful debugging steps when setting up a device owner application. ## 4. Managed Configurations (App Restrictions) [#4-managed-configurations-app-restrictions] For fully managed (company-owned) devices, you can use [managed configurations](https://developer.android.com/work/managed-configurations) to restrict and remotely modify Webview Kiosk settings through your MDM/EMM. It is also possible to set app restrictions using [OwnDroid](https://github.com/BinTianqi/OwnDroid) or [Test DPC](https://github.com/googlesamples/android-testdpc). For a list of available settings, refer to [./app/src/main/res/xml/app\_restrictions.xml](https://github.com/nktnet1/webview-kiosk/blob/main/app/src/main/res/xml/app_restrictions.xml). Below are instructions for a few popular MDM/EMM providers: * [Google Endpoint Management](https://support.google.com/a/answer/6328701?hl=en#configure\&zippy=%2Cset-up-android-apps-with-managed-configurations) * [Microsoft Intune](https://learn.microsoft.com/en-us/intune/intune-service/apps/app-configuration-policies-managed-app) * [Miradore](https://www.miradore.com/knowledge/android/how-to-configure-application-settings) * [Manage Engine](https://www.manageengine.com/mobile-device-management/managed-app-configuration.html) * [Scale Fusion](https://help.scalefusion.com/v1/docs/application-configurations-for-android-applications) * [Hexnode](https://www.hexnode.com/mobile-device-management/help/set-up-permissions-and-configurations-for-an-app-using-hexnode-mdm) At the time of writing, [Headwind MDM](https://h-mdm.com) (an open-source platform to manage android device) does not yet support managed configurations, but this is [on their roadmap for the future](https://github.com/h-mdm/hmdm-server/issues/49#issuecomment-3574073134). # Setting Actions (/docs/setting-actions) Setting actions are accessible on the default app settings list page by clicking the () icon. ## 1. Backups & Restore [#1-backups--restore] When selecting `Export`, a dialog will appear showing all user settings encoded as either `Base64` or raw `JSON`. You can either copy the text in your desired format or save it to a file on your device. To import your user settings, simply paste the copied text into the `Import` input field (or load from a file) under the same format you exported with. ## 2. Device Settings [#2-device-settings] Clicking the `Settings` entry here will open your device's settings application. Additionally, there is a `Launcher` entry that takes you directly to the "Default Home App" device settings page, which will allow you to select your desired launcher, e.g. * Webview Kiosk * One UI Home * Nova Launcher * Pixel Launcher ## 3. Help [#3-help] This will open the Webview Kiosk Home Page in your default browser: * [https://webviewkiosk.nktnet.uk](https://webviewkiosk.nktnet.uk) ## 4. More [#4-more] This will open the `More Actions` screen. ### 4.1. Quick Access Actions [#41-quick-access-actions] Open relevant device settings via intent. | Quick Access | Description | | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | App Info | Opens the application details settings for this app.
See [ACTION\_APPLICATION\_DETAILS\_SETTINGS](https://developer.android.com/reference/android/provider/Settings.html#ACTION_APPLICATION_DETAILS_SETTINGS) | | Default Launcher | Opens the device's default launcher settings.
See [ACTION\_HOME\_SETTINGS](https://developer.android.com/reference/android/provider/Settings.html#ACTION_HOME_SETTINGS) | | Default Apps | Opens the default apps management screen (Android N+).
See [ACTION\_MANAGE\_DEFAULT\_APPS\_SETTINGS](https://developer.android.com/reference/android/provider/Settings.html#ACTION_MANAGE_DEFAULT_APPS_SETTINGS) | | Wi-Fi | Opens the Wi-Fi settings screen.
See [ACTION\_WIFI\_SETTINGS](https://developer.android.com/reference/android/provider/Settings.html#ACTION_WIFI_SETTINGS) | | Data Usage | Opens the data usage settings screen (Android P+).
See [ACTION\_DATA\_USAGE\_SETTINGS](https://developer.android.com/reference/android/provider/Settings.html#ACTION_DATA_USAGE_SETTINGS) | | Settings | Opens the main device settings screen.
See [ACTION\_SETTINGS](https://developer.android.com/reference/android/provider/Settings.html#ACTION_SETTINGS) | ### 4.2. Manage Actions [#42-manage-actions] Manage stored data and states. | Action | Description | | ---------------- | --------------------------------------------------------------------- | | Local Files | Opens `Web Content -> Manage Local Files`. | | Site Permissions | Opens `Web Browsing -> Manage Site Permissions`. | | Device Owner | Opens `Device -> Manage Device Owner`. | | App Launcher | Opens a dialog for installed apps on the device that can be launched. | ### 4.3. Clear Actions [#43-clear-actions] Clear WebView or application data and cache. | Action | Description | | --------------------- | ------------------------------------------------------------------------------------- | | Clear Cookies | Removes all cookies stored by the WebView, including session cookies. | | Clear Cache | Clears the WebView's cached files on disk. | | Clear Form Data | Clears saved form inputs and autofill data in the WebView. | | Clear History | Clears the WebView's browsing history and session history. | | Clear SSL Preferences | Clears stored SSL certificate decisions and preferences. | | Clear Web Storage | Deletes all HTML5 Web Storage (localStorage, Web SQL, IndexedDB) used by the WebView. | # About (/docs/settings/about) This page displays basic information about the app, including its package name, version, build type, supported ABIs, and installer source. You can touch and hold (long-press) any item in the app to copy them to your clipboard. ## 1. App [#1-app] ### 1.1. App Name [#11-app-name] The display name of the application, e.g. Webview Kiosk ### 1.2. Package Name [#12-package-name] The unique identifier for the app on different platforms: * `com.nktnet.webview_kiosk` for Aurora Store and Google Play * `uk.nktnet.webviewkiosk` for GitHub, F-Droid and IzzyOndroid as of [v0.15.7](https://github.com/nktnet1/webview-kiosk/releases/tag/v0.15.7) ### 1.3. Version [#13-version] The version code and version name, e.g. `46 (0.18.0)` ### 1.4. Min SDK [#14-min-sdk] The minimum supported SDK - e.g. `21` (Android 5, Lollipop) ### 1.5. Target SDK [#15-target-sdk] The Android SDK level the app targets, e.g. `36` (Android 16, Baklava) ### 1.6. Debug Build [#16-debug-build] Indicates whether the current build is a debug build, e.g. `true` / `false` ### 1.7. Installer Source [#17-installer-source] The package or store that installed the app, e.g.: * `dev.imranr.obtainium` → [Obtainium](https://obtainium.imranr.dev) * `org.fdroid.fdroid` → [F-Droid](https://f-droid.org) * `com.looker.droidify` → [Droidify](https://droidify.eu.org) * `com.machiav3lli.fdroid` → [Neo Store](https://github.com/NeoApplications/Neo-Store) * `com.android.vending` → [Google Play Store](https://play.google.com/store/apps) * `com.google.android.packageinstaller` → Default installer for APKs outside of Play Store * `com.aurora.com` → [Aurora Store](https://auroraoss.com/aurora-store) ### 1.8. Device Owner [#18-device-owner] Whether the app was set as the device owner or not, e.g. `true` / `false` See [DevicePolicyManager.isDeviceOwnerApp](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#isDeviceOwnerApp\(java.lang.String\)). ### 1.9. Lock Task Permitted [#19-lock-task-permitted] Whether the app is allowed to use [Lock Task Mode](https://developer.android.com/work/dpc/dedicated-devices/lock-task-mode) or not, e.g. `true` / `false` If no, [screen pinning](https://developer.android.com/about/versions/lollipop/android-5.0#ScreenPinning) will be the fallback. See [DevicePolicyManager.isLockTaskPermitted](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#isLockTaskPermitted\(java.lang.String\)). ### 1.10. Dhizuku Permission Granted [#110-dhizuku-permission-granted] Whether the app has been granted device owner privileges by [Dhizuku](https://github.com/iamr0s/Dhizuku). This is done using the [Dhizuku API](https://github.com/iamr0s/Dhizuku-API). ### 1.11. Instance ID [#111-instance-id] App Instance ID is a [UUID](https://developer.mozilla.org/en-US/docs/Glossary/UUID) generated when you first view the `Settings -> About` page, e.g. `c345e39c-accd-11f0-9ea0-5a93ec0e6f91` This value can be reset by clearing data or uninstalling the app. ### 1.12. Source Code URL [#112-source-code-url] The link to the application's source code, e.g. [https://github.com/nktnet1/webview-kiosk](https://github.com/nktnet1/webview-kiosk) ## 2. Device [#2-device] ### 2.1. Android Version [#21-android-version] Your device's current android version and SDK, e.g. `15 (SDK 35)` ### 2.2. WebView Version [#22-webview-version] Your device's WebView implementation's version, e.g. `141.0.7390.43` ### 2.3. Screen / Display [#23-screen--display] Height, width and density of your display, e.g. `1080 x 2400 px, density: 3.0` ### 2.4. Managed Profile [#24-managed-profile] Whether the user's profile is managed (work profile/company-owned) or not, e.g. `true` / `false` See [UserManage.isManagedProfile](https://developer.android.com/reference/android/os/UserManager#isManagedProfile\(\)). ### 2.5. Time Zone [#25-time-zone] The user's default time zone, e.g. `Australia/Sydney` ### 2.6. Locale [#26-locale] The user's default locale, e.g. `en_US` ### 2.7. Total RAM [#27-total-ram] The total memory on the device, e.g. `8 GB` ### 2.8. Total Storage [#28-total-storage] The total disk space on the device, e.g. `128 GB` ### 2.9. Model [#29-model] The end-user-visible name for the end product, e.g. `sdk_gphone64_arm64` ### 2.10. Manufacturer [#210-manufacturer] The manufacturer of the product/hardware, e.g. `Google` ### 2.11. Brand [#211-brand] The consumer-visible brand with which the product/hardware will be associated, if any, e.g. `google` ### 2.12. Device [#212-device] The name of the industrial design, e.g. `emu64a` ### 2.13. Product [#213-product] The name of the overall product, e.g. `sdk_gphone64_arm64` ### 2.14. Hardware [#214-hardware] The name of the hardware (from the kernel command line or /proc), e.g. `ranchu` ### 2.15. Board [#215-board] The name of the underlying board, e.g. `goldfish_arm64` ### 2.16. Bootloader [#216-bootloader] The system bootloader version number, e.g. `X210XXS8DYH1` ### 2.17. Security Patch [#217-security-patch] The security patch version, e.g. `2024-09-05` ### 2.18. Supported ABIs [#218-supported-abis] An ordered list of ABIs supported by this device. The most preferred ABI is the first element in the list. E.g. `arm64-v8a, armeabi-v7a, armeabi` ### 2.19. Supported 32-bit ABIs [#219-supported-32-bit-abis] An ordered list of 32 bit ABIs supported by this device. The most preferred ABI is the first element in the list. E.g. `armeabi-v7a, armeabi` ### 2.19. Supported 64-bit ABIs [#219-supported-64-bit-abis] An ordered list of 64 bit ABIs supported by this device. The most preferred ABI is the first element in the list. E.g. `arm64-v8a` ### 2.20. Build Fingerprint [#220-build-fingerprint] A string that uniquely identifies your device build, e.g. ``` generic_arm64/sdk_google_phone_arm64/generic_arm64:5.0.2/LSY66K/8789838:eng/test-keys ``` # Appearance (/docs/settings/appearance) ## 1. Theme [#1-theme] Select one of: 1. System 2. Dark 3. Light See also: `Settings -> JS Scripts -> Apply App Theme`. **Default:** System ## 2. Floating Toolbar Mode [#2-floating-toolbar-mode] Control the visibility and behaviour of the floating toolbar menu button: 1. Hidden 2. Hidden when locked 3. Shown When set to **Hidden**, the "Settings" button will be visible from the Kiosk Control Panel. **Default:** Hidden when locked ## 3. Window Insets [#3-window-insets] Controls padding for full-screen content relative to system UI elements. Use `WebViewInset` in your app to select the desired inset for full-height/width components. For details, see the [Android Compose System Insets guide](https://developer.android.com/develop/ui/compose/system/insets). | Inset | Description | | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | None | No padding applied. | | Status Bars | The insets describing the status bars. These are the top system UI bars containing notification icons and other indicators. | | Navigation Bars | The insets describing the navigation bars. These are the system UI bars on the left, right, or bottom side of the device, describing the taskbar or navigation icons. These can change at runtime based on the user's preferred navigation method and interacting with the taskbar. | | System Bars | The union of the system bar insets, which include the status bars, navigation bars, and caption bar. | | Display Cutout | The insets representing the amount of spacing needed to avoid overlapping with a display cutout (notch or pinhole). | | Safe Drawing | Insets representing safe drawing area that avoids system UI and cutouts. | | Safe Gestures | Insets representing areas where system gestures are active and the app should avoid placing interactive elements. | | Safe Content | Insets representing the safe content area where important UI should not be obscured by system UI. | **Default:** System Bars ## 4. Immersive Mode [#4-immersive-mode] In immersive mode, your system bars (status and navigation) are hidden. You can temporarily reveal the system bars with gestures such as swiping from the edge of the screen where the bar is hidden from. Note: immersive mode is enabled automatically when entering fullscreen (for example, when watching a video), irrespective of this setting. | Mode | Description | | ---------------- | ----------------------------------------------------------------------------- | | Always On | System bars are always hidden. | | Always Off | System bars are never hidden (unless in fullscreen). | | Only when locked | System bars are only hidden when the device is in locked/pinned (kiosk) mode. | For more details, refer to: * [Android Immersive Mode Official Documentation](https://developer.android.com/develop/ui/views/layout/immersive) * [BEHAVIOR\_SHOW\_TRANSIENT\_BARS\_BY\_SWIPE](https://developer.android.com/reference/androidx/core/view/WindowInsetsControllerCompat#BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE\(\)) **Default:** Only when locked ## 5. Blocked Message [#5-blocked-message] The message to display when a URL matches the blacklist regex filter rule. **Default:** This site is blocked by Webview Kiosk ## 6. Custom Block Page HTML [#6-custom-block-page-html] Define the custom HTML content to show when a page is blocked. Leave blank to use the default block page. Examples: Minimal Redirect Full ```html

Blocked

This site is not accessible.

```
```html ``` ```html Blocked

Blocked

This site is not accessible.

```
**Default:** (blank) ## 7. Address Bar Mode [#7-address-bar-mode] Customise the visibility of the address bar. Select one of: 1. Hidden 2. Hidden when locked 3. Shown With `Hidden when locked`, the address bar will be visible in the default view, but disappears when the app is locked (pinned) using the floating toolbar (). **Default:** Hidden when locked ## 8. Address Bar Size [#8-address-bar-size] Customise the size of the address bar, which will determine the height, font size, padding and icon size. Select one of: 1. Extra Small 2. Small 3. Medium 4. Large 5. Extra Large **Default:** Medium ## 9. Address Bar Position [#9-address-bar-position] Customise the position of the address bar. Select one of: 1. Top 2. Bottom **Default:** Top # Device (/docs/settings/device) ## 1. Keep Screen On [#1-keep-screen-on] Enable this option to keep your device awake (no screen timeout). Useful if you have a kiosk application that should always remain active. **Default:** false ## 2. Rotation [#2-rotation] Select one of: | Option | Orientation | Description | | ------ | ------------------ | --------------------------------------------------------------------------------------------------------------- | | Auto | `unspecified` | No preference specified: let the system decide the best orientation. | | 0° | `portrait` | Would like to have the screen in a portrait orientation: display taller than wide, ignoring sensor data. | | 90° | `landscape` | Would like to have the screen in a landscape orientation: display wider than tall, ignoring sensor data. | | 180° | `reversePortrait` | Would like to have the screen in portrait orientation, turned in the opposite direction from normal portrait. | | 270° | `reverseLandscape` | Would like to have the screen in landscape orientation, turned in the opposite direction from normal landscape. | For more details, refer to Android's official documentation for [R.attr.screenOrientation](https://developer.android.com/reference/android/R.attr#screenOrientation). **Default:** Auto ## 3. Brightness [#3-brightness] Set the app window brightness from 0 (very dim) to 100 (very dark). Use -1 to disable (i.e. the system default brightness will be used). **Default:** -1 ## 4. Allow Camera [#4-allow-camera] Set to true to give WebView access to your device's camera. You will need to grant the [CAMERA](https://developer.android.com/reference/android/Manifest.permission#CAMERA) permission, which is required for the WebView's [RESOURCE\_VIDEO\_CAPTURE](https://developer.android.com/reference/android/webkit/PermissionRequest#RESOURCE_VIDEO_CAPTURE) feature. **Default:** false ## 5. Allow Microphone [#5-allow-microphone] Set to true to give WebView access to your device's microphone. You will need to grant the [RECORD\_AUDIO](https://developer.android.com/reference/android/Manifest.permission#RECORD_AUDIO) permission, which is required for the WebView's [RESOURCE\_AUDIO\_CAPTURE](https://developer.android.com/reference/android/webkit/PermissionRequest#RESOURCE_AUDIO_CAPTURE) feature. **Default:** false ## 6. Allow Location [#6-allow-location] When enabled, websites can request the device's location. You can choose to request precise location (FINE) or approximate location (COARSE). For more information, refer to [location/permissions#accuracy](https://developer.android.com/develop/sensors-and-location/location/permissions#accuracy). You will need to grant either [ACCESS\_FINE\_LOCATION](https://developer.android.com/reference/android/Manifest.permission#ACCESS_FINE_LOCATION) or [ACCESS\_COARSE\_LOCATION](https://developer.android.com/reference/android/Manifest.permission#ACCESS_COARSE_LOCATION), required for the WebView's [GeolocationPermissions](https://developer.android.com/reference/android/webkit/GeolocationPermissions). **Default:** false ## 7. Allow NFC [#7-allow-nfc] Set to true to enable NFC support in Webview Kiosk via a Web NFC compatibility bridge. This allows websites to read and write NFC tags using the device's NFC hardware. Please note that this does not use Web NFC directly, as Web NFC is not yet available in Android System WebView. Instead, a compatibility layer is provided between native NFC and JavaScript. As a result, it is not subject to the same [security limitations](https://developer.chrome.com/docs/capabilities/nfc#security-and-permissions) as Web NFC and can also operate on insecure (non-HTTPS) websites. **Default:** false ## 8. Allow Notifications [#8-allow-notifications] Set to true to allow Webview Kiosk to send notifications. For example, this will allow the MQTT notify command to create alerts. You will need to grant the [POST\_NOTIFICATIONS](https://developer.android.com/reference/android/Manifest.permission#POST_NOTIFICATIONS) android permission. Please note that for foreground services, e.g. when using lock task mode kiosk-launch or MQTT, the notification will always be created irrespective of this setting. You can disable notifications at the device level if you do not want them. **Default:** false ## 9. Back Button Hold Action [#9-back-button-hold-action] Customise the behaviour when the back button is held down (long pressed). | Option | Description | | -------------------------- | ------------------------------------------------------------------ | | `OPEN_KIOSK_CONTROL_PANEL` | See `Web Browsing -> Kiosk Control Panel Region` for more details. | | `GO_HOME` | Navigates to the Home Screen. | | `DISABLED` | Do nothing (ignore long-press). | **Default:** Open Kiosk Control Panel ## 10. Custom Unlock Shortcut [#10-custom-unlock-shortcut] Provide a custom keyboard shortcut using a modifier key (CTRL/SHIFT/ALT/META) in combination with another standard key to unlock/unpin the application. For example, `CTRL+1`. This is useful for devices with no navigation buttons on screen and instead has a physical keyboard connected. **Default:** *(blank)* ## 11. Custom Auth Password [#11-custom-auth-password] Specify a custom password to protect your settings or when unlocking from the kiosk state. For user-owned devices that utilises [screen pinning](https://developer.android.com/about/versions/lollipop/android-5.0#ScreenPinning), this will only work if you are using an unlock method provided by the app. Device-level unpin methods (e.g. gestures/holding overview + back button simultaneously) will bypass this setting. To enhance security, please refer to the [security](/docs/security) documentation. Leave this setting blank to use your device's biometrics or credentials. **Default:** *(blank)* ## 12. Unlock Auth Requirement [#12-unlock-auth-requirement] This setting only applies to in-app unlock methods, e.g. when unlocking using `Kiosk Control Panel` or `Custom Unlock Shortcut`. | Option | Description | | ------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | Default | Require authentication for lock task mode (device owner, fully-managed/company-owned devices), off for screen pinning (user-owned devices). | | Off | Unlock without requiring authentication. | | Require | Prompt for biometrics or device credentials when unlocking. | For user-owned devices without lock task mode, the device will auto-lock when unpinning, which is outside the control of Webview Kiosk. **Default:** Default ## 13. Block Screen Capture [#13-block-screen-capture] Prevent screenshots, screen recording and content previews in Recent Apps. This is done by setting the FLAG\_SECURE window flag. For more information, see [Android Fraud Prevention: Secure Sensitive Activities](https://developer.android.com/security/fraud-prevention/activities). **Default:** false ## 14. Block Volume Keys [#14-block-volume-keys] Disable the volume control buttons, specifically: * [KEYCODE\_VOLUME\_UP](https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_VOLUME_UP) * [KEYCODE\_VOLUME\_DOWN](https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_VOLUME_DOWN) * [KEYCODE\_VOLUME\_MUTE](https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_VOLUME_MUTE) **Default:** false ## 15. Device Owner [#15-device-owner] For more information about `Device Owner`, see the [Security](/docs/security) documentation. ### 15.1. Lock Task Features [#151-lock-task-features] Webview Kiosk The settings below are extracted from the official documentations: * [Lock Task Mode -> Customise UI](https://developer.android.com/work/dpc/dedicated-devices/lock-task-mode#customize-ui) * [DevicePolicyManager#LOCK\_TASK\_FEATURE\_BLOCK\_ACTIVITY\_START\_IN\_TASK](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK)
Feature Description
Show Home Button Shows the Home button. Enable for custom launchers—tapping an enabled Home button has no action unless you allowlist the default Android launcher. LOCK\_TASK\_FEATURE\_HOME
Show Overview Button Shows the Overview button (tapping this button opens the Recents screen). If you enable this button, you must also enable the Home button. LOCK\_TASK\_FEATURE\_OVERVIEW
Enable Global Actions Enables the global actions dialog that shows when long-pressing the power button. The only feature that's enabled when setLockTaskFeatures() hasn't been called. A user typically can't power off the device if you disable this dialog. LOCK\_TASK\_FEATURE\_GLOBAL\_ACTIONS
Enable Notifications Enables notifications for all apps. This shows notification icons in the status bar, heads-up notifications, and the expandable notification shade. If you enable this button, you must also enable the Home button. Tapping notification actions and buttons that open new panels doesn't work in lock task mode. LOCK\_TASK\_FEATURE\_NOTIFICATIONS
Show System Info Enables the status bar's system info area that contains indicators such as connectivity, battery, and sound and vibrate options. LOCK\_TASK\_FEATURE\_SYSTEM\_INFO
Enable Keyguard Enables any lock screen that might be set on the device. Typically not suitable for devices with public users such as information kiosks or digital signage. LOCK\_TASK\_FEATURE\_KEYGUARD
Block Activity Start in Task Enable blocking of non-allowlisted activities from being started into a locked task. This requires Android 11 (API level 30). LOCK\_TASK\_FEATURE\_BLOCK\_ACTIVITY\_START\_IN\_TASK
### 15.2. Dhizuku Request Permission on Launch [#152-dhizuku-request-permission-on-launch] When enabled, if [Dhizuku](https://github.com/iamr0s/Dhizuku) is installed and has not granted Webview Kiosk access through the [Dhizuku API](https://github.com/iamr0s/Dhizuku-API), prompt for permission. **Default:** true # JS Scripts (/docs/settings/js-scripts) ## 1. Apply App Theme [#1-apply-app-theme] This option injects JavaScript that sets `prefers-color-scheme` according to your selected Webview Kiosk theme, which will keeps the webpage theme consistent with the app. The script runs immediately **on page start**. If **System** is used, this script is a no-op (does nothing). **Default:** true ## 2. Apply Desktop Viewport Width (px) [#2-apply-desktop-viewport-width-px] This script injects JavaScript code that sets document.meta.content to `width=YOUR_WIDTH_VALUE`, simulating web browsing on a Desktop. JS history state changes will also be subscribed to (e.g. from Single Page Applications), and the script will be re-triggered as needed. You should only enable this option if setting the user agent was insufficient to force Desktop mode, as the additional JS here will slow down the page. You may also want to enable the following options under `Settings -> Web Engine`: * User Agent: Desktop * Use Wide Viewport: `True` * Load with Overview Mode: `True` To disable, use the value `0`. **Minimum:** 640 **Default:** 0 ## 3. Enable Battery API [#3-enable-battery-api] When enabled, web pages can call `window.WebviewKioskBatteryInterface.getBatteryStatus()` to retrieve the battery data below: * **Level and percentage** - Battery charge level as a decimal (0.0-1.0) and percentage (0-100) * **Charging status** - Whether the device is currently charging * **Charging type** - Method of charging: `none`, `usb`, `ac`, or `wireless` * **Voltage** - Battery voltage in volts * **Temperature** - Battery temperature in degrees Celsius * **Health** - Battery health status: `good`, `overheat`, `dead`, `overvoltage`, `cold`, or `unknown` Example web usage: ```javascript try { const dataString = window.WebviewKioskBatteryInterface.getBatteryStatus(); const battery = JSON.parse(dataString); console.log(`Level: ${battery.level}`); console.log(`Percentage: ${battery.percentage}%`); console.log(`Charging: ${battery.charging}`); console.log(`Charging Type: ${battery.chargingType}`); console.log(`Voltage: ${battery.voltage} V`); console.log(`Temperature: ${battery.temperature} °C`); console.log(`Health: ${battery.health}`); } catch (error) { console.error("Failed to retrieve battery information:", error); } ``` **Default:** false ## 4. Enable Brightness API [#4-enable-brightness-api] When enabled, web pages can call * `window.WebviewKioskBrightnessInterface.getBrightness(): number` * `window.WebviewKioskBrightnessInterface.setBrightness(value: number)` Values are integers between -1 and 100, with * `-1`: use system brightness * `0`: very dim * `100`: very bright Example web usage: ```javascript try { const brightness = parseInt(window.WebviewKioskBrightnessInterface.getBrightness()); console.log(`Current brightness: ${brightness}`); const newBrightness = 10; window.WebviewKioskBrightnessInterface.setBrightness(newBrightness); console.log(`Brightness set to ${newBrightness}%`); } catch (error) { console.error("Brightness Control Error:", error); } ``` **Default:** false ## 5. Enable Dark Reader [#5-enable-dark-reader] Automatically inject Dark Reader into web pages. * [https://github.com/darkreader/darkreader](https://github.com/darkreader/darkreader) This applies dynamic CSS transformations to force dark mode on websites that do not support it natively. Note: Some websites may render incorrectly due to CSS overrides. **Default:** false ## 6. Enable Eruda Console [#6-enable-eruda-console] Automatically inject the Eruda console into web pages. * [https://github.com/liriliri/eruda](https://github.com/liriliri/eruda) This provides a mobile browser developer console for inspecting: * JavaScript errors * Console output * Network requests * DOM elements * Storage and cookies Useful for debugging web applications on Android devices without desktop developer tools. **Default:** false ## 7. Custom Scripts [#7-custom-scripts] Your code content will be wrapped as follows to prevent polluting the global scope and avoid conflicts with other scripts: ```javascript (function() { // })() ``` **Example:** ```javascript document.body.style.backgroundColor = 'green'; ``` ### 7.1. On Page Start [#71-on-page-start] JavaScript to run immediately when the page starts loading. Useful for early DOM manipulation or overriding functions. **Default:** *(blank)* ### 7.2. On Page Finish [#72-on-page-finish] JavaScript to run after the page has fully loaded. Useful for DOM updates, styling, or injecting behavior. **Default:** *(blank)* # Connection (/docs/settings/mqtt/connection) The settings below are modelled after HiveMQ client library's documentation for [client configurations](https://hivemq.github.io/hivemq-mqtt-client/docs/client-configuration) and [mqtt operations -> connect](https://hivemq.github.io/hivemq-mqtt-client/docs/mqtt-operations/connect/#connect). ### 1. Server Host [#1-server-host] The hostname or IP address of the MQTT broker the app should connect to. For example, * 192.168.1.190 * broker.hivemq.com * broker.emqx.io **Default:** 127.0.0.1 ### 2. Server Port [#2-server-port] The [port](https://www.emqx.com/en/blog/mqtt-ports#default-mqtt-ports-numbers) of the MQTT broker the app should connect to. Typically, * `1883`: MQTT (TCP) * `8883`: MQTTS (TCP with SSL/TLS) * `80`: WS (WebSocket, same port as HTTP) * `443`: WSS (WebSocket Secure, same port as HTTPS) When using WebSocket (e.g. on port 80 or 443), you will also need to enable the setting [Use WebSocket](#13-use-websocket) **Default:** 1883 ### 3. Use TLS [#3-use-tls] When enabled, the client will connect securely to the broker using TLS. Ensure the broker supports TLS on the configured port. **Default:** false ### 4. Username [#4-username] The username used to authenticate with the MQTT broker. **Default:** (blank) ### 5. Password [#5-password] The password used to authenticate with the MQTT broker. **Default:** (blank) ### 6. Client ID [#6-client-id] A unique identifier for this client when connecting to the MQTT broker. Leave this field blank if you want the broker server to generate a client ID for Webview Kiosk. Global variables are supported. **Default:** (blank) ### 7. Clean Start [#7-clean-start] When enabled, the MQTT client will start a new session on connect, discarding any previous session state stored by the broker. When disabled, the client will resume the previous session (subscriptions, in-flight messages, etc.) if it exists. **Default:** true ### 8. Keep Alive [#8-keep-alive] The time interval (in seconds) in which the client sends a ping to the broker if no other MQTT packets are sent during this period of time. It is used to determine if the connection is still up. **Default:** 60 ### 9. Connect Timeout (seconds) [#9-connect-timeout-seconds] The timeout between sending the Connect and receiving the ConnAck message. Use 0 to disable the timeout. **Default:** 30 ### 10. Socket Connect Timeout (seconds) [#10-socket-connect-timeout-seconds] The timeout for connecting the socket to the server. Use 0 to disable the timeout. **Default:** 5 ### 11. Automatic Reconnect [#11-automatic-reconnect] When enabled, attempt to automatically reconnect to the MQTT broker after an unexpected disconnect. In Webview Kiosk, this is implemented linearly at a fixed 3-second interval. **Default:** true ### 12. Session Expiry Interval (seconds) [#12-session-expiry-interval-seconds] Specify the maximum time a session is retained on the server after disconnecting from the network. The server will discard the corresponding session state when the expiration time is reached. **Default:** 0 (immediate expiry) ### 13. Use WebSocket [#13-use-websocket] When enabled, the client will connect securely to the broker using TLS. Ensure the broker supports TLS on the configured port, e.g. * `80`: WS (WebSocket, same port as HTTP) * `443`: WSS (WebSocket Secure, same port as HTTPS) Use WebSocket only when necessary, as it consumes more resources than a direct MQTT connection via TCP. For example, it may be required on networks where a firewall blocks non-standard ports such as `8883` but allows HTTPS traffic. **Default:** false ### 14. WebSocket Server Path [#14-websocket-server-path] The path the MQTT broker WebSocket server listens on. Must start with a `/`. **Default:** /mqtt # MQTT (/docs/settings/mqtt) New to MQTT? see the resources below: * [EMQX — Getting Started with MQTT](https://www.emqx.com/en/blog/the-easiest-guide-to-getting-started-with-mqtt) * [HiveMQ — MQTT Essentials](https://www.hivemq.com/mqtt/) * [AWS — What Is MQTT?](https://aws.amazon.com/what-is/mqtt/) To understand MQTT's publish and subscribe architecture, refer to * [EMQX — MQTT 5: Introduction to the Publish/Subscribe Model](https://www.emqx.com/en/blog/mqtt-5-introduction-to-publish-subscribe-model) * [HiveMQ — MQTT Essentials Part 2: Publish & Subscribe](https://www.hivemq.com/blog/mqtt-essentials-part2-publish-subscribe) ## 1. Introduction [#1-introduction] Message Queueing Telemetry Transport ([MQTT](https://mqtt.org)) is a lightweight messaging protocol for devices with limited resources. MQTT is built on top of TCP/IP and is ideal for machine-to-machine communication and the Internet of Things (IoT). Webview Kiosk utilises the MQTT protocol to enable you to remotely: * receive events * update app settings * perform actions via commands * request information ## 2. MQTT Broker [#2-mqtt-broker] To communicate with Webview Kiosk, you will need an [MQTT Broker](https://www.emqx.com/en/blog/the-ultimate-guide-to-mqtt-broker-comparison). The broker acts as an intermediary entity (central hub) that routes messages between devices and applications. Our recommendation for open source, self-hostable brokers (server) and clients (to send messages to Webview Kiosk) are: 1. [EMQX](https://github.com/emqx/emqx) and [MQTTX](https://github.com/emqx/MQTTX) (or [MQTTX Web](https://github.com/emqx/MQTTX/tree/main/web)) 2. [Eclipse Mosquitto](https://github.com/eclipse-mosquitto/mosquitto) and [Home Assistant](https://github.com/home-assistant) - see the [Integration Guide](https://www.home-assistant.io/integrations/mqtt) Here is a third-party integration with Home Assistant: * [https://github.com/RcRaCk2k/ha\_webview\_kiosk](https://github.com/RcRaCk2k/ha_webview_kiosk) This project is community-built and not maintained by Webview Kiosk. There are also public brokers you can use for testing purposes, such as * HiveMQ: [https://www.mqtt-dashboard.com](https://www.mqtt-dashboard.com) * Mosquitto: [https://test.mosquitto.org](https://test.mosquitto.org) * EMQX: [https://www.emqx.com/en/mqtt/public-mqtt5-broker](https://www.emqx.com/en/mqtt/public-mqtt5-broker) ## 3. Global Variables [#3-global-variables] The following variables will be string-interpolated for supported settings, such as topic names and will payload: | Variable Name | Description | | ----------------- | --------------------------------------- | | APP\_INSTANCE\_ID | Unique identifier for the app instance. | | USERNAME | MQTT username used for authentication. | To use variables in your settings, use the syntax `${YOUR_VARIABLE}`, e.g. ```js wk/${USERNAME}/${APP_INSTANCE_ID}/command ``` which may evaluate to a string such as ```txt // [!code word:kiosk_user_01] // [!code word:b8378168-ca69-11f0-af20-5a93ec0e6f90] wk/kiosk_user_01/b8378168-ca69-11f0-af20-5a93ec0e6f90/command ``` Some settings will support additional variables. ## 4. Debug Logs [#4-debug-logs] MQTT operations are recorded in the debug logs, which can be accessed from any MQTT settings screens. This includes: * connecting/connected/disconnect * subscribes * messages received or published * errors A maximum of 100 messages will be stored for the duration of the app activity lifecycle. The logs will not persist between app restarts. ## 5. Settings [#5-settings] ### 5.1. Enabled [#51-enabled] Set to `true` to allow connections to your configured broker in `MQTT -> Connections`. If you are currently in a disconnected state, you will need to manually click the `Connect` button after enabling this option (or simply restart the app). Updated MQTT settings do not get applied immediately if you are already connected. Instead, you will need to reconnect by: * clicking the restart button in MQTT settings * manually restarting the application * send a `Reconnect` command **Default:** false ### 5.2. Use Foreground Service [#52-use-foreground-service] Start a [Foreground Service](https://developer.android.com/develop/background-work/services/fgs) to keep the MQTT connection alive. This will maintain the connection even when Webview Kiosk goes to the background (e.g. another app is opened) or the device screen is turned off (by using [PowerManager.PARTIAL\_WAKE\_LOCK](https://developer.android.com/reference/android/os/PowerManager.html#PARTIAL_WAKE_LOCK)). Turn on notifications to see the current MQTT status being updated by the foreground service every second. Also, it is highly recommended that you disable battery optimisation for Webview Kiosk to stop the service from being killed. For more information, visit: * [https://dontkillmyapp.com](https://dontkillmyapp.com) **Default:** false # Restrictions (/docs/settings/mqtt/restrictions) The settings below are modelled after HiveMQ client library's documentation for [connect#restrictions](https://hivemq.github.io/hivemq-mqtt-client/docs/mqtt-operations/connect/#restrictions). ### 1. Receive Maximum [#1-receive-maximum] Maximum number of MQTT messages the client can receive simultaneously. **Default:** 65535 ### 2. Send Maximum [#2-send-maximum] Maximum number of MQTT messages the client can send simultaneously. **Default:** 65535 ### 3. Maximum Packet Size [#3-maximum-packet-size] Maximum size in bytes of MQTT packets the client can receive. **Default:** 268435460 ### 4. Send Maximum Packet Size [#4-send-maximum-packet-size] Maximum size in bytes of MQTT packets the client can send. **Default:** 268435460 ### 5. Topic Alias Maximum [#5-topic-alias-maximum] Maximum number of topic aliases the client can receive. **Default:** 0 ### 6. Send Topic Alias Maximum [#6-send-topic-alias-maximum] Maximum number of topic aliases the client can send. **Default:** 16 ### 7. Request Problem Information [#7-request-problem-information] When enabled, the client requests additional problem information from the broker in MQTT responses. **Default:** true ### 8. Request Response Information [#8-request-response-information] When enabled, the client requests additional response information from the broker in MQTT responses. **Default:** false # Command (/docs/settings/mqtt/topics/command) ## 1. Settings [#1-settings] ### 1.1. Topic Name [#11-topic-name] All [global variables](/docs/settings/mqtt/#3-global-variables) are supported. For example, ```js wk/${USERNAME}/${APP_INSTANCE_ID}/command ``` **Default:** ```js wk/command ``` ### 1.2. Quality of Service (QoS) [#12-quality-of-service-qos] Quality of Service (QoS) ensures different message delivery guarantees in case of connection failures. **Default:** At Most Once (0) ### 1.3. Retain Handling [#13-retain-handling] Control whether Webview Kiosk should receive existing retained messages when subscribing. **Default:** Do Not Send (2) ### 1.4. Retain as Published [#14-retain-as-published] Controls whether retained messages from the broker keep their original retained flag when delivered to the subscriber. **Default:** false ## 2. Payloads [#2-payloads] In addition to the [Shared Subscribe Payload Properties](/docs/settings/mqtt/topics/#3-shared-subscribe-payload-properties), the following properties exists for all commands:
Property Type Description
command string The command to execute, e.g. clear_history .
interact boolean (optional) Whether a user interaction should be triggered. For example, this will restore brightness if Web Lifecycle → Dim Screen on Inactivity (seconds) is configured. Default: true
wakeScreen boolean (optional) Whether to wake the screen if it is turned off. This requires Settings → MQTT → Use Foreground Service. It is highly recommended that you disable battery optimisation for Webview Kiosk, which will help keep its foreground service alive. For more details, visit * [https://dontkillmyapp.com](https://dontkillmyapp.com) Default: false
### 2.1. Go Back [#21-go-back] Navigates one page back in history. Example payload: Minimal Full ```json { "command": "go_back" } ``` ```json { "command": "go_back", "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.2. Go Forward [#22-go-forward] Navigates one page forward in history. Example payload: Minimal Full ```json { "command": "go_forward" } ``` ```json { "command": "go_forward", "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.3. Go Home [#23-go-home] Navigates to your configured home page. Example payload: Minimal Full ```json { "command": "go_home" } ``` ```json { "command": "go_home", "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.4. Refresh [#24-refresh] Refresh the current webview page. Example payload: Minimal Full ```json { "command": "refresh" } ``` ```json { "command": "refresh", "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.5. Go to URL [#25-go-to-url] Navigates to a specific URL. Example Payload: Minimal Full ```json { "command": "go_to_url", "data": { "url": "https://webviewkiosk.nktnet.uk" } } ``` ```json { "command": "go_to_url", "data": { "url": "https://webviewkiosk.nktnet.uk" }, "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.6. Search [#26-search] Perform a query search using the selected search engine. This is the same as using Webview Kiosk's address bar. Example Payload: Minimal Full ```json { "command": "search", "data": { "query": "How to Train Your Dragon" } } ``` ```json { "command": "search", "data": { "query": "How to Train Your Dragon" }, "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.7. Clear History [#27-clear-history] Removes the navigation history, leaving the current URL as the only entry in the stack. Example Payload: Minimal Full ```json { "command": "clear_history" } ``` ```json { "command": "clear_history", "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.8. Toast [#28-toast] Shows a short toast message. If the message is empty or only contains white space, no toast will be shown. This is still helpful if you need a dummy command to: * trigger a user interaction with the `interact` property * turn the screen on with the `wakeScreen` property Example Payload: Minimal Full ```json { "command": "toast", "data": { "message": "Welcome!" } } ``` ```json { "command": "toast", "data": { "message": "Welcome!" }, "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.9. Lock [#29-lock] Start lock task mode (or screen pinning) depending on whether Webview Kiosk has device owner permissions. Please note that for screen pinning, the user will be prompted to confirm the action, which needs to be done on the device. If possible, we recommend to always enable lock task packages for Webview Kiosk - more details in the [security](/docs/security) section. Example Payload: Minimal Full ```json { "command": "lock" } ``` ```json { "command": "lock", "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.10. Unlock [#210-unlock] Stop lock task mode (or screen pinning) depending on whether Webview Kiosk has device owner permissions. Example Payload: Minimal Full ```json { "command": "unlock" } ``` ```json { "command": "unlock", "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.11. Reconnect [#211-reconnect] Disconnect, then reconnect and resubscribe to all MQTT topics. This is helpful if you have updated any MQTT-related settings, which requires a reconnection to apply. Example Payload: Minimal Full ```json { "command": "reconnect" } ``` ```json { "command": "reconnect", "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.12. Lock Device [#212-lock-device] Turns the device screen off. This command requires device owner privileges or Dhizuku permission. For more details, see the [security](/docs/security#33-device-owner-mode) documentation. Note that if the `MQTT → Use Foreground Service` setting is not enabled, locking the device will also stop the MQTT connection. Example Payload: Minimal Full ```json { "command": "lock_device" } ``` ```json { "command": "lock_device", "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.13. Page Up [#213-page-up] Scrolls the contents of this WebView up by half the view size. You can also specify `absolute: true` in the payload's data property to scroll fully up the page. This command uses the [Webview#pageDown](https://developer.android.com/reference/android/webkit/WebView#pageDown\(boolean\)) API. Example Payload: Minimal Full ```json { "command": "page_up" } ``` ```json { "command": "page_up", "data": { "absolute": true }, "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.14. Page Down [#214-page-down] Scrolls the contents of this WebView down by half the page size. You can also specify `absolute: true` in the payload's data property to scroll fully down the page. This command uses the [Webview#pageUp](https://developer.android.com/reference/android/webkit/WebView#pageUp\(boolean\)) API. Example Payload: Minimal Full ```json { "command": "page_down" } ``` ```json { "command": "page_down", "data": { "absolute": true }, "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.15. Notify [#215-notify] Shows a notification on the device. The title comes from the most recent message, and the body will display the content text of the last 5 messages. This feature requires: * Android `POST_NOTIFICATIONS` permission * `Settings -> Device -> Allow Notifications` Additionally, when in kiosk/locked mode, the following are required: * Device owner or Dhizuku privileges * `Settings -> Device -> Device Owner -> Home` * `Settings -> Device -> Device Owner -> Notifications` Your payload data value can have the following properties: | Property | Type | Default | Description | | -------------- | -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `contentTitle` | string? | `MQTT` | The title of the notification. | | `contentText` | string | `Notify` | The content body of the notification. | | `silent` | boolean? | `false` | If `true`, the notification will not make sound or vibration. | | `onGoing` | boolean? | `false` | See [NotificationCompat.Builder#setOngoing(boolean)](https://developer.android.com/reference/androidx/core/app/NotificationCompat.Builder#setOngoing\(boolean\)). | | `priority` | string? | `DEFAULT` | Notification priority: `MIN`, `LOW`, `DEFAULT`, `HIGH`, or `MAX`. | | `timeout` | long? | `0` | Time in milliseconds before auto-dismiss (0 = no timeout). | | `autoCancel` | boolean? | `true` | Dismiss the notification when the user taps it. | Example payload: Minimal Full ```json { "command": "notify", "data": { "contentText": "Hello, World!" } } ``` ```json { "command": "notify", "data": { "contentTitle": "MQTT", "contentText": "Hello, World!", "silent": true, "onGoing": false, "priority": "DEFAULT", "timeout": 5000, "autoCancel": true }, "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": true, "wakeScreen": false } ``` ### 2.16. Launch Package [#216-launch-package] Open an application based on its package name, e.g. `com.afwsamples.testdpc`. In Lock Task Mode, the same restrictions outlined in [Web Browsing](/docs/settings/web-browsing) under `Kiosk Control Panel Actions -> Apps` applies. Additionally, packages can only be launched when Webview Kiosk is in the foreground, unless direct Device Owner permission has been granted. Dhizuku is insufficient. In the payload `data`, you can optionally specify the `activityName`. For example, this can be any of the following: * `com.afwsamples.testdpc.PolicyManagementActivity` * `.PolicyManagementActivity` * `PolicyManagementActivity` Example Payload: Minimal Full ```json { "command": "launch_package", "data": { "packageName": "com.afwsamples.testdpc" } } ``` ```json { "command": "launch_package", "data": { "packageName": "com.afwsamples.testdpc", "activityName": ".PolicyManagementActivity" }, "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` ### 2.17. Clear Cache [#217-clear-cache] Clears webview cache. This is equivalent to [Clear Cache Action](/docs/setting-actions/#43-clear-actions). Example Payload: Minimal Full ```json { "command": "clear_cache" } ``` ```json { "command": "clear_cache", "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "interact": false, "wakeScreen": true } ``` # Event (/docs/settings/mqtt/topics/event) ## 1. Settings [#1-settings] ### 1.1. Topic Name [#11-topic-name] All [global variables](/docs/settings/mqtt/#3-global-variables) are supported, in addition to `EVENT_TYPE`. For example, ```js wk/${USERNAME}/${APP_INSTANCE_ID}/event/${EVENT_TYPE} ``` **Default:** ```js wk/event/${EVENT_TYPE} ``` ### 1.2. Quality of Service (QoS) [#12-quality-of-service-qos] Quality of Service (QoS) ensures different message delivery guarantees in case of connection failures. **Default:** At Most Once (0) ### 1.3. Retain [#13-retain] Keep response topic messages retained for new subscribers. **Default:** false ## 2. Payloads [#2-payloads] All published events will contain the [shared payload properties](/docs/settings/mqtt/topics#2-shared-payload-properties) mentioned previously, as well as an additional `eventType` property. ### 2.1. Connected [#21-connected] The `connected` event is published when Webview Kiosk has successfully connected to your configured MQTT Broker. The payload data is identical to the `get_status` request/response. Example payload: ```json { "eventType": "connected", "messageId": "41576b3f-20ef-49a1-8793-afaa7d130514", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1", "data": { "currentUrl": "https://webviewkiosk.nktnet.uk", "lastInteractionTime": 1764689417653, "isLocked": false, "batteryPercentage": 62, "appBrightnessPercentage": -1, "systemBrightness": 255, "isDeviceInteractive": true } } ``` ### 2.2. Disconnecting [#22-disconnecting] The `disconnecting` event will be published before the MQTT connection is halted. The cause of disconnection will be one of: * `USER_INITIATED_DISCONNECT` * `USER_INITIATED_RESTART` * `USER_INITIATED_SETTINGS_DISABLED` * `SYSTEM_ACTIVITY_STOPPED` (only when not using foreground service) * `SYSTEM_ACTIVITY_DESTROYED` (only when using foreground service) * `MQTT_RECONNECT_COMMAND_RECEIVED` Example payload: ```json { "eventType": "disconnecting", "messageId": "45dcd504-0795-467b-b58c-5afc5da31c17", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1", "data": { "cause": "SYSTEM_ACTIVITY_STOPPED" } } ``` ### 2.3. URL Changed [#23-url-changed] The `url_changed` event is sent each time a new page starts loading. This is [debounced](https://developer.mozilla.org/en-US/docs/Glossary/Debounce) by 1 second, and will not be sent on app launch or refresh, as the URL did not change. Example Payload: ```json { "eventType": "url_changed", "messageId": "b304f047-0e5b-4389-bcbc-3f9eb1ee4ec3", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1", "data": { "url": "https://webviewkiosk.nktnet.uk/docs/installation/" } } ``` ### 2.4. Lock [#24-lock] The `lock` event is triggered whenever the app enters Lock Task Mode (or Screen Pinning for user-owned devices) from an unlocked state. The `lockStateType` is passed as data, which can be one of: * `LOCK_TASK` * `SCREEN_PINNING` * `UNKNOWN` (on Android 5.0) Example payload: ```json { "eventType": "lock", "messageId": "fada3acc-50aa-42dc-be96-681c295b8d4a", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1", "data": { "lockStateType": "LOCK_TASK" } } ``` ### 2.5. Unlock [#25-unlock] The `unlock` event is triggered when the app exits Lock Task Mode (or Screen Pinning for user-owned devices) from a locked state. Example Payload: ```json { "eventType": "unlock", "messageId": "74dd1313-88ed-48db-b707-5eda8c598e4d", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1" } ``` ### 2.6. Screen On [#26-screen-on] The `screen_on` event is published when the device screen is turned on. This requires `Settings -> MQTT -> Use Foreground Service`. Example payload: ```json { "eventType": "screen_on", "messageId": "a0095065-0221-49dc-9030-04dc703ca430", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1" } ``` ### 2.7. Screen Off [#27-screen-off] The `screen_off` event is published when the device screen is turned off. This requires `Settings -> MQTT -> Use Foreground Service`. Example payload: ```json { "eventType": "screen_off", "messageId": "347cff66-4625-41f0-9a8e-75f20e012727", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1" } ``` ### 2.8. User Present [#28-user-present] The `user_present` event is published when the user unlocks the device. This requires `Settings -> MQTT -> Use Foreground Service`. Example payload: ```json { "eventType": "user_present", "messageId": "af281acb-2ac7-4686-a129-51faa2f7d516", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1" } ``` ### 2.9. App Background [#29-app-background] The `app_background` event is published when the kiosk app moves to the background. This requires `Settings -> MQTT -> Use Foreground Service`. Example payload: ```json { "eventType": "app_background", "messageId": "d59755c1-bac5-4a88-8cb6-3c7f4f59c281", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1" } ``` ### 2.10. App Foreground [#210-app-foreground] The `app_foreground` event is published when the kiosk app moves to the foreground. This requires `Settings -> MQTT -> Use Foreground Service`. Example payload: ```json { "eventType": "app_foreground", "messageId": "5ce42a8d-605c-48c4-9b06-ea84606980c5", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1" } ``` ### 2.11. Power Plugged [#211-power-plugged] The `power_plugged` event is published when the device is connected to a power source. Example payload: ```json { "eventType": "power_plugged", "messageId": "d1e2f3g4-8901-2cde-f123-4567890abcde", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1", } ``` ### 2.12. Power Unplugged [#212-power-unplugged] The `power_unplugged` event is published when the device is disconnected from a power source. Example payload: ```json { "eventType": "power_unplugged", "messageId": "9b3ea5f2-e43b-44d0-83f3-e2d97dfff065", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1" } ``` ### 2.13. Admin Restrictions Changed [#213-admin-restrictions-changed] The `application_restrictions_changed` event is published when device admin restrictions are updated. Example payload: ```json { "eventType": "application_restrictions_changed", "messageId": "f4ba1dbd-dc5d-4ea8-8693-0f6c81b67248", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1" } ``` # Topics (/docs/settings/mqtt/topics) To understand MQTT's publish and subscribe architecture, refer to * [EMQX — MQTT 5: Introduction to the Publish/Subscribe Model](https://www.emqx.com/en/blog/mqtt-5-introduction-to-publish-subscribe-model) * [HiveMQ — MQTT Essentials Part 2: Publish & Subscribe](https://www.hivemq.com/blog/mqtt-essentials-part2-publish-subscribe) ## 1. Common Settings [#1-common-settings] ### 1.1. Quality of Service (QoS) [#11-quality-of-service-qos] All topics in Webview Kiosk will allow the Quality of Service to be configured using one of: | QoS | Description | | ----------------- | ----------------------------------------------------------------------------------------------------------------- | | At most once (0) | The message is delivered at most once, with no acknowledgment. Delivery is not guaranteed. | | At least once (1) | The message is delivered at least once. It may be delivered multiple times if acknowledgment is lost. | | Exactly once (2) | The message is guaranteed to be delivered exactly once by using a two-step handshake between sender and receiver. | The default is `At most once (0)`. For more information, see: * [EMQX QoS Guide](https://www.emqx.com/en/blog/introduction-to-mqtt-qos) * [HiveMQ QoS Guide](https://www.hivemq.com/blog/mqtt-essentials-part-6-mqtt-quality-of-service-levels) ### 1.2. Retained Messages [#12-retained-messages] For publish topics, the `retain` property (type boolean) can be configured (default: false) For subscribe topics, the `retain as published` property (type boolean, default false) can be configured, as well as `retain handling`, which can be: | Retain Handling | Description | | --------------------------------------- | ---------------------------------------------------------------------------------------------- | | Send (0) | The broker sends the retained message to the subscriber when it subscribes. | | Send if Subscription Does not Exist (1) | The broker sends the retained message only if the subscription is new and didn't exist before. | | Do Not Send (2) | The broker does not send any retained messages when the subscription is made. | The default `retain handling` is `Do Not Send (2)`. For more information, see: * [EMQX Retained Messages Guide](https://www.emqx.com/en/blog/mqtt5-features-retain-message) * [HiveMQ Retained Messages Guide](https://www.hivemq.com/blog/mqtt-essentials-part-8-retained-messages/) ## 2. Shared Publish Payload Properties [#2-shared-publish-payload-properties] ### 2.1. Message ID [#21-message-id] For **published topics**, a [UUID](https://developer.mozilla.org/en-US/docs/Glossary/UUID) will be generated for all messages. Example in Payload: ```json { "messageId": "e5e7cb82-cff4-11f0-a32b-5a93ec0e6f92" } ``` ### 2.2. App Instance ID [#22-app-instance-id] For **published topics**, the `appInstanceId`, which you can find in the [Settings -> About](/docs/settings/about) screen, will be included in each message, both in the payload and as a [user property](https://www.emqx.com/en/blog/mqtt5-user-properties). Example in Payload: ```json { "appInstanceId": "c345e39c-accd-11f0-9ea0-5a93ec0e6f91" } ``` ### 2.3. Username [#23-username] For **published topics**, the MQTT connection `username` will be included in each message, both in the payload and as a [user property](https://www.emqx.com/en/blog/mqtt5-user-properties). Example in Payload: ```json { "username": "test-user-001" } ``` ## 3. Shared Subscribe Payload Properties [#3-shared-subscribe-payload-properties] ### 3.1. Message ID [#31-message-id] For **subscribed topics**, the `messageId` can be optionally specified, which will be displayed and highlighted in the debug logs For request-response, the response payload will include a `requestMessageId` property with the value you've provided when making the request. ```json { "messageId": "example-001" } ``` ### 3.2. Target Instances & Target Usernames [#32-target-instances--target-usernames] These properties are intended for convenience and testing purposes, with all messages being received and filtered client-side. It is better practice subscribe only to topics that the client needs, e.g. by modifying the default topic names and making use of the global variables. For **subscribed topics**, the `targetInstances` and `targetUsernames` (**type:** string array) can be optionally provided. Webview Kiosk will ignore messages that contain these properties if neither of its `appInstanceId` or `username` were specified in the array. When the arrays are empty (or `null`/`undefined`), all messages will be processed. Target Instances Target Usernames ```json { "targetInstances": [ "4f79ca9c-d0c6-11f0-953d-5a93ec0e6f90", "55ebdc6c-d0c6-11f0-8fcc-5a93ec0e6f90" ] } ``` ```json { "targetUsernames": [ "user-001", "user-002" ] } ``` # Request (/docs/settings/mqtt/topics/request) Webview Kiosk also utilises the request-response pattern for manual query of device information states.
This pattern is explained in: * [EMQX — MQTT 5: Request–Response](https://www.emqx.com/en/blog/mqtt5-request-response) * [HiveMQ — MQTT 5 Essentials Part 9: Request–Response Pattern](https://www.hivemq.com/blog/mqtt5-essentials-part9-request-response-pattern/)
## 1. Settings [#1-settings] ### 1.1. Topic Name [#11-topic-name] All [global variables](/docs/settings/mqtt/#3-global-variables) are supported. For example, ```js wk/${USERNAME}/${APP_INSTANCE_ID}/request ``` **Default:** ```js wk/request ``` ### 1.2. Quality of Service (QoS) [#12-quality-of-service-qos] Quality of Service (QoS) ensures different message delivery guarantees in case of connection failures. **Default:** At Most Once (0) ### 1.3. Retain Handling [#13-retain-handling] Control whether Webview Kiosk should receive existing retained messages when subscribing. **Default:** Do Not Send (2) ### 1.4. Retain as Published [#14-retain-as-published] Controls whether retained messages from the broker keep their original retained flag when delivered to the subscriber. **Default:** false ## 2. Payloads [#2-payloads] In addition to the [Shared Subscribe Payload Properties](/docs/settings/mqtt/topics/#3-shared-subscribe-payload-properties), the following properties can be provided for all requests:
Property Type Description
responseTopic string (optional) Topic the server should publish responses to. Global variables are supported. If empty, the response will be published to the configured *response topic name* in settings (default: wk/response/$\{RESPONSE\_NAME}). This is provided as a fallback, and will be overridden by MQTT's V5 metadata (3.1.3.2.6. Response Topic) if both are provided.
correlationData string (optional) Data to correlate the response with the request. In Webview Kiosk This is provided as a fallback, and will be overridden by MQTT V5 metadata (3.1.3.2.7. Correlation Data) if both are provided. In Webview Kiosk, the correlation data must be a `UTF-8` string.
### 2.1. Get Status [#21-get-status] Retrieves device and app states. Example payload: Minimal Full ```json { "requestType": "get_status" } ``` ```jsonc { "requestType": "get_status", "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], // NOTE: these can be specified as metadata in MQTT v5 "responseTopic": "wk/${APP_INSTANCE_ID}/${RESPONSE_TYPE}", "correlationData": "arbitrary-data-12345" } ``` ### 2.2. Get Settings [#22-get-settings] Retrieves configured user settings of your choosing by providing an array of setting keys inside the payload data. This array could look like: ```json [ "device.rotation", "appearance.theme" ] ``` The values for the following settings will not be returned for security reasons: * `device.custom_auth_password` * `mqtt.connection.password` If no setting keys are provided, all valid settings will be returned. #### 2.2.1. Parse as Array [#221-parse-as-array] For the the following setting keys, which are stored as strings and delimited by a new line (`\n`): 1. `web_content.website_blacklist` 2. `web_content.website_whitelist` 3. `web_content.website_bookmarks` You can optionally use the object notation below with the `parseAsArray` property: ```jsonc [ // Before "web_content.website_blacklist", // After { "key": "web_content.website_blacklist", "parseAsArray": true } ] ``` which will return them as an array of strings split by new lines. #### 2.2.2. Evaluate Variables [#222-evaluate-variables] For the following setting keys: 1. `mqtt.connection.client_id` 2. `mqtt.publish.event.topic` 3. `mqtt.publish.response.topic` 4. `mqtt.subscribe.command.topic` 5. `mqtt.subscribe.settings.topic` 6. `mqtt.will.topic` 7. `mqtt.will.payload` You can optionally use the object notation below with the `evaluateVariables` property: ```jsonc [ // Before "mqtt.connection.client_id", // After { "key": "mqtt.connection.client_id", "evaluateVariables": true } ] ``` which will interpolates global variables with static values such as `APP_INSTANCE_ID` or `USERNAME`. #### 2.2.3. Example payload [#223-example-payload] Minimal Advanced ```json { "requestType": "get_settings" } ``` ```jsonc { "requestType": "get_settings", "data": { "settings": [ "device.rotation", "appearance.theme", { "key": "web_content.website_blacklist", "parseAsArray": true }, { "key": "mqtt.connection.client_id", "evaluateVariables": true }, "web_browsing.allow_refresh" ] }, "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], // NOTE: these can be specified as metadata in MQTT v5 "responseTopic": "wk/${APP_INSTANCE_ID}/${RESPONSE_TYPE}", "correlationData": "arbitrary-data-12345" } ``` ### 2.3. Get System Info [#23-get-system-info] Retrieves device and app system information. Example payload: Minimal Full ```json { "requestType": "get_system_info" } ``` ```jsonc { "requestType": "get_system_info", "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], // NOTE: these can be specified as metadata in MQTT v5 "responseTopic": "wk/${APP_INSTANCE_ID}/${RESPONSE_TYPE}", "correlationData": "arbitrary-data-12345" } ``` ### 2.3. Get Launchable Packages [#23-get-launchable-packages] Retrieves a list of package names corresponding to applications that can be opened on the device. In the `data` property, you can optionally specify: * `filterLockTaskPermitted`: (boolean) if true, only return launchable packages that are permitted for [Lock Task Mode](https://developer.android.com/work/dpc/dedicated-devices/lock-task-mode) Example payload: Minimal Full ```json { "requestType": "get_launchable_packages" } ``` ```jsonc { "requestType": "get_launchable_packages", "data": { "filterLockTaskPermitted": true }, "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], // NOTE: these can be specified as metadata in MQTT v5 "responseTopic": "wk/${APP_INSTANCE_ID}/${RESPONSE_TYPE}", "correlationData": "arbitrary-data-12345" } ``` ### 2.4. Get Lock Task Packages [#24-get-lock-task-packages] Retrieves the list of lock task packages using [DevicePolicyManager#getLockTaskPackages](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#getLockTaskPackages\(android.content.ComponentName\)). This list is not limited to only launchable packages. If neither Device Owner nor Dhizuku privileges were granted to Webview Kiosk, an empty list will be returned. Example payload: Minimal Full ```json { "requestType": "get_lock_task_packages" } ``` ```jsonc { "requestType": "get_lock_task_packages", "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], // NOTE: these can be specified as metadata in MQTT v5 "responseTopic": "wk/${APP_INSTANCE_ID}/${RESPONSE_TYPE}", "correlationData": "arbitrary-data-12345" } ``` # Response (/docs/settings/mqtt/topics/response) Webview Kiosk also utilises the request-response pattern for manual query of device information states.
This pattern is explained in: * [EMQX — MQTT 5: Request–Response](https://www.emqx.com/en/blog/mqtt5-request-response) * [HiveMQ — MQTT 5 Essentials Part 9: Request–Response Pattern](https://www.hivemq.com/blog/mqtt5-essentials-part9-request-response-pattern/)
## 1. Settings [#1-settings] ### 1.1. Topic Name [#11-topic-name] All [global variables](/docs/settings/mqtt/#3-global-variables) are supported, in addition to `RESPONSE_TYPE`. For example, ```js wk/${USERNAME}/${APP_INSTANCE_ID}/response/${RESPONSE_TYPE} ``` If a `responseTopic` is specified in the request, either in the payload or using MQTT V5's metadata ([3.1.3.2.7. Response Topic](https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901066)), the reply will be published to that `responseTopic` instead. **Default:** ```js wk/response/${RESPONSE_TYPE} ``` ### 1.2. Quality of Service (QoS) [#12-quality-of-service-qos] Quality of Service (QoS) ensures different message delivery guarantees in case of connection failures. **Default:** At Most Once (0) ### 1.3. Retain [#13-retain] Keep response topic messages retained for new subscribers. **Default:** false ## 2. Payloads [#2-payloads] All published events will contain the [shared payload properties](/docs/settings/mqtt/topics#2-shared-payload-properties) mentioned previously, as well as the following: | Property | Type | Description | | ------------------ | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `responseType` | string | The type of response matching the request type, e.g. `get_status`. | | `requestMessageId` | string *(nullable)* | if a `messageId` was provided in the request, it will be re-used here. | | `correlationData` | string *(nullable)* | if provided in the request, either in the payload or using MQTT V5's metadata ([3.1.3.2.7. Correlation Data](https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html#_Toc3901067)), it will be present here in addition to the message's metadata. | ### 2.1. Get Status [#21-get-status] This response is published when a `get_status` request is received. Example Payload: ```json { "responseType": "get_status", "messageId": "e3d50b37-febf-4289-86ff-bf2f5506fafc", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1", "requestMessageId": null, "correlationData": null, "data": { "currentUrl": "https://webviewkiosk.nktnet.uk", "isLocked": false, "lockStateType": "NONE", "lastInteractionTime": 1764695317211, "batteryPercentage": 62, "appBrightnessPercentage": -1, "systemBrightness": 255, "isDeviceInteractive": true } } ``` ### 2.2. Get Settings [#22-get-settings] This response is published when a `get_settings` request is received. The returned settings will depend on what was included in the request payload. Example Payload: ```jsonc { "responseType": "get_settings", "messageId": "887eb103-43c8-4306-b9cc-97f1e8499fe1", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1", "requestMessageId": null, "correlationData": null, "data": { "settings": { // Response settings depends on the request payload "appearance.theme": "SYSTEM", "device.rotation": "AUTO" } } } ``` ### 2.3. Get System Info [#23-get-system-info] This response is published when a `get_system_info` request is received. ```json { "responseType": "get_system_info", "messageId": "154ec3ff-ff5a-49e6-9fa0-f6311e6893b8", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1", "requestMessageId": null, "correlationData": null, "data": { "app": { "name": "Webview Kiosk", "packageName": "uk.nktnet.webviewkiosk", "versionName": "0.25.0.12-mqtt-beta", "versionCode": 98, "minSdk": 21, "targetSdk": 36, "isDebug": true, "installer": null, "isDeviceOwner": false, "isLockTaskPermitted": true, "dhizukuPermissionGranted": true, "instanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1", "sourceCodeUrl": "https://github.com/nktnet1/webview-kiosk" }, "device": { "releaseVersion": "15", "sdkVersion": 35, "incrementalVersion": "12592187", "webViewVersion": "141.0.7390.122", "screenWidth": 1080, "screenHeight": 2400, "screenDensity": 2.625, "isManagedProfile": false, "timeZone": "Australia/Sydney", "locale": "en_US", "totalMemory": 2070986752, "totalStorage": 6228115456, "manufacturer": "Google", "model": "sdk_gphone64_arm64", "brand": "google", "device": "emu64a", "product": "sdk_gphone64_arm64", "hardware": "ranchu", "board": "goldfish_arm64", "bootloader": "unknown", "securityPatch": "2024-09-05", "supportedAbis": [ "arm64-v8a" ], "supported32BitAbis": [], "supported64BitAbis": [ "arm64-v8a" ], "buildFingerprint": "google/sdk_gphone64_arm64/emu64a:15/AE3A.240806.036/12592187:user/release-keys" } } } ``` ### 2.4. Get Launchable Packages [#24-get-launchable-packages] This response is published when a `get_launchable_packages` request is received. Example Payload: ```json { "responseType": "get_launchable_packages", "messageId": "69569438-c6c7-488f-bce4-f9b348e3baad", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1", "requestMessageId": null, "correlationData": null, "data": { "packages": [ "com.afwsamples.testdpc", "com.android.vending", "com.bintianqi.owndroid", "com.google.android.calendar", "com.google.android.deskclock", "com.looker.droidify" "com.rosan.dhizuku", "com.termux", "moe.shizuku.privileged.api" "uk.nktnet.webviewkiosk" ] } } ``` ### 2.5. Get Lock Task Packages [#25-get-lock-task-packages] This response is published when a `get_lock_task_packages` request is received. Example Payload: ```json { "responseType": "get_lock_task_packages", "messageId": "aa92ece1-4daf-4a44-83ad-cbfc5317f8c0", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1", "requestMessageId": null, "correlationData": null, "data": { "packages": [ "com.google.android.calendar", "com.google.android.deskclock", "uk.nktnet.webviewkiosk" ] } } ``` ### 2.6. Error [#26-error] This response is published whenever an error occurs with processing a request. For example, the `requestType` could be invalid. Example Payload: ```json { "responseType": "error", "messageId": "058a8f44-d34a-43b6-a7e7-8f5537cea62f", "username": "medium-phone-api-35", "appInstanceId": "42188f0c-6784-4a52-95b6-8569f0f4d2f1", "requestMessageId": null, "correlationData": null, "payloadStr": "{\n \"requestType\": \"invalid\"\n}", "errorMessage": "Unexpected JSON token at offset 0: Serializer for subclass 'invalid' is not found in the polymorphic scope of 'MqttRequestMessage' at path: $\nCheck if class with serial name 'invalid' exists and serializer is registered in a corresponding SerializersModule.\nTo be registered automatically, class 'invalid' has to be '@Serializable', and the base class 'MqttRequestMessage' has to be sealed and '@Serializable'.\nJSON input: {\n \"requestType\": \"invalid\"\n}" } ``` # Settings (/docs/settings/mqtt/topics/settings) ## 1. Settings [#1-settings] ### 1.1. Topic Name [#11-topic-name] All [global variables](/docs/settings/mqtt/#3-global-variables) are supported, in addition to `EVENT_TYPE`. For example, ```js wk/${USERNAME}/${APP_INSTANCE_ID}/settings ``` **Default:** ```js wk/settings ``` ### 1.2. Quality of Service (QoS) [#12-quality-of-service-qos] Quality of Service (QoS) ensures different message delivery guarantees in case of connection failures. **Default:** At Most Once (0) ### 1.3. Retain Handling [#13-retain-handling] Control whether Webview Kiosk should receive existing retained messages when subscribing. **Default:** Do Not Send (2) ### 1.4. Retain as Published [#14-retain-as-published] Controls whether retained messages from the broker keep their original retained flag when delivered to the subscriber. **Default:** false ## 2. Payloads [#2-payloads] In addition to the [Shared Subscribe Payload Properties](/docs/settings/mqtt/topics/#3-shared-subscribe-payload-properties), the following properties can be specified: | Property | Type | Description | | ---------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | `showToast` | boolean *(optional)* | Whether a toast message should be displayed.
**Default:** `true` | | `reloadActivity` | boolean *(optional)* | Whether the activity should be reloaded, which is necessary for some settings to take effect (e.g. `device.rotation`).
**Default:** `true` | For a list of available setting keys, refer to [./app/src/main/res/xml/app\_restrictions.xml](https://github.com/nktnet1/webview-kiosk/blob/main/app/src/main/res/xml/app_restrictions.xml). Example Payloads: Minimal Advanced ```json { "data": { "settings": { "appearance.theme": "LIGHT" } } } ``` ```json { "data": { "settings": { "web_browsing.allow_refresh": false, "web_browsing.address_bar_actions": [ "GO_BACK", "GO_FORWARD", "REFRESH" ], "appearance.theme": "LIGHT", "appearance.address_bar_position": "BOTTOM" } }, "messageId": "example-001", "targetInstances": ["070219ea-d0cb-11f0-9e76-5a93ec0e6f90"], "targetUsernames": ["user-001"], "showToast": false, "reloadActivity": false } ``` If a key is specified, but its value is invalid (e.g. wrong type), the default value for the key (which may differ from the current value) will be used. # Will (LWT) (/docs/settings/mqtt/will) For more information about the Last Will and Testament (LWT), refer to: * [EMQX - Use of MQTT Will Message](https://www.emqx.com/en/blog/use-of-mqtt-will-message) * [HiveMQ - MQTT Essentials Part 9: Last Will and Testament](https://www.hivemq.com/blog/mqtt-essentials-part-9-last-will-and-testament) The settings below are modelled after HiveMQ client library's documentation for [connect#will](https://hivemq.github.io/hivemq-mqtt-client/docs/mqtt-operations/connect/#will). ### 1. Topic [#1-topic] The MQTT topic to publish the last will message if the client disconnects unexpectedly. All global variables are supported, e.g. you can use ```js wk/${USERNAME}/${APP_INSTANCE_ID}/will ``` **Default:** wk/will ### 2. Will QoS [#2-will-qos] Quality of Service (QoS) for the MQTT last will message. Determines the guarantee of message delivery in case of client disconnect. **Default:** At Most Once (0) ### 3. Payload [#3-payload] The MQTT payload to send for the last will message if the client disconnects unexpectedly. **Default:** ```json { "message": "Client has disconnected.", "username": "${USERNAME}", "appInstanceId": "${APP_INSTANCE_ID}" } ``` ### 4. Retain [#4-retain] Set to true to retain the last will message on the broker after it is sent. **Default:** false ### 5. Message Expiry Interval (seconds) [#5-message-expiry-interval-seconds] The lifetime in seconds of the last will message on the broker after it is sent. A value of 0 means the message does not expire. **Default:** 0 ### 6. Will Delay Interval (seconds) [#6-will-delay-interval-seconds] Time in seconds the broker will wait before sending the last will message after the client disconnects unexpectedly. A value of 0 means immediate delivery. **Default:** 0 # UnifiedPush (/docs/settings/unifiedpush) ## 1. Introduction [#1-introduction] UnifiedPush is a decentralised push notification system designed to be privacy-friendly, flexible, and open. For more information, see the official documentation: [https://unifiedpush.org](https://unifiedpush.org) Webview Kiosk utilises UnifiedPush to enable you to remotely: * update app settings * perform actions via commands ## 2. Distributor [#2-distributor] To use UnifiedPush with Webview Kiosk, you will need to choose a [distributor](https://unifiedpush.org/users/distributors) application, e.g. * [sunup](https://codeberg.org/Sunup/android) * [ntfy (android)](https://github.com/binwiederhier/ntfy-android) You will also need a push server, e.g. by self-hosting or using the public servers for: * [autopush-rs](https://github.com/p1gp1g/autopush-rs) * [ntfy (server)](https://github.com/binwiederhier/ntfy) ## 3. Debug Logs [#3-debug-logs] UnifiedPush operations are recorded in the debug logs, which can be accessed from the UnifiedPush settings screen. This includes * register/unregister * message received * new endpoint * errors A maximum of 100 messages will be stored for the duration of the app activity lifecycle. The logs will not persist between app restarts. ## 4. Settings [#4-settings] ### 4.1. Enabled [#41-enabled] Allow Webview Kiosk to process new push messages or register new endpoints. **Default:** false ### 4.2. Distributor [#42-distributor] The package name of the [distributor](https://unifiedpush.org/users/distributors), e.g. * org.unifiedpush.distributor.sunup * io.heckel.ntfy The distributor app serves as the middle-man that receives the app notification from the push server and forwarding it to Webview Kiosk. **Default:** (blank) ### 4.3. Instance [#43-instance] Registration instance. Can be used to create multiple registrations. Supported variables: * `APP_INSTANCE_ID` Example: * `wk-${APP_INSTANCE_ID}` If left blank, `default` will be used. **Default:** (blank) ### 4.4. Message for Distributor [#44-message-for-distributor] A customised message that may be shown by the distributor UI to identify this registration. **Default:** (blank) ### 4.5. VAPID Public Key [#45-vapid-public-key] VAPID public key (RFC8292), base64url, in uncompressed form (87 chars long). For more details, see: * [https://www.rfc-editor.org/rfc/rfc8292](https://www.rfc-editor.org/rfc/rfc8292) **Default:** (blank) ### 4.6. Process Unencrypted Messages [#46-process-unencrypted-messages] When enabled, Webview Kiosk will also handle UnifiedPush messages that did not successfully decrypt. A valid use case for this would be to for sending simple curl requests to `ntfy.sh` without encryption for testing or convenience, although this reduces security. **Default:** false ### 4.7. Store Endpoint Credentials [#47-store-endpoint-credentials] When enabled, Webview Kiosk will persist the following values after registration: * Endpoint URL * Endpoint Public Key * Endpoint Auth Secret Ideally, these values should not be stored at all, and are instead sent directly to the application server at the point of registration. However, Webview Kiosk does not yet have an application server. These values are thus stored locally in the application so they can be copied. They can be optionally redacted afterwards through the settings UI. **Default:** true # Integration (/docs/settings/unifiedpush/integration) ## 1. Curl (ntfy) [#1-curl-ntfy] This solution is specific to the ntfy server and is less secure than web push. If you use [ntfy](https://github.com/binwiederhier/ntfy) as your distributor and push server, it is possible to send push messages directly to Webview Kiosk via an [API client](https://www.postman.com/api-platform/api-client/) such as [curl](https://curl.se). To use this method, you will need to enable the setting `UnifiedPush -> Process Unencrypted Messages`. Example: Command Settings ```bash # NOTE: Replace the URL with your registered endpoint curl 'https://ntfy.sh/upKsJhj5FnOYoT?up=1' \ -d '{ "type": "command", "command": "go_to_url", "data": { "url": "https://webviewkiosk.nktnet.uk" } }' ``` ```bash # NOTE: Replace the URL with your registered endpoint curl 'https://ntfy.sh/upKsJhj5FnOYoT?up=1' \ -d '{ "type": "settings", "data": { "settings": { "appearance.theme": "LIGHT" } } }' ``` ## 2. Web Push [#2-web-push] The guide below uses JavaScript (TypeScript). Create an empty project with the following `package.json`: ```json { "type": "module", "dependencies": { "dotenv": "^17.2.3", "valibot": "^1.2.0", "web-push": "^3.6.7" }, "devDependencies": { "@types/node": "^25.0.9", "@types/web-push": "^3.6.4", "tsx": "^4.21.0", "typescript": "^5.9.3" } } ``` Use your preferred package manager to install the dependencies: ```sh pnpm install ``` Create `src/vapid.ts` with the following content: ```ts import webPush from "web-push"; const generateVAPID = () => { const vapidKeys = webPush.generateVAPIDKeys(); const vapidSubject = "mailto:admin@example.com"; console.log("Add the following to your .env file:\n"); console.log(`VAPID_PUBLIC_KEY=${vapidKeys.publicKey}`); console.log(`VAPID_PRIVATE_KEY=${vapidKeys.privateKey}`); console.log(`VAPID_SUBJECT=${vapidSubject}`); }; if (import.meta.url === `file://${process.argv[1]}`) { void generateVAPID(); } ``` Generate your VAPID keys: ```sh pnpx tsx src/vapid.ts ``` Create a new file called `.env` and populate first 3 VAPID values below: ```bash # VAPID keys VAPID_PUBLIC_KEY= VAPID_PRIVATE_KEY= VAPID_SUBJECT= # UnifiedPush Credentials ENDPOINT_URL= ENDPOINT_PUBLIC_KEY= ENDPOINT_AUTH_SECRET= ``` In Webview Kiosk, under the `Settings -> UnifiedPush` screen, 1. Enable UnifiedPush 2. Select a distributor (e.g. ntfy or sunup) 3. Paste in your VAPID public key (generated in a previous step) Click the `Register` button, then expand the status box and copy the * Endpoint URL * Endpoint Public Key * Endpoint Auth Secret To your `.env` file. Create `src/index.ts` with the following content: ```ts import webPush from "web-push"; import * as v from "valibot"; import "dotenv/config"; const WebPushEnvSchema = v.object({ VAPID_PUBLIC_KEY: v.string(), VAPID_PRIVATE_KEY: v.string(), VAPID_SUBJECT: v.string(), ENDPOINT_URL: v.string(), ENDPOINT_PUBLIC_KEY: v.string(), ENDPOINT_AUTH_SECRET: v.string(), }); const createToast = async () => { const env = v.parse(WebPushEnvSchema, process.env); webPush.setVapidDetails( env.VAPID_SUBJECT, env.VAPID_PUBLIC_KEY, env.VAPID_PRIVATE_KEY, ); const res = await webPush.sendNotification( { endpoint: env.ENDPOINT_URL, keys: { p256dh: env.ENDPOINT_PUBLIC_KEY, auth: env.ENDPOINT_AUTH_SECRET, }, }, JSON.stringify({ type: "command", command: "toast", wakeScreen: true, data: { message: "Hello from UnifiedPush!", }, }), ); return res; }; /** * This will create a small pop-up message on Webview Kiosk */ void createToast() .then((data) => { console.log(data); process.exit(0); }) .catch((err) => { console.error(err); process.exit(1); }); ``` Run the script with: ```sh pnpx tsx src/index.ts ``` This will result in Webview Kiosk creating an on-screen message (i.e. toast) on your device. # Messages (/docs/settings/unifiedpush/messages) Webview Kiosk push message payloads are similar to that of [MQTT](/docs/settings/mqtt). However, all messages are sent to a single UnifiedPush endpoint instead of being separated by topics. A `type` property is used to differentiate between the different actions such as `command` and `settings`. ## 1. Command [#1-command] For additional options and the full list of supported commands, refer to [MQTT -> Topics -> Command](/docs/settings/mqtt/topics/command#2-payloads). Example Payload ```jsonc { // Unique to UnifiedPush "type": "command", // Same as MQTT "command": "go_to_url", "data": { "url": "https://webviewkiosk.nktnet.uk" } } ``` ## 2. Settings [#2-settings] For additional options, refer to [MQTT -> Topics -> Settings](/docs/settings/mqtt/topics/settings#2-payloads). Example Payload ```jsonc { // Unique to UnifiedPush "type": "settings", // Same as MQTT "data": { "settings": { "appearance.theme": "LIGHT" } } } ``` # Web Browsing (/docs/settings/web-browsing) ## 1. Allow Refresh [#1-allow-refresh] Set to true to allow the user to refresh the page, e.g. using the * address bar actions * kiosk control panel * pull to refresh (can be configured separately) **Default:** true ## 2. Allow Pull to Refresh [#2-allow-pull-to-refresh] Set to true to allow the user to refresh the page by pulling down from the top 1/4 of the screen. Note that this requires: * the `Allow Refresh` setting to also be true * the page to have been scrolled fully to the top prior to the gesture * a single finger (touch) is used **Default:** true ## 3. Allow Backwards Navigation [#3-allow-backwards-navigation] Set to true to allow the user to go back one page in history. This also enables forward navigation. **Default:** true ## 4. Allow Go Home [#4-allow-go-home] Set to true to allow the user to go home using one of: 1. Tapping the top-left quadrant of the screen 10 times in quick succession (opens Kiosk Control Panel) 2. Holding the back button (long-pressed). For more details, see `Settings -> Device` 3. Clicking the () icon on the right of the address bar (top-right corner of screen) and selecting `Home` 4. Clicking the floating toolbar () icon and selecting `Home` 5. Clicking your device's home button * This requires Webview Kiosk to be set as the **default launcher (home) app** **Default:** true ## 5. Clear History on Home [#5-clear-history-on-home] Set to true if you want to clear the backwards/forward navigation history whenever a `Go Home` action is triggered. **Default:** false ## 6. Replace History URL on Redirect [#6-replace-history-url-on-redirect] Set to true to replace the current history entry with the final URL if any page redirections occurs, rather than adding multiple entries to the history navigation stack. **Default:** true ## 7. Allow History Access [#7-allow-history-access] Set to true to allow viewing and navigating back in history, by clicking the () icon on the right of the address bar (top-right corner of screen) and selecting `History`. **Default:** true ## 8. Allow Bookmark Access [#8-allow-bookmark-access] Set to true to allow viewing and navigating to bookmarks configured in settings, by clicking the () icon on the right of the address bar (top-right corner of screen) and selecting `Bookmark`. **Default:** true ## 9. Allow Other URL Schemes [#9-allow-other-url-schemes] Allow the handling of non-http/https URL schemes (i.e. intents) such as `intent:`, `mailto:`, `sms:`, `tel`:, `spotify:`, `whatsapp:`, `unifiedpush:`, etc in other apps. When in Lock Task Mode, the apps responsible for handling these intents needs to be present in the Lock Task Permitted list under the device owner settings to function. **Default:** false ## 10. Allow Default Long Press [#10-allow-default-long-press] When enabled, long-pressing areas in the WebView will trigger the native WebView behaviour, e.g. text selection. Specifically for links, even if set to false, this setting can be overridden by the `Allow Link Long Press Context Menu` setting. **Default:** true ## 11. Allow Link Long Press Context Menu [#11-allow-link-long-press-context-menu] When enabled, long-pressing links or images will trigger a custom context menu. This will take precedence over the `Allow Default Long Press` setting (i.e. overrides it). For links, the options are: * Copy Link * Open Link * Open in Browser (when unlocked) * Share Link (when unlocked) For images, there is an additional option: * Download Image (requires `web_engine.allow_file_download`) **Default:** true ## 12. Override URL Loading Block Action [#12-override-url-loading-block-action] Action to take when a URL navigation (via [shouldOverrideUrlLoading](https://developer.android.com/reference/android/webkit/WebViewClient#shouldOverrideUrlLoading\(android.webkit.WebView,%20android.webkit.WebResourceRequest\)])) matches the blacklist regex. Typically, this is from clicking links (`` tags) on a webpage's HTML. | Action | Description | | ------------------ | -------------------------------------------- | | Show Block Page | Display a HTML block page | | Prevent Navigation | Does nothing when links are clicked | | Show Toast | Shows a toast with your custom block message | This option will NOT take effect for: * JavaScript navigation * Custom URL loading, e.g. from the Address Bar, Bookmarks, History, etc In those other cases, the block page will simply be shown. **Default:** Show Block Page ## 13. Address Bar Actions [#13-address-bar-actions] This setting is only controlling the UI aspect of the Address Bar. Access will still need to be enabled using the dependent settings. See the `Settings Web Browsing -> Kiosk Control Panel Actions` for a list of available actions. ## 14. Kiosk Control Panel Region [#14-kiosk-control-panel-region] Controls which part of the screen can be multi-tapped 10 times in quick succession to show the Kiosk Control Panel dialog. Available regions are:
Region Description
Top Left Upper-left quadrant of the screen.
Top Right Upper-right quadrant of the screen.
Bottom Left Lower-left quadrant of the screen.
Bottom Right Lower-right quadrant of the screen.
Top Upper half of the screen.
Bottom Lower half of the screen.
Full Entire screen.
Disabled Do nothing on multi-tap. Please note that if both of the following are true:
  1. Web Browsing -> Kiosk Control Panel Region is disabled
  2. Device -> Back Button Hold Action is not set to Open Kiosk Control Panel
Then this option cannot be disabled, and will default to Top Left.
At the top-right corner of the dialog, there is an icon button that toggles the stickiness Kiosk Control Panel's stickiness behaviour. By default, sticky mode is disabled (). When enabled (), clicking on the action buttons will not automatically close the dialog. You can also disable this setting and instead configure `Device -> Back Button Hold Action` to open the Kiosk Control Panel. **Default:** Top left ## 15. Kiosk Control Panel Actions [#15-kiosk-control-panel-actions] This setting is only controlling the UI aspect of the Kiosk Control Panel. Access will still need to be enabled using the dependent settings. The following actions are available to be configured (remove or rearrange):
Action Description
Navigation Combination of Back and Forward buttons side-by-side. Requires Web Browsing -> Allow Backwards Navigation
Back Navigates one page backwards in history. Requires Web Browsing -> Allow Backwards Navigation
Forward Navigates one page forward in history. Requires Web Browsing -> Allow Backwards Navigation
Home Navigates to the home page. Requires Web Browsing -> Allow Go Home
Refresh Perform a reload on the current webpage. Requires Web Browsing -> Allow Refresh
History Opens the history dialog. Requires Web Browsing -> Allow History Access
Bookmark Opens the bookmark dialog. Requires Web Browsing -> Allow Bookmark Access
Files Opens the local files dialog. Requires Web Content -> Allow Local Files
Find Opens a search bar to find matching text on the page.
Scroll Top Scrolls to the top of the page.
Scroll Bot Scrolls to the bottom of the page.
Apps Opens a dialog allowing you to launch other apps. When in lock task mode (kiosk), the following are required to launch apps:
  1. Your device is on Android 9+ (SDK/API level 28+)
  2. Webview Kiosk is lock task permitted
  3. The target app is lock task permitted
  4. Lock Task Feature -> HOME is enabled
The last condition helps avoid being trapped in lock task mode. It enables the use of the home button to open your default launcher (which *may* show an error that you can safely dismiss). From the launcher, you can find and open Webview Kiosk to unlock the kiosk. You may want to also consider:
  1. Granting notifications permission to Webview Kiosk
  2. Enabling Lock Task Feature -> NOTIFICATIONS
  3. Setting Webview Kiosk as the default launcher
The first two suggestions is to display the foreground service notification in lock task mode. Tapping on the notification will return you to Webview Kiosk. Please note that for user-owned devices utilising "Screen Pinning" mode, app launching is not supported. Refer to the Security documentation for further details.
Settings Open the app settings screen. By default, this action is not configured. This will always be visible if Appearance -> Floating Toolbar Mode is set to Hidden, and will be appended to the end if not configured.
Lock Trigger either screen pinning or lock task mode.
Unlock Trigger screen unpinning or unlock task. Will require biometrics or device credentials to succeed. This action will always be visible when the device is in locked mode, and will be appended to the end if not configured.
## 16. Search Provider URL [#16-search-provider-url] The URL used for search queries in the address bar. This URL must include the search string query parameter. For example, | Provider | Search URL | | ----------- | ------------------------------------ | | Google | `https://google.com/search?q=` | | DuckDuckGo | `https://duckduckgo.com/?q=` | | Bing | `https://bing.com/search?q=` | | Yahoo | `https://search.yahoo.com/search?p=` | | Startpage | `https://startpage.com/do/search?q=` | | Ecosia | `https://ecosia.org/search?q=` | | Unduck | `https://unduck.link?q=` | | Unduckified | `https://s.dunkirk.sh?q=` | **Default:** [https://duckduckgo.com?q=](https://duckduckgo.com?q=) ## 17. Search Suggestion Engine [#17-search-suggestion-engine] Configure the search engine for text suggestions (autocomplete/hints) when typing in the address bar. For example, when searching for "new", you may get suggested * news * new recipes * new york times Supported options are: | Engine | Endpoint | | ---------- | ---------------------------------------------------------------------------- | | None | No search suggestions/autocomplete will be shown | | Google | `https://suggestqueries.google.com/complete/search?client=firefox&q=` | | DuckDuckGo | `https://duckduckgo.com/ac?q=` | | Yahoo | `https://api.search.yahoo.com/sugg/gossip/gossip-in-ura?output=sd1&command=` | **Default:** NONE # Web Content (/docs/settings/web-content) ## 1. Home URL [#1-home-url] Configure the Home URL, which can be returned to as per
`Web Browsing -> Allow Go Home`. **Default:** [https://webviewkiosk.nktnet.uk](https://webviewkiosk.nktnet.uk) ## 2. Blacklist & Whitelist Regex [#2-blacklist--whitelist-regex] Specify regular expressions (regex), one per line. Escaping is required for special characters in regex like `.` and `?`. These patterns also use partial matching. If you need strict control, anchor your regex with `^` and `$`. Whitelist patterns take precedence over blacklist patterns. **Default:** (blank) ### 2.1. Blacklist Example [#21-blacklist-example] Block all: ``` .* ``` Block google, including all subdomains and paths: ``` ^https://.*\.?google\.com/?.* ``` ### 2.2. Whitelist Example [#22-whitelist-example] Allow `https://allowsite.com` home page and all subdomains and paths for `https://trusted.org` to bypass rules in the blacklist: ``` ^https://trusted\.org/?$ ^https://.*\.trusted\.org/?.* ``` ### 2.3. Regex Playground [#23-regex-playground] ## 3. Bookmarks [#3-bookmarks] Specify bookmarked URLs one per line. Blank lines will be ignored. This is accessible in the address bar. See the relevant setting `Web Browsing -> Allow Bookmark Access`. You can also specify a title for display in the format: ` | `. For example: ```log https://webviewkiosk.nktnet.uk | Webview Kiosk https://duckduckgo.com | DuckDuckGo https://f-droid.org | F-Droid ``` **Default:** (blank) ## 4. Support PDF Rendering [#4-support-pdf-rendering] Set to true to support PDF Rendering using Mozilla's PDF.js renderer: * [https://github.com/mozilla/pdf.js](https://github.com/mozilla/pdf.js) You will first need to download the renderer by opening the popup menu for this setting and clicking the `Download PDF.js assets` button. Remote PDF files are loaded through a dummy endpoint: * [https://pdf-dummy.webviewkiosk.nktnet.uk?wk\_pdf\_url=\[SAMPLE\_PDF\_URL\].pdf](https://pdf-dummy.webviewkiosk.nktnet.uk?wk_pdf_url=\[SAMPLE_PDF_URL].pdf) which gets locally routed to the downloaded PDF.js renderer using the WebViewAssetLoader API: * [https://developer.android.com/reference/androidx/webkit/WebViewAssetLoader](https://developer.android.com/reference/androidx/webkit/WebViewAssetLoader) **Default:** false ## 5. Allow Local Files [#5-allow-local-files] Set to true to enable access to local files (html, image, text) that were uploaded in the app settings via the 3-dot icon <span className="inline-flex">(<EllipsisVertical />)</span> on the right of the address bar. **Default:** true # Web Engine (/docs/settings/web-engine) ## 1. Enable JavaScript [#1-enable-javascript] When enabled, the WebView can execute JavaScript code on web pages. This is required for most modern websites to function properly. **Android API:** [WebSettings#setJavaScriptEnabled(boolean)](https://developer.android.com/reference/android/webkit/WebSettings#setJavaScriptEnabled\(boolean\)) **Default:** true ## 2. Enable DOM Storage [#2-enable-dom-storage] When enabled, websites can use DOM storage APIs such as `localStorage` and `sessionStorage`. Useful for saving data client-side in the browser context. **Android API:** [WebSettings#setDomStorageEnabled(boolean)](https://developer.android.com/reference/android/webkit/WebSettings#setDomStorageEnabled\(boolean\)) **Default:** true ## 3. Accept Cookies [#3-accept-cookies] When enabled, the WebView allows websites to store and read cookies. This includes first-party cookies that persist session or preference data. **Android API:** [CookieManager#setAcceptCookie(boolean)](https://developer.android.com/reference/android/webkit/CookieManager#setAcceptCookie\(boolean\)) **Default:** true ## 4. Accept Third-party Cookies [#4-accept-third-party-cookies] When enabled, third-party websites (embedded in iframes or resources) are allowed to set cookies. This is important for services like embedded analytics or login widgets. **Android API:** [CookieManager#setAcceptThirdPartyCookies(android.webkit.WebView, boolean)](https://developer.android.com/reference/android/webkit/CookieManager#setAcceptThirdPartyCookies\(android.webkit.WebView,%20boolean\)) **Default:** false ## 5. Cache Mode [#5-cache-mode] Controls how the WebView uses its cache when loading pages. Options: * **Default (`LOAD_DEFAULT`)** - Normal caching behavior; the WebView decides when to use cached content. * **Cache else network (`LOAD_CACHE_ELSE_NETWORK`)** - Uses cached content if available; otherwise fetches from network. * **No cache (`LOAD_NO_CACHE`)** - Always fetches from the network; ignores cached content. * **Cache only (`LOAD_CACHE_ONLY`)** - Only loads content from cache; network requests are skipped. **Android API:** [WebSettings#LOAD\_CACHE\_ELSE\_NETWORK](https://developer.android.com/reference/android/webkit/WebSettings#LOAD_CACHE_ELSE_NETWORK) **Default:** `LOAD_DEFAULT` ## 6. User Agent [#6-user-agent] The User Agent string controls how the web engine identifies itself to websites. Some sites may behave differently depending on this value. Leave blank to use the system default User Agent. **Android API:** [WebSettings#setUserAgentString(java.lang.String)](https://developer.android.com/reference/android/webkit/WebSettings#setUserAgentString\(java.lang.String\)) **Default:** (blank) ## 7. Layout Algorithm [#7-layout-algorithm] Controls how the WebView arranges and scales content. Options: * **Normal** - No rendering changes. Recommended for maximum compatibility across different platforms and Android versions. * **Single Column** - Moves all content into one column that is the width of the view. **Deprecated in API 29** * **Narrow Columns** - Makes all columns no wider than the screen if possible. Only use for API levels prior to KitKat. **Deprecated in API 29** * **Text Autosizing** - Boosts font size of paragraphs based on heuristics to make text readable in wide-viewport layouts. Recommended to enable zoom support. Supported from API level KitKat. **Android API:** [WebSettings.LayoutAlgorithm](https://developer.android.com/reference/android/webkit/WebSettings.LayoutAlgorithm) **Default:** `NORMAL` ## 8. Use Wide ViewPort [#8-use-wide-viewport] When enabled, the WebView will use a viewport wide enough to fit the content as if viewed on a desktop browser. **Android API:** [WebSettings#setUseWideViewPort(boolean)](https://developer.android.com/reference/android/webkit/WebSettings#setUseWideViewPort\(boolean\)) **Default:** true ## 9. Load With Overview Mode [#9-load-with-overview-mode] When enabled, the WebView scales the page so that the content fits on screen initially. **Android API:** [WebSettings#setLoadWithOverviewMode(boolean)](https://developer.android.com/reference/android/webkit/WebSettings#setLoadWithOverviewMode\(boolean\)) **Default:** true ## 10. Zoom [#10-zoom] ### 10.1. Support Zoom [#101-support-zoom] Sets whether the WebView should support zooming using its on-screen zoom controls and gestures. **Android API:** [WebSettings#setSupportZoom(boolean)](https://developer.android.com/reference/android/webkit/WebSettings#setSupportZoom\(boolean\)) **Default:** true ### 10.2. Built In Zoom Controls [#102-built-in-zoom-controls] Sets whether the WebView should use its built-in zoom mechanisms. The built-in zoom mechanisms comprise on-screen zoom controls, which are displayed over the WebView's content, and the use of a pinch gesture to control zooming. **Android API:** [WebSettings#setBuiltInZoomControls(boolean)](https://developer.android.com/reference/android/webkit/WebSettings#setBuiltInZoomControls\(boolean\)) **Default:** true ### 10.3. Display Zoom Controls [#103-display-zoom-controls] Sets whether the WebView should display on-screen zoom controls when using the built-in zoom mechanisms. **Android API:** [WebSettings#setDisplayZoomControls(boolean)](https://developer.android.com/reference/android/webkit/WebSettings#setDisplayZoomControls\(boolean\)) **Default:** false ### 10.4. Initial Scale [#104-initial-scale] Sets the initial scale for this WebView as a percentage. 0 means default. The behavior for the default scale depends on the state of * useWideViewPort * loadWithOverviewMode If the content fits into the WebView control by width, the zoom is set to 100%. For wide content, the behaviour depends on the state of loadWithOverviewMode. If its value is true, the content will be zoomed out to be fit by width into the WebView control, otherwise not. If initial scale is greater than 0, WebView starts with this value as initial scale. Please note that unlike the scale properties in the viewport meta tag, this method doesn't take the screen density into account. **Android API:** [WebView#setInitialScale(int)](https://developer.android.com/reference/android/webkit/WebView#setInitialScale\(int\)) **Default:** 0 ## 11. File Access [#11-file-access] These settings are insecure and deprecated. To access `file://` URLs, you will also need to enable `Web Content -> Allow Local Files`, which will set [WebSettings#setAllowFileAccess(boolean)](https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccess\(boolean\)) accordingly. ### 11.1. Allow File Access from File URLs [#111-allow-file-access-from-file-urls] This method was deprecated in API level 30. Sets whether cross-origin requests in the context of a file scheme URL should be allowed to access content from other file scheme URLs. Note that some accesses such as image HTML elements don't follow same-origin rules and aren't affected by this setting. Don't enable this setting if you open files that may be created or altered by external sources. Enabling this setting allows malicious scripts loaded in a `file://` context to access arbitrary local files including WebView cookies and app private data. **Android API:** [WebSettings#setAllowFileAccessFromFileURLs(boolean)](https://developer.android.com/reference/android/webkit/WebSettings#setAllowFileAccessFromFileURLs\(boolean\)) **Default:** false ### 11.2. Allow Universal Access from File URLs [#112-allow-universal-access-from-file-urls] This method was deprecated in API level 30. Sets whether cross-origin requests in the context of a file scheme URL should be allowed to access content from any origin. This includes access to content from other file scheme URLs or web contexts. Note that some access such as image HTML elements doesn't follow same-origin rules and isn't affected by this setting. Don't enable this setting if you open files that may be created or altered by external sources. Enabling this setting allows malicious scripts loaded in a `file://` context to launch cross-site scripting attacks, either accessing arbitrary local files including WebView cookies, app private data or even credentials used on arbitrary web sites. **Android API:** [WebSettings#setAllowUniversalAccessFromFileURLs(boolean)](https://developer.android.com/reference/android/webkit/WebSettings#setAllowUniversalAccessFromFileURLs\(boolean\)) **Default:** false ## 12. Allow File Picker [#12-allow-file-picker] Allow websites to open the system file picker, e.g. for uploading files. **Android API:** <a href="https://developer.android.com/reference/android/webkit/WebChromeClient#onShowFileChooser(android.webkit.WebView,%20android.webkit.ValueCallback%3Candroid.net.Uri[]%3E,%20android.webkit.WebChromeClient.FileChooserParams)" target="_blank" rel="noopener noreferrer">WebChromeClient#onShowFileChooser</a> **Default:** false ## 13. Allow File Download [#13-allow-file-download] Allow files to be downloaded from websites to the device's default download directory, e.g. `/storage/emulated/0/Download/` For Android 9.0 (SDK 28) and below, the `WRITE_EXTERNAL_STORAGE` permission is required. **Android API:** [WebView#setDownloadListener(android.webkit.DownloadListener)](https://developer.android.com/reference/android/webkit/WebView#setDownloadListener\(android.webkit.DownloadListener\)) **Default:** false ## 14. Media Playback Requires User Gesture [#14-media-playback-requires-user-gesture] Sets whether the WebView requires a user gesture (e.g. tap) to play media. **Android API:** [WebSettings#setUseWideViewPort(boolean)](https://developer.android.com/reference/android/webkit/WebSettings#setMediaPlaybackRequiresUserGesture\(boolean\)) **Default:** true ## 15. SSL Error Mode [#15-ssl-error-mode] Configure the action to take when an SSL Error is received. | Mode | Description | | ------- | ---------------------------------------------------------------- | | Block | Cancels all failed SSL requests. | | Prompt | Opens a dialog for the user to decide. | | Proceed | Always proceeds despite SSL errors (dangerous, NOT RECOMMENDED). | **Default:** Block ## 16. Mixed Content Mode [#16-mixed-content-mode] Configures the WebView's behavior when a secure origin attempts to load a resource from an insecure origin. | Mode | Description | | ------------------ | --------------------------------------------------------------------------------------------------------- | | Never Allow | Blocks any mixed content from insecure origins. This is the safest and recommended mode. | | Compatibility Mode | Allows mixed content in a backward-compatible way, depending on Android version. Use with caution. | | Always Allow | Loads mixed content from insecure origins without restriction. Strongly discouraged for security reasons. | **Android API:** [WebSettings#setMixedContentMode(int)](https://developer.android.com/reference/android/webkit/WebSettings#setMixedContentMode\(int\)) **Default:** Never Allow ## 17. Over Scroll Mode [#17-over-scroll-mode] Configures the WebView's behavior when the user scrolls beyond the content boundaries. | Mode | Description | | ------------------ | --------------------------------------------------------------------------- | | Always | Allows over-scroll effect regardless of content size. | | If Content Scrolls | Allow over-scrolling only if the view content is larger than the container. | | Never | Prevents any over-scroll effect. | **Android API:** [WebView#setOverScrollMode(int)](https://developer.android.com/reference/android/webkit/WebView#setOverScrollMode\(int\)) **Default:** If Content Scrolls ## 18. Request Focus On Page Start [#18-request-focus-on-page-start] Sets whether the WebView should request focus when a page starts loading. **Android API:** [WebView#requestFocus(int, android.graphics.Rect)](https://developer.android.com/reference/android/webkit/WebView#requestFocus\(int,%20android.graphics.Rect\)) **Default:** true # Web Lifecycle (/docs/settings/web-lifecycle) ## 1. Lock on Launch [#1-lock-on-launch] When enabled, the app will immediately enter locked/pinned mode on startup, preventing exit until unpinned. On some devices, you may still be prompted with a confirmation screen. **Default:** false ## 2. Reset on Launch [#2-reset-on-launch] When enabled, the app will always start fresh at the Home URL when closed and re-opened, as opposed to the last visited URL. The navigation history will also be cleared. **Default:** false ## 3. Reset On Inactivity (seconds) [#3-reset-on-inactivity-seconds] Number of seconds of inactivity before the app resets to the home URL. When there is 5 seconds left, a warning countdown will be shown on the screen. The navigation history will be cleared when resetting. To disable, use the value `0`. **Minimum:** 10 **Default:** 0 ## 4. Dim Screen On Inactivity (seconds) [#4-dim-screen-on-inactivity-seconds] Number of seconds of inactivity before the screen is dimmed (brightness = 0). This will set the app brightness to 0, and will restore the brightness to your `device -> brightness` setting upon new user interactions. **Minimum:** 10 **Default:** 0 ## 5. Refresh on Network Available [#5-refresh-on-network-available] Select when the page should automatically refresh when network connectivity is restored. * **Always:** refresh whenever a network connection is available * **On Page Error:** only refresh if the previous page load failed * **Never:** do not refresh automatically **Default:** On Page Error ## 6. Refresh on Loading Error Interval (seconds) [#6-refresh-on-loading-error-interval-seconds] Interval in seconds between automatic refresh attempts when a page fails to load. This usually indicate the inability to connect to the server, e.g. due to no internet connection or the server is offline. This is detected using the Android API: [WebViewClient#onReceivedError](https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedError\(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20android.webkit.WebResourceError\)) in conjunction with [WebResourceRequest#isForMainFrame](https://developer.android.com/reference/android/webkit/WebResourceRequest#isForMainFrame\(\)). To disable, use the value `0`. **Minimum:** 5 **Default:** 0