feat: leanback webview kiosk activity
This commit is contained in:
@@ -1,3 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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>
|
||||
|
||||
@@ -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