github RushB-fr/freekiosk v1.2.19-beta.1
FreeKiosk v1.2.19 - Screensaver, Auth & Runtime Switching

pre-release5 hours ago

Added

  • πŸŒ™ Customizable screensaver content (#47, #91, #61): The screensaver is no longer just a brightness dimmer. A new "Screensaver Style" selector in Settings β†’ Display β†’ Screensaver offers three modes: Dim Only (default, unchanged β€” just dims the brightness), Web Page (displays a read-only URL fullscreen β€” clock, dashboard, HTML; tap anywhere to wake), and Video / Image (plays a video/image playlist via the existing MediaPlayerComponent with loop, mute, fit modes). In URL and Video modes the current brightness is preserved (auto-brightness keeps working), so the screen stays visible and Android no longer turns it off β€” addressing wall-mounted panel use cases. Existing users are unaffected: defaults remain Dim Only. A warning is shown in settings if Screensaver Brightness is below 10% while URL/Video is selected.

  • πŸ” HTTP Basic Auth for WebView (#113): FreeKiosk now automatically responds to HTTP 401 authentication challenges using credentials configured in Settings β†’ General β†’ Website Authentication. Enter a username and password; the password is stored in the Android Keychain (never in plain text). Leave the username empty to disable. Implemented via the basicAuthCredential prop of react-native-webview, which hooks into WebViewClient.onReceivedHttpAuthRequest natively β€” no JavaScript injection required and no impact on sites that don't use Basic Auth.

  • πŸ”€ Switch display mode via REST/MQTT (setMode) (#76): A new setMode command allows switching between WebView mode and External App mode at runtime without restarting FreeKiosk. Send {"mode":"webview","url":"https://..."} to switch to WebView (the url field is optional), or {"mode":"external_app","package":"com.app.name"} to launch an app and activate the return overlay. Available via REST (POST /api/mode) and MQTT (set/mode). The transition is clean in both directions: switching to WebView stops the OverlayService and background monitor; switching to External App reads fresh overlay settings from storage to avoid stale closures, verifies the app is installed, starts the OverlayService, then launches the app.

  • 🎯 Motion detection sensitivity setting (#125): A new "Sensitivity" radio group (Low / Medium / High) is now visible in Settings β†’ Display β†’ Screensaver β†’ Motion Detection when motion detection is enabled. Previously the sensitivity was hardcoded to Medium. Low sensitivity requires larger movements to trigger (15% pixel change threshold), Medium is the default (8%), and High reacts to subtle movements (4%). The selected value is persisted and applied immediately to the camera-based motion detector.

  • 🏠 FreeKiosk can be set as the default home launcher (#127): MainActivity now declares the HOME / DEFAULT intent categories alongside LAUNCHER. This makes FreeKiosk appear in the Android "Choose home app" picker and allows adb shell cmd package set-home-activity "com.freekiosk/.MainActivity" to succeed. Previously the command failed because no HOME intent-filter was declared on the main activity. This is optional β€” FreeKiosk only becomes the default launcher if the user (or ADB) explicitly selects it.

  • πŸ” Keep Alive / Launch on Boot in Website mode (#37): Background apps (managed apps with "Keep Alive" or "Launch on Boot" enabled) can now be configured and monitored in Website (WebView) mode, not just App mode. A new "Background Apps" section appears in Settings β†’ General when in Website mode. Use case: keep a music or audio receiver app (e.g. Spotify, Sendspin) alive in the background while displaying a web dashboard. The BackgroundAppMonitorService now runs independently of the display mode and stops itself automatically if no keep-alive apps are configured.

  • πŸ—£οΈ Web Speech API (speechSynthesis) polyfill (#NEW): Web apps running inside the WebView can now use the standard window.speechSynthesis.speak() API for text-to-speech. Android WebView does not natively implement the Web Speech API (unlike Chrome), so FreeKiosk injects a transparent polyfill that bridges speechSynthesis.speak() β†’ postMessage β†’ native Android TextToSpeech engine. This means any web app that uses TTS (e.g. accessibility tools, notification readers, custom kiosk UIs) will work out of the box without code changes. Supports speak(), cancel(), getVoices(), onvoiceschanged, SpeechSynthesisUtterance (text, lang, rate, pitch, volume), and automatic language detection via the existing FreeKiosk TTS engine. The polyfill only activates when the native speechSynthesis is missing or non-functional (no voices). Also exposed HttpServerModule.speak() and HttpServerModule.stopSpeaking() as React Native bridge methods for direct native TTS access from JS. Requested by Carlos via email

  • πŸ–¨οΈ Configurable print paper size (#NEW): A new "Default Paper Size" selector appears in Settings β†’ General β†’ Printing when printing is enabled. Available sizes: A4, A5, A3, Letter, Legal. The selected size is used as the default in the Android print dialog β€” the user can still override it manually if needed. Previously the print dialog always defaulted to A4 regardless of CSS @page rules. Reported by Paolo Leone via email

Fixed

  • ⏳ WebView stuck on infinite loading spinner for sites with redirect chains (#140): On sites that respond with HTTP redirects (e.g. a homepage redirecting to a login page), onLoadStart fired once per redirect step and each call cleared and restarted the 10-second fallback timeout. If the site produced a rapid series of navigations (redirect chain, iframe loads, SPA internal routing), the countdown was continuously reset and never completed β€” leaving the loading overlay permanently on screen and hiding the actual page. Fixed by starting the fallback timer only once per loading session: if a timeout is already running, subsequent onLoadStart events leave it untouched. onLoadEnd and onLoadProgress === 1 still cancel the timer normally when the page loads successfully. Reported by @SamuelSilvaG

  • πŸ“Ά SSID showing "Wifi" instead of network name on Android 12+ devices (#80): On Android 12+ (API 31+), WifiManager.connectionInfo is deprecated and returns <unknown ssid> even when the location permission is granted and location services are enabled. Fixed by using NetworkCapabilities.transportInfo (the recommended API since Android 10) to retrieve the WifiInfo object on API 31+. Affects the REST API /api/info, MQTT status messages, and all system info endpoints. Reported by @hapishyguy

  • πŸ”’ Lock Mode permanently disabled after using "Exit Kiosk Mode" (#124, #138): Calling "Exit Kiosk Mode" from the Advanced settings was writing @kiosk_enabled=false to AsyncStorage, which permanently disabled Lock Mode β€” on every subsequent launch, the kiosk started unlocked and users could escape via the home button. Root cause: the setKioskEnabledInAsyncStorage(false) call was added as belt-and-suspenders for the watchdog fix (#96), but the watchdog is already stopped explicitly via stopService() before the activity finishes, making the write unnecessary. Fixed by removing the AsyncStorage write from exitKioskMode() β€” @kiosk_enabled now stays true, so kiosk mode re-engages on the next FK launch. The DE fast-boot flag is still cleared (so BootLockActivity does not hard-lock on next reboot), and the watchdog is still stopped explicitly (#96 fix unaffected). Reported by @mpreusse and @Mkdir1511

  • πŸ—£οΈ TTS silent for Chinese and other non-Latin languages even when language data is installed (#115): Root cause was that TextToSpeech() was initialized without specifying an engine β€” Android may pick a default English-only engine rather than the engine the user configured in system settings (which has Chinese/Japanese/Korean support). Fixed by initializing TTS with Settings.Secure.getString("tts_default_engine") so FreeKiosk uses the same engine as the system TTS test page. Also improved parseLocale() to use Locale.forLanguageTag() (proper BCP 47 parsing) instead of manual string splitting, fixing edge cases with tags like zh-CN or zh_CN. Also applied the same engine fix and added language auto-detection to MQTT's speakText() which previously spoke all text without ever calling setLanguage(). Reported by @nowpast

  • πŸ”Š Volume Button Alternative toggle not accessible in App mode (#110): The "Volume Button Alternative" toggle (Settings β†’ Security β†’ Return to Settings) was hidden when display mode was set to App. It is now visible in all modes. The toggle description in App mode now clarifies that the feature is active by default and may cause accidental PIN triggers during normal volume adjustment β€” users who do not need it in App mode can disable it here. Reported by @Mkdir1511

  • πŸ”’ Kiosk not locked during Android boot on low-end / slow devices (#98): After reboot, there was a window of 15–60 seconds where the device was unprotected while React Native loaded. This was partially fixed in v1.2.17 by BootLockActivity (a pure-native activity that enters lock-task in under a second), but the fix was incomplete: ACTION_LOCKED_BOOT_COMPLETED fires before Android decrypts CE (user-encrypted) storage, so the SQLite/AsyncStorage reads used to check kiosk settings all returned their safe default (false), preventing BootLockActivity from launching at all. Fixed by using DE (Device Encrypted) SharedPreferences β€” readable at any point during the boot process β€” to persist whether the fast-boot lock should activate. The DE flag is written: (a) whenever startLockTask / exitKioskMode is called from the app, and (b) at every normal ACTION_BOOT_COMPLETED so it stays in sync. At ACTION_LOCKED_BOOT_COMPLETED, only the DE flag is read (no SQLite). Additionally, if BootLockActivity was launched at LOCKED_BOOT_COMPLETED but MainActivity (which is not Direct Boot–aware) couldn't start yet, the activity now retries launching MainActivity every 5 seconds in its poll loop until CE storage becomes available. Reported by @rarcher

  • πŸ” Launch on Boot causes infinite loop in External App mode (#37): Enabling "Launch on Boot" on a managed app (e.g. Velocity) while in External App mode caused the device to enter an unrecoverable loop β€” the screen cycled continuously between FreeKiosk and the external app until FreeKiosk was uninstalled. Three root causes fixed: (1) launchBootApps() was called on every loadSettings() invocation (including returns from Settings or PIN screen), not only on genuine app startup β€” a bootAppsLaunchedRef guard now ensures it fires at most once per app session; (2) AppLauncherModule.launchBootApps() called bringFreeKioskToFront() after launching the boot app, which triggered MainActivity.onResume() fast-path while loadSettings was still running β€” this caused a second native relaunch of the external app and a double-start of OverlayService, creating an unstable monitoring loop; (3) OverlayService is now started with the primary app's package before launchBootApps() is called (single-app mode only), so kiosk protection is active from the moment the boot app appears in the foreground β€” no unprotected window. As a bonus, BootReceiver.launchMainActivityLegacy() no longer calls Thread.sleep() on the main looper (replaced by a nested postDelayed), eliminating an ANR risk on Android 14+ devices. Reported by Tom Schiettecat (Hupac Intermodal)

  • πŸ“„ PDF Viewer fails to load PDFs from CDN/WAF-protected servers (#BUG): PDFs hosted behind CDN/WAFs like Alibaba Cloud (e.g. byd.com) failed to load in the built-in PDF.js viewer with "Unable to load PDF" error. Three root causes fixed: (1) Missing Referer header β€” the native PDF proxy now injects Referer: <pdf_url> when the WebView doesn't send one (which is always the case from file:// origins), preventing WAF anti-hotlink blocks; (2) Lost session cookies β€” Set-Cookie headers from proxied responses (e.g. Alibaba's acw_tc WAF cookie) are now persisted back into Android's CookieManager so subsequent requests include them; (3) Range request failures β€” PDF.js was making multiple range requests that lost WAF session state between requests, now uses disableRange: true for a single full-download request for maximum compatibility. Also improved viewer error messages to include the truncated URL for easier debugging. Reported by Martin Lemke via email

  • πŸ“„ PDF opened via popup (window.open) blocked by URL filtering: When a website opened a PDF link via window.open() (popup), the onOpenWindow handler checked URL filtering before checking for PDF interception β€” causing the PDF to be blocked in whitelist mode even with the PDF viewer enabled. PDF detection now runs first in onOpenWindow, consistent with onShouldStartLoadWithRequest. Reported by Martin Lemke via email

  • πŸŽ₯ Back button overlay disappears behind camera apps in fullscreen (#121): In External App / Multi-App mode, FreeKiosk's return overlay (back button and 5-tap exit zone) disappeared when camera apps (Google Camera, Open Camera) entered their fullscreen viewfinder mode. Root cause: camera apps use a hardware-accelerated SurfaceView whose compositor layer can render above TYPE_APPLICATION_OVERLAY windows after certain window state transitions. Fix: OverlayService now runs a periodic re-pin loop (every 3 s) while an external app is locked β€” it removes and immediately re-adds the overlay to WindowManager, placing it back at the top of the overlay stack. Also added FLAG_HARDWARE_ACCELERATED to overlay window params for correct compositing. Note: camera apps that call SurfaceView.setZOrderOnTop(true) permanently may still briefly occlude the overlay between re-pin cycles; the volume-button 5-tap exit (Settings β†’ Security) remains available as an always-reachable alternative. Reported by @jmynes

  • ⌨️ Soft keyboard persists after screen sleep (#135): When a kiosk page had an input focused (e.g. Force Numeric mode on a login screen) and the device timed out, the soft keyboard remained visible on the next screen-on instead of being dismissed with the sleep event. Fixed by calling InputMethodManager.hideSoftInputFromWindow() (+ clearFocus()) in ScreenStateReceiver when ACTION_SCREEN_OFF is received. Reported by @asfreitas17

  • πŸ“± Display settings tab crashes on Android 8.x (StackOverflowError in Slider) (#86): Opening Settings β†’ Display on Android 8.x (API 26–27) triggered an immediate StackOverflowError and crashed the app. Root cause: on Android 8, AppCompatSeekBar.setMax() internally calls setProgressInternal() β†’ refreshProgress() β†’ onProgressRefresh() β†’ onProgressChanged() on the registered listener. The listener then called seekbar.setProgress() to clamp the value, which re-triggered onProgressChanged() recursively until the stack overflowed. An earlier fix attempt (v1.2.16-beta.1) added a JS-side local state wrapper in SettingsSlider to reduce parent re-renders during drag, but the crash happened at initialization time (when React Native applies minimumValue / maximumValue props via the native bridge) so the JS fix had no effect. Root fix: added a mIsSettingProgress re-entrancy guard directly in ReactSliderManager.onProgressChanged() via a patch-package patch on @react-native-community/slider@5.1.1 β€” the guard returns immediately if re-entered, breaking the recursive loop. Reported by @gauthier-th

Don't miss a new freekiosk release

NewReleases is sending notifications on new releases.