feat: leanback webview kiosk activity
This commit is contained in:
@@ -1,3 +1,33 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
|
<!-- TV-only app: leanback required, touchscreen not -->
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.software.leanback"
|
||||||
|
android:required="true" />
|
||||||
|
<uses-feature
|
||||||
|
android:name="android.hardware.touchscreen"
|
||||||
|
android:required="false" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:allowBackup="false"
|
||||||
|
android:banner="@drawable/banner"
|
||||||
|
android:icon="@drawable/icon"
|
||||||
|
android:label="Grafana Kiosk"
|
||||||
|
android:usesCleartextTraffic="true"
|
||||||
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:screenOrientation="landscape"
|
||||||
|
android:configChanges="keyboard|keyboardHidden|navigation|screenSize|density">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 162 B |
Binary file not shown.
|
After Width: | Height: | Size: 157 B |
Reference in New Issue
Block a user