Fix Menu popup, DPAD room-list navigation, and cleartext leftover
- Menu key: WebView refuses to forward Android "system" keycodes (KEYCODE_MENU among them) to page JS, confirmed via diagnostic logging (downConsumed=false even though the key reaches dispatchKeyEvent). Relay it as KEYCODE_X instead - room.js on the website side treats 'x' as an alias for the ContextMenu trigger. - DPAD center/up/down/media keys are now only remapped inside a room (shouldIntercept() gates on isRoomList()) - the room-list page uses plain ArrowUp/ArrowDown/Enter and never moved focus when those keys arrived pre-remapped as Space/P/N. - Removed a leftover cleartextTrafficPermitted="true" left over from local LAN debugging against a docker instance. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LHgWjmEJXsJEi1EVAoTp4K
This commit is contained in:
@@ -18,11 +18,27 @@ import android.webkit.WebViewClient
|
||||
* den einmaligen Autoplay-Ton-Klick eine vertrauenswuerdige Nutzereingabe,
|
||||
* die ein simuliertes KeyboardEvent nicht liefert.
|
||||
*
|
||||
* KEYCODE_MENU wird bewusst NICHT abgefangen: das Oeffnen des TV-Menue-
|
||||
* Popups wurde bereits gegen die echte Website in einem normalen Browser
|
||||
* auf echter Fire-TV-Hardware bestaetigt, ohne dass diese App beteiligt
|
||||
* war - unveraendertes Durchreichen ist die naechste Annaeherung an genau
|
||||
* dieses schon erprobte Verhalten.
|
||||
* KEYCODE_MENU wird NICHT als KEYCODE_MENU ins WebView weitergereicht,
|
||||
* sondern als KEYCODE_X. Grund (per Diagnose-Log bestaetigt): Androids
|
||||
* WebView.dispatchKeyEvent() liefert "System"-Keycodes (KEYCODE_MENU,
|
||||
* HOME, BACK, CALL, VOLUME_*, ...) grundsaetzlich nicht an den Seiteninhalt
|
||||
* aus - sendKey(KEYCODE_MENU) kam zwar in dispatchKeyEvent() an, aber
|
||||
* webView.dispatchKeyEvent() meldete downConsumed=false/upConsumed=false
|
||||
* und JS bekam weder keydown- noch contextmenu-Events. Ein gewoehnlicher
|
||||
* Buchstaben-Keycode wie KEYCODE_P (fuer DPAD_UP) wird dagegen anstandslos
|
||||
* durchgereicht (downConsumed=true). Die Website (room.js) behandelt 'x'
|
||||
* deshalb als Alias fuer die 'ContextMenu'-Taste, ausschliesslich fuer
|
||||
* diesen App-Anwendungsfall.
|
||||
*
|
||||
* DPAD Center/Up/Down (und die entsprechenden Medientasten) werden NUR
|
||||
* innerhalb eines Raums remapped (Space/P/N - siehe Design-Spec). Auf der
|
||||
* Raumliste (/tv) haben sie dort keine Bedeutung: die Raumliste hat ihr
|
||||
* eigenes Tastaturschema (ArrowUp/ArrowDown/Enter, siehe tv-rooms.js auf
|
||||
* der Website) und muss die echten, unveraenderten Tasten bekommen, sonst
|
||||
* bewegt sich der Fokus zwischen den Raum-Kacheln nie (genau der Fehler,
|
||||
* der beim ersten Hardware-Test auftrat: die Raumliste laed, aber keine
|
||||
* Taste tut etwas, weil DPAD_DOWN/CENTER als 'n'/Space statt als
|
||||
* ArrowDown/Enter ankamen).
|
||||
*/
|
||||
class MainActivity : Activity() {
|
||||
|
||||
@@ -94,48 +110,37 @@ class MainActivity : Activity() {
|
||||
sendKey(keyCode, shift = true)
|
||||
}
|
||||
|
||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||
if (event.action != KeyEvent.ACTION_DOWN) {
|
||||
return when (event.keyCode) {
|
||||
/** Ob dispatchKeyEvent diese Taste ueberhaupt anfasst - fuer ACTION_DOWN
|
||||
* und ACTION_UP gleich ausgewertet, damit nie nur die eine Haelfte eines
|
||||
* Tastendrucks abgefangen wird (sonst haengt Chromiums interner
|
||||
* Tastenstatus fest, weil ein Keydown ohne passendes Keyup ankaeme). */
|
||||
private fun shouldIntercept(keyCode: Int): Boolean = when (keyCode) {
|
||||
KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT,
|
||||
KeyEvent.KEYCODE_MENU -> true
|
||||
KeyEvent.KEYCODE_DPAD_CENTER, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,
|
||||
KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT,
|
||||
KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN,
|
||||
KeyEvent.KEYCODE_MEDIA_PREVIOUS, KeyEvent.KEYCODE_MEDIA_NEXT,
|
||||
KeyEvent.KEYCODE_BACK -> true // ACTION_UP derselben Tasten verschlucken, wir haben schon auf ACTION_DOWN reagiert
|
||||
else -> super.dispatchKeyEvent(event)
|
||||
KeyEvent.KEYCODE_MEDIA_PREVIOUS, KeyEvent.KEYCODE_MEDIA_NEXT -> !isRoomList()
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
return when (event.keyCode) {
|
||||
KeyEvent.KEYCODE_DPAD_CENTER, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> {
|
||||
sendKey(KeyEvent.KEYCODE_SPACE)
|
||||
true
|
||||
}
|
||||
KeyEvent.KEYCODE_DPAD_LEFT -> {
|
||||
handleSeek(KeyEvent.KEYCODE_DPAD_LEFT, event.repeatCount > 0)
|
||||
true
|
||||
}
|
||||
KeyEvent.KEYCODE_DPAD_RIGHT -> {
|
||||
handleSeek(KeyEvent.KEYCODE_DPAD_RIGHT, event.repeatCount > 0)
|
||||
true
|
||||
}
|
||||
KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS -> {
|
||||
sendKey(KeyEvent.KEYCODE_P)
|
||||
true
|
||||
}
|
||||
KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT -> {
|
||||
sendKey(KeyEvent.KEYCODE_N)
|
||||
true
|
||||
}
|
||||
KeyEvent.KEYCODE_BACK -> {
|
||||
when {
|
||||
|
||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||
if (!shouldIntercept(event.keyCode)) return super.dispatchKeyEvent(event)
|
||||
if (event.action != KeyEvent.ACTION_DOWN) return true // ACTION_UP der abgefangenen Taste verschlucken, ACTION_DOWN hat schon reagiert
|
||||
|
||||
when (event.keyCode) {
|
||||
KeyEvent.KEYCODE_DPAD_CENTER, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> sendKey(KeyEvent.KEYCODE_SPACE)
|
||||
KeyEvent.KEYCODE_DPAD_LEFT -> handleSeek(KeyEvent.KEYCODE_DPAD_LEFT, event.repeatCount > 0)
|
||||
KeyEvent.KEYCODE_DPAD_RIGHT -> handleSeek(KeyEvent.KEYCODE_DPAD_RIGHT, event.repeatCount > 0)
|
||||
KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS -> sendKey(KeyEvent.KEYCODE_P)
|
||||
KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT -> sendKey(KeyEvent.KEYCODE_N)
|
||||
KeyEvent.KEYCODE_MENU -> sendKey(KeyEvent.KEYCODE_X)
|
||||
KeyEvent.KEYCODE_BACK -> when {
|
||||
isRoomList() -> { /* verschluckt, keine weitere Aktion */ }
|
||||
isFullscreen() -> sendKey(KeyEvent.KEYCODE_ESCAPE)
|
||||
else -> webView.loadUrl(BuildConfig.WEBSITE_URL)
|
||||
}
|
||||
true
|
||||
}
|
||||
else -> super.dispatchKeyEvent(event)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config>
|
||||
<base-config cleartextTrafficPermitted="false">
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
</trust-anchors>
|
||||
|
||||
Reference in New Issue
Block a user