From 6ca64ea2ff72fe62c0d99b270f17e720edc9823a Mon Sep 17 00:00:00 2001 From: Arnie via Claude Date: Fri, 12 Jun 2026 13:21:16 +0200 Subject: [PATCH] feat: leanback webview kiosk activity --- app/src/main/AndroidManifest.xml | 30 ++++++ .../java/cz/c3c/webviewkiosk/MainActivity.kt | 87 ++++++++++++++++++ app/src/main/res/drawable/banner.png | Bin 0 -> 162 bytes app/src/main/res/drawable/icon.png | Bin 0 -> 157 bytes 4 files changed, 117 insertions(+) create mode 100644 app/src/main/java/cz/c3c/webviewkiosk/MainActivity.kt create mode 100644 app/src/main/res/drawable/banner.png create mode 100644 app/src/main/res/drawable/icon.png diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9a40236..4387fae 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,3 +1,33 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/cz/c3c/webviewkiosk/MainActivity.kt b/app/src/main/java/cz/c3c/webviewkiosk/MainActivity.kt new file mode 100644 index 0000000..f9a141f --- /dev/null +++ b/app/src/main/java/cz/c3c/webviewkiosk/MainActivity.kt @@ -0,0 +1,87 @@ +package cz.c3c.webviewkiosk + +import android.annotation.SuppressLint +import android.app.Activity +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.view.View +import android.view.WindowManager +import android.webkit.WebResourceError +import android.webkit.WebResourceRequest +import android.webkit.WebSettings +import android.webkit.WebView +import android.webkit.WebViewClient + +class MainActivity : Activity() { + + companion object { + const val DASHBOARD_URL = + "https://grafana.c3c.cz/public-dashboards/381fe3e71e164eb99dd0b10e246a36e2" + } + + private lateinit var webView: WebView + private val handler = Handler(Looper.getMainLooper()) + private val backoff = BackoffPolicy(initialDelayMs = 2_000, maxDelayMs = 60_000) + private var lastLoadFailed = false + + @SuppressLint("SetJavaScriptEnabled") + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + + webView = WebView(this) + webView.settings.apply { + javaScriptEnabled = true + domStorageEnabled = true + cacheMode = WebSettings.LOAD_DEFAULT + mediaPlaybackRequiresUserGesture = false + } + webView.webViewClient = object : WebViewClient() { + override fun onPageFinished(view: WebView, url: String) { + // onPageFinished also fires after a failed load (error page), + // so only treat a clean finish as recovery. + if (!lastLoadFailed) backoff.reset() + lastLoadFailed = false + } + + override fun onReceivedError( + view: WebView, + request: WebResourceRequest, + error: WebResourceError, + ) { + // Subresource failures (one panel's query, a font) must not + // tear down the whole page; only main-frame failures retry. + if (!request.isForMainFrame) return + lastLoadFailed = true + handler.postDelayed( + { view.loadUrl(DASHBOARD_URL) }, + backoff.nextDelayMs(), + ) + } + } + + setContentView(webView) + hideSystemUi() + webView.loadUrl(DASHBOARD_URL) + } + + override fun onResume() { + super.onResume() + hideSystemUi() + } + + private fun hideSystemUi() { + @Suppress("DEPRECATION") // WindowInsetsController needs API 30; minSdk is 26 + window.decorView.systemUiVisibility = + View.SYSTEM_UI_FLAG_FULLSCREEN or + View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or + View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY + } + + override fun onDestroy() { + handler.removeCallbacksAndMessages(null) + webView.destroy() + super.onDestroy() + } +} diff --git a/app/src/main/res/drawable/banner.png b/app/src/main/res/drawable/banner.png new file mode 100644 index 0000000000000000000000000000000000000000..166071910a1d3799f557bde718a6a8f6e1f60fd0 GIT binary patch literal 162 zcmeAS@N?(olHy`uVBq!ia0y~yU~~Yow=gmT$@^OAKmi7YWRD45bDP46hOx7_4S6Fo+k-*%fF5lwb?+32~KIG5G)g|77F1Z$J^oByV>Y#{W#Z z_kbKZPZ!6Kh{JCW8ZrWThZcPG&*kM`0Azwd9k0w421aq?nP)*fPgg&ebxsLQ0JPXB AX8-^I literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/icon.png b/app/src/main/res/drawable/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..079ba0091449b9cfc2f5cf202f8c75de0e9ca692 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^3qY8W8Axtq{F(=(6p}rHd>I(3)EF2VS{N990fib~ zFff!FFfhDIU|_JC!N4G1FlSew4N!tDz$e7@O9sRL|Non2{D=dJFeZ7syDFVdQ&MBb@0HwkyPXGV_ literal 0 HcmV?d00001