github RushB-fr/freekiosk v1.2.18-beta.1
FreeKiosk v1.2.18-beta.1 - Printing Support & Multi-Fix

pre-release7 hours ago

Added

  • 🖨️ Allow Printing toggle (#NEW): New "Allow Printing" setting (off by default) in General → Printing that enables window.print() support in kiosk mode. When enabled: (1) the window.print() JavaScript call is intercepted and routed to Android's native PrintManager, (2) print spooler packages (com.android.printspooler + all installed print services like Samsung Print, HP Print, etc.) are dynamically discovered via queryIntentServices and automatically whitelisted in Lock Task mode so the system print dialog can appear, (3) immersive mode is suspended while the print dialog is open and re-applied after it closes, (4) onResume lock task re-entry is deferred during printing to avoid killing the print UI, and (5) data: URLs are allowed in the WebView to support popup-based print flows (label printers, receipt generators). Supports WiFi, Bluetooth, USB printers and Save as PDF. Requested by @Poppy
  • ☀️ Auto-Brightness Offset (#92): New slider in Display → Auto-Brightness settings that lets you add a fixed percentage offset to the calculated auto-brightness value. For example, setting +10% means if the light sensor calculates 30% brightness, FreeKiosk will apply 40% instead. Useful when auto-brightness is consistently too dim for your environment but you still want it to adapt to ambient light. The offset is clamped at 100% maximum. Available in the settings UI (0–50% range with 5% steps) and via the REST API (POST /api/autoBrightness/enable now accepts an optional offset parameter, 0–100). Requested by @Delivator

Fixed

  • TTS silent for non-English text (#115): /api/tts only spoke English and was completely silent for Chinese, Japanese, Korean and other non-Latin text because TextToSpeech.setLanguage() was never called — the engine defaulted to English. Added automatic language detection based on Unicode script analysis (CJK → Chinese, Hangul → Korean, Hiragana/Katakana → Japanese, Arabic, Thai, Hindi, Cyrillic, etc.). Also added an optional language parameter (BCP 47 tag, e.g. "zh-CN", "ja", "ko") for explicit control. The locale is now set before each speak() call. Requires the target language TTS voice data to be installed on the device. Reported by @nowpast
  • Some packages do not show up in app picker (#112): Packages without a launchable UI (services, VPN tools like gnirehtet, etc.) were excluded from the managed apps picker because getInstalledApps() filtered on getLaunchIntentForPackage() != null. Added a new native method getAllInstalledApps() that includes user-installed (non-system) packages even when they have no launcher activity. The managed apps picker now uses this method and offers a "Show all packages" toggle (off by default) to reveal background services/VPNs. Non-UI apps display a "service" badge for clarity. The single-app primary picker remains launcher-only since launching a non-UI package as the main app is not meaningful. Reported by @Royalflamejlh
  • ADB configuration doesn't support multi-app mode (#111): Added external_app_mode and managed_apps ADB intent extras to configure multi-app mode via ADB. You can now set --es external_app_mode "multi" and provide a JSON array of apps with --es managed_apps '[{"packageName":"com.app1"},{"packageName":"com.app2"}]'. Each app supports showOnHomeScreen, launchOnBoot, keepAlive, and allowAccessibility flags. Both individual intent extras and full JSON config (--es config '{...}') are supported. Uninstalled packages are silently skipped. Display names are auto-resolved from the system if not provided. Reported by @Royalflamejlh
  • Volume buttons trigger PIN request when held (#110): Holding the volume button to adjust volume would trigger the PIN request because both MainActivity.onKeyDown and VolumeChangeReceiver counted auto-repeat/rapid events as separate taps. Fixed by ignoring KeyEvent with repeatCount > 0 in MainActivity, and adding a minimum 250ms interval between counted volume changes in VolumeChangeReceiver to filter out the rapid events (~50-100ms) generated by holding the button. Deliberate separate presses (≥250ms apart) still work normally. Reported by @Mkdir1511
  • Crash on boot with Lock Mode enabled (#109): BootLockActivity crashed immediately on boot with a NullPointerException in hideSystemUI() because window.insetsController was called before setContentView(). On Android R+ (API 30+), this internally accesses the DecorView which is only created by setContentView() — so the DecorView was null. Fixed by reordering the calls so setContentView() runs first, and added a try-catch safety net in hideSystemUI() for extra robustness on devices with unusual boot timing. Only affected v1.2.17-beta.1; v1.2.16 was unaffected because it didn't have BootLockActivity. Reported by @sharkooon
  • Backup import from other devices / ADB push not working (#107): On Android 11+ (Scoped Storage), backup files pushed via adb push or copied from another device were invisible to the import list because RNFS.readDir() can only see files created by the app itself. Added a "Browse device for backup file..." button in the import modal that uses Android's Storage Access Framework (SAF) via ACTION_OPEN_DOCUMENT to open the native file picker — this bypasses Scoped Storage restrictions entirely. The JSON content is read directly through ContentResolver (no file copy needed). Also added importBackupFromContent() and parseBackupContent() to BackupService for content-based import/preview, and improved the empty-state message to guide users toward the browse button. Reported by @sharkooon
  • 📖 Device Owner setup incorrectly requires factory reset (#68): Updated all setup documentation (README, INSTALL.md, ADB_CONFIG.md, FAQ) to clarify that a factory reset is not required to activate Device Owner. Android's actual requirement is that no user accounts are active on the device — users can simply sign out of all accounts, run the dpm command, and sign back in. Factory reset is now documented as a fallback only. Also added notes about SIM profiles/accounts that some devices retain. Reported by @realAllonZ, confirmed by @hapishyguy
  • WebView blocked by hosting providers (SiteGround, etc.): The hardcoded User-Agent (Chrome/120.0.0.0 on X11; Linux x86_64) was outdated and had a platform mismatch — hosting WAFs flagged it as a bot. Updated the default UA to a modern Chrome 131 on Android (Mozilla/5.0 (Linux; Android 13; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Mobile Safari/537.36). Also added a new Custom User Agent setting in Display settings, allowing users to override the UA string if specific sites require it
  • Screen Sleep Schedule not saving in App mode (#103): The Screen Sleep Scheduler settings (enabled, rules, wake-on-touch) were only persisted when in Website or Media Player mode. In External App mode, the save function forcibly reset screenSchedulerEnabled to false and discarded all rules — even though the UI allowed configuring them in all modes. Moved scheduler save calls out of the mode-conditional block so they are now saved unconditionally, consistent with how they are loaded and executed. Reported by @hungrycactus
  • MQTT audio commands not working (#102): audio_play, audio_beep, and audio_stop MQTT commands were not functional while their REST API equivalents worked fine. The MQTT path forwarded audio commands to JS (ApiService.ts) which had no handler for them, whereas the REST API handled them natively in Kotlin (HttpServerModule). Added native audio handling (MediaPlayer, AudioTrack) directly in MqttModule.kt, matching the existing REST API implementation. Reported by @zeroping
  • MQTT still fails on older devices after #97 fix (#97): On older devices (Android 11 and below), R8 obfuscation of HiveMQ's internal classes (Dagger 2 IoC components, staged auth builder interfaces, lazy InstanceHolder factories) caused AbstractMethodError or IncompatibleClassChangeError on older ART runtimes when the auth code path was taken. Added comprehensive ProGuard keep rules for HiveMQ, Dagger, javax.inject, and RxJava. Hardened error handling with catch (Throwable) (instead of catch (Exception)) to properly catch Error subclasses from Netty/Dagger static initialization and propagate them to the UI
  • Kiosk Watchdog not stopping on exit (#96): Fixed KioskWatchdogService continuing to run (and relaunching the app) after intentionally exiting kiosk mode. The watchdog now writes @kiosk_enabled=false to AsyncStorage and explicitly stops the service before closing the activity. Also clears the watchdog notification on exit. Reported by @krheinwald

Don't miss a new freekiosk release

NewReleases is sending notifications on new releases.