github RushB-fr/freekiosk v1.2.17-beta.1
FreeKiosk v1.2.17 - Boot Lock & Multi-App Mode

pre-release13 hours ago

Added

  • 🔒 Boot Lock Activity (#98): New lightweight native Android activity (BootLockActivity) that enters lock-task mode immediately after boot — before React Native loads

    • Eliminates the window where users could interact with the OS freely on low-spec devices (e.g. Nokia C210) where RN can take 1-2 minutes to initialize
    • Shows a minimal loading screen (app icon + spinner) and automatically hands off to MainActivity once React Native is ready
    • Only activates for Device Owner installs with kiosk mode enabled; non-DO installs use the existing delayed-launch path
  • 🛡️ Kiosk Watchdog Service (#96): New KioskWatchdogService foreground service using START_STICKY flag to survive OOM kills

    • On low-RAM devices (e.g. 2GB AndroidTV), automatically relaunches FreeKiosk within seconds if the kernel kills it due to memory pressure
    • Includes relaunch cooldown (15s) to prevent relaunch storms
    • Self-disables when kiosk mode is turned off; uses a silent minimal-priority notification
  • 🎬 Media Player Mode: Brand-new display mode alongside Website and External App

    • Play videos and images in full-screen kiosk mode with playlist support
    • Local file support: Pick videos and images directly from the device via Android's native file picker; files are copied to app internal storage for reliable WebView playback; local files show a 📱 badge and filename in the playlist
    • Native FilePickerModule: New Kotlin native module (FilePickerModule.kt) using ACTION_OPEN_DOCUMENT intent; includes deleteMediaFile, listMediaFiles, clearMediaFiles helpers
    • Remote URL support: Also accepts remote http:// and https:// URLs for hosted media content
    • Playlist management: Add multiple media URLs or pick local files from General settings, with auto-detection of media type based on file extension or MIME type
    • Video support: MP4, WebM, OGG formats with optional mute toggle
    • Image support: PNG, JPG, GIF, SVG, WebP with configurable per-item or default display duration (seconds)
    • Playback options: Auto-play, loop, shuffle, and optional on-screen controls (prev/play-pause/next with progress bar)
    • Display options: Fit mode (contain/cover/fill), background color, crossfade transitions with configurable duration
    • Full kiosk integration: Brightness control, screensaver, screen always on, status bar, lock mode, volume button return, and touch blocking all work identically to Website mode
    • WebView-based rendering: Uses an embedded HTML5 player with allowFileAccess, allowFileAccessFromFileURLs, and allowUniversalAccessFromFileURLs enabled for local file playback; dual-slot crossfade transitions
    • Error handling: Auto-skips unplayable items with retry; shows friendly empty state when no items configured
    • Settings persistence: All media player settings saved to AsyncStorage, included in backup/restore, and properly reset
    • Android 13+ permissions: Added READ_MEDIA_VIDEO and READ_MEDIA_IMAGES for granular media access
  • 📊 Dashboard Mode: New display mode that shows a configurable grid of URL tiles instead of a single WebView

    • Users can create tiles with custom names and URLs, each automatically assigned a distinct color
    • Tapping a tile opens its URL in the WebView with a navigation bar (back/forward/refresh/home)
    • Configurable in Settings → Dashboard tab
  • 📱 Multi-App Mode (#67): External App mode now supports managing multiple apps

    • Add apps from the new "Managed Apps" section in General settings — each app appears on a home screen grid with icon circles
    • All managed apps are automatically whitelisted in Lock Task Mode, so users can switch between them without escaping the kiosk
    • The primary app (single package) still works exactly as before for backward compatibility
  • 🚀 Launch App on Boot (#37): Managed apps with "Launch on Boot" enabled are automatically started in the background when the device boots, before FreeKiosk's own UI loads

    • Combined with "Keep Alive", apps can be maintained as persistent background services
  • 💓 Keep Alive Background Monitor (#37): New BackgroundAppMonitorService foreground service checks every 30 seconds (via UsageStatsManager) if managed apps with "Keep Alive" enabled are still running, and relaunches them if they've stopped or crashed

    • Starts automatically on boot when at least one keep-alive app is configured
  • Accessibility Whitelist for Other Apps (#66): Device Owners can now allow other apps' accessibility services via a per-app "Allow Accessibility" toggle in Managed Apps settings

    • Uses DevicePolicyManager.setPermittedAccessibilityServices() to whitelist selected packages alongside FreeKiosk's own service
    • Applied at boot, on save, and when enabling via Device Owner
  • ⚙️ Android Settings Button (#89): New "Android System Settings" section in the Advanced tab

    • Main button to open the native Android settings, plus quick-access shortcuts for WiFi, Sound, Display, Bluetooth, Date & Time, and Apps
    • Fully compatible with Lock Task Mode: automatically pauses the lock, opens the settings, and re-engages kiosk mode when the user returns to FreeKiosk
    • An info banner warns when kiosk mode is active
    • Useful for devices with no physical navigation buttons where ADB commands are restricted by Admin mode
  • 🔍 WebView Zoom Level (Display settings): New slider to control how web pages are rendered in WebView mode

    • Range: 50%–200%, default 100% (matches Chrome's default rendering)
    • Quick presets at 75%, 100%, 125%, 150%
    • An info hint appears when zoom is not at default; only available in WebView mode
    • Persisted to storage and included in backup/restore

Changed

  • 🏪 Play Store Compliance: Conditional Self-Update (#playstore): In-app self-update via GitHub is now completely disabled when building for the Play Store
    • A single Gradle flag (-Pplaystore) controls everything at compile time — no separate codebase needed
    • When active: REQUEST_INSTALL_PACKAGES permission removed, UpdateInstallReceiver disabled, entire "Updates" UI section hidden from Settings → Advanced, all native update methods become no-ops
    • R8 strips the dead update code from the final bytecode
    • Normal sideload/F-Droid builds (./gradlew assembleRelease) remain fully functional with self-update enabled
    • Play Store builds: ./gradlew bundleRelease -Pplaystore

Fixed

  • 🔌 MQTT Doesn't Connect When Password Is Set (#97): Fixed a crash in the password masking logic — String.repeat(password.length - 6) produced a negative count for passwords shorter than 7 characters, throwing IllegalArgumentException before the MQTT client was even built

    • This silently aborted connect(), resulting in zero network traffic and an immediate return to "Disconnected"
    • Also fixed authentication being skipped entirely when a password was configured without a username
  • 🔄 Inactivity Return Now Works in Dashboard Mode: Previously had no effect because the feature required a base URL (empty in dashboard mode)

    • Now correctly returns to the dashboard grid after the configured timeout
  • 🔄 URL Planner Return to Dashboard Grid: When a scheduled planner event ended while in Dashboard Mode, the app did not return to the dashboard grid due to a stale closure in the planner callback

    • Fixed by using a ref to track the active event
  • Accessibility Auto-Enable Fails with "Permission Denial: WRITE_SECURE_SETTINGS" (#99): The "Enable Automatically (Device Owner)" button crashed because Settings.Secure.putString() requires android.permission.WRITE_SECURE_SETTINGS, which is not automatically granted to Device Owners

    • Added the permission to the manifest, wrapped the secure settings write in a SecurityException catch with a specific WRITE_SECURE_SETTINGS_REQUIRED error code
    • Improved UI shows a clear dialog with the one-time ADB command: adb shell pm grant com.freekiosk android.permission.WRITE_SECURE_SETTINGS
    • BootReceiver also handles the missing permission gracefully instead of crashing silently
  • 🔒 PIN Bypass via Back Gesture (#93): Fixed a security issue where swiping back (Android predictive back gesture) from the Settings or PIN screen could bypass PIN protection on Android 16+ devices (e.g. Lenovo Idea Tab Pro)

    • Disabled swipe-back gestures on PIN and Settings screens
    • Added BackHandler to block hardware/gesture back navigation
    • Replaced navigation.navigate with navigation.reset to fully clear the navigation stack when returning to kiosk mode
  • 📦 Self-Update Fails with "No Storage Permission" (#88): The APK download used setDestinationInExternalPublicDir() which requires WRITE_EXTERNAL_STORAGE runtime permission — never requested at runtime

    • Switched to setDestinationInExternalFilesDir() (app-private directory), eliminating the storage permission requirement entirely
    • Old downloaded APKs are now cleaned up automatically before each new download
  • 📦 Self-Update Fails to Install on Android 8+ (#88): APK install was blocked because "Install from unknown sources" was not enabled for the app

    • Added a pre-download permission check (canRequestPackageInstalls()) with a user-friendly dialog that opens the system settings page to grant the permission
    • On restricted devices (e.g. Amazon Echo Show / Fire OS) where the settings page doesn't exist, a clear fallback message guides the user to use adb install -r <apk> instead
  • 🔧 Duplicate Import in HttpServerModule (#88): Removed duplicate android.location.LocationManager import that caused Kotlin compilation failure

  • 🎮 Remote Control Now Works Natively Like a Physical Keyboard (#85): Remote key commands (/api/remote/up, down, left, right, select, back, home, menu, playpause) were previously routed through a JavaScript round-trip via React Native bridge

    • Now handled entirely in native code — dispatched via the AccessibilityService (cross-app D-pad navigation with UI element highlighting) or activity.dispatchKeyEvent() (in-app fallback)
    • On /e/OS, LineageOS, and other custom ROMs, this enables proper focus-based UI navigation identical to a physical remote/keyboard
  • 📡 MQTT Now Supports Remote Control and Keyboard Commands (#85): Added 12 new MQTT command topics for full remote control parity with the REST API

    • remote_up, remote_down, remote_left, remote_right, remote_select, remote_back, remote_home, remote_menu, remote_playpause, keyboard_key, keyboard_combo, keyboard_text
    • Home Assistant Discovery registers 9 new button entities (remote D-pad) and 3 new text entities (keyboard input), bringing the total from 30 to 42 auto-discovered entities
  • 📡 MQTT Background Persistence (#80): MQTT now stays alive when the app is in background or the screen is off, with 4 layers of protection:

    • PARTIAL_WAKE_LOCK + WIFI_MODE_FULL_HIGH_PERF keep CPU and WiFi active for MQTT PING packets
    • NetworkCallback detects WiFi recovery and triggers immediate reconnect instead of waiting for TCP timeout + exponential backoff
    • OverlayService watchdog checks MQTT health every 60 seconds from the existing foreground service
    • SCREEN_ON receiver triggers an instant MQTT reconnect check when the screen wakes up
  • 🏷️ MQTT Device Name Prompt on Every Keystroke (#80): Changing the Device Name no longer triggers a reconnect popup on every key press

    • The reconnect prompt now only appears once when the field loses focus (onBlur)
  • 📶 WiFi connected Field Reporting True When Not on WiFi (#80): MQTT status and REST API used ipAddress != "0.0.0.0" to determine WiFi connection, which returned true for cellular, Ethernet, or USB tethering

    • Now uses ConnectivityManager.getNetworkCapabilities(TRANSPORT_WIFI) consistently across all 3 modules — only returns true when actually connected to WiFi
  • 📶 SSID Shows "WiFi" Instead of Actual Network Name (#80): When Android blocks SSID access, the app now shows a diagnostic message — "WiFi (no permission)" or "WiFi (location off)" — instead of silently showing "WiFi"

    • Also handles the 0x edge case on some Chinese tablets

Don't miss a new freekiosk release

NewReleases is sending notifications on new releases.