Returning null from onCreateInputConnection() prevented the Chromium renderer from relaying hardware key events into HTML inputs, breaking scanner input on the Urovo CT58C. Return the real InputConnection from super and rely on the multi-layer keyboard suppression (JS inputmode, InputMethodManager, EditorInfo flags, manifest flags) which is already proven to work on this device. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
84 lines
3.4 KiB
Markdown
84 lines
3.4 KiB
Markdown
# JoykooScanner — Android Barcode Scanner Kiosk App
|
|
|
|
## What This Is
|
|
|
|
Native Android app (Kotlin) that wraps `https://smart.joykoo.mx/` in a fullscreen WebView for dedicated Chinese industrial handheld barcode scanners. The scanner operates in HID/keyboard-wedge mode — it sends Android key events like a physical keyboard.
|
|
|
|
## Critical Design Decision
|
|
|
|
The Android soft keyboard must NEVER appear. Keyboard suppression uses multiple layers — do not remove any of them:
|
|
|
|
1. `NoSoftKeyboardWebView.onCheckIsTextEditor()` → `false`
|
|
2. `EditorInfo` flags `IME_FLAG_NO_EXTRACT_UI | IME_FLAG_NO_FULLSCREEN` in `onCreateInputConnection()`
|
|
3. `InputMethodManager.hideSoftInputFromWindow()` posted after each InputConnection request and on page load / window focus
|
|
4. JavaScript injection setting `inputmode="none"` on all `<input>`, `<textarea>`, and `contenteditable` elements via `MutationObserver`
|
|
5. Manifest `windowSoftInputMode="stateAlwaysHidden|adjustNothing"`
|
|
|
|
The real `InputConnection` from `super.onCreateInputConnection()` **must be returned** — returning `null` breaks hardware key input from the barcode scanner on devices like the Urovo CT58C.
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
app/src/main/java/mx/joykoo/scanner/
|
|
AppConfig.kt — URL, allowed hosts, gesture thresholds (single config point)
|
|
MainActivity.kt — Fullscreen kiosk activity, WebView setup, navigation, lifecycle
|
|
NoSoftKeyboardWebView.kt — IME suppression via null InputConnection
|
|
ScannerIntegration.kt — Interface stub for future vendor scanner SDK
|
|
```
|
|
|
|
## Build
|
|
|
|
- **Language**: Kotlin, targeting JVM 1.8 bytecode
|
|
- **SDK**: compileSdk 34, minSdk 24, targetSdk 34
|
|
- **Dependencies**: androidx core-ktx, appcompat, webkit, swiperefreshlayout
|
|
- **Gradle**: 8.7 with Kotlin DSL, AGP 8.5.2, Kotlin 1.9.24
|
|
- **Package**: `mx.joykoo.scanner`
|
|
|
|
### Build prerequisites (not yet installed on this server)
|
|
|
|
1. `sudo dnf install java-17-openjdk-devel` — only the JRE is installed, need javac
|
|
2. Android SDK cmdline-tools — download to `~/Android/Sdk/`, then install:
|
|
- `platform-tools`
|
|
- `platforms;android-34`
|
|
- `build-tools;34.0.0`
|
|
3. Set env vars:
|
|
```
|
|
JAVA_HOME=/usr/lib/jvm/java-17-openjdk-17.0.20.1.1-1.2.el9.x86_64
|
|
ANDROID_HOME=~/Android/Sdk
|
|
```
|
|
4. `./gradlew assembleDebug`
|
|
|
|
### Server environment (RHEL 9.8)
|
|
|
|
- JRE 17 installed at `/usr/lib/jvm/java-17-openjdk-17.0.20.1.1-1.2.el9.x86_64`
|
|
- 323 GB free on /home, 5.5 GB free on /
|
|
- curl, wget, unzip, zip available
|
|
- No Android SDK present anywhere
|
|
|
|
## Configuration
|
|
|
|
All configurable values are in `AppConfig.kt`:
|
|
- `HOME_URL` — the webpage to load
|
|
- `ALLOWED_HOSTS` — domains that stay inside the WebView
|
|
- `BACK_PRESS_EXIT_COUNT` / `BACK_PRESS_WINDOW_MS` — back-button exit guard
|
|
- `ADMIN_TAP_COUNT` / `ADMIN_TAP_WINDOW_MS` — hidden admin exit gesture (7 taps top-left corner)
|
|
|
|
## Navigation Rules
|
|
|
|
- URLs on `joykoo.mx` or `smart.joykoo.mx` (and subdomains) load inside the WebView
|
|
- All other URLs are silently blocked
|
|
- Back button goes back in WebView history; 3 rapid presses exits when no history
|
|
- Admin exit: 7 rapid taps in top-left 60dp corner → confirmation dialog (PIN-ready stub)
|
|
|
|
## Security
|
|
|
|
- HTTPS only, no cleartext, no SSL error bypass
|
|
- No JavaScript interfaces exposed
|
|
- No file:// or content:// access
|
|
- Network security config enforces system trust anchors only
|
|
- Domain allowlist in WebViewClient
|
|
|
|
## UI Strings
|
|
|
|
Spanish (`es`) — this is for a Mexico-based company.
|