Compare commits

...

3 Commits

Author SHA1 Message Date
f17a7fcaa2 WebViewAssetLoader 2025-04-09 14:25:05 -04:00
5713b6572e upgrade AGP and Gradlee 2025-04-09 13:00:34 -04:00
4381016e57 remove unused tests 2025-04-08 14:37:44 -04:00
10 changed files with 97 additions and 40 deletions

26
.idea/appInsightsSettings.xml generated Normal file
View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AppInsightsSettings">
<option name="tabSettings">
<map>
<entry key="Firebase Crashlytics">
<value>
<InsightsFilterSettings>
<option name="connection">
<ConnectionSetting>
<option name="appId" value="PLACEHOLDER" />
<option name="mobileSdkAppId" value="" />
<option name="projectId" value="" />
<option name="projectNumber" value="" />
</ConnectionSetting>
</option>
<option name="signal" value="SIGNAL_UNSPECIFIED" />
<option name="timeIntervalDays" value="THIRTY_DAYS" />
<option name="visibilityType" value="ALL" />
</InsightsFilterSettings>
</value>
</entry>
</map>
</option>
</component>
</project>

View File

@@ -4,10 +4,10 @@
<selectionStates>
<SelectionState runConfigName="app">
<option name="selectionMode" value="DROPDOWN" />
<DropdownSelection timestamp="2025-04-03T16:08:16.340902800Z">
<DropdownSelection timestamp="2025-04-09T17:43:14.816533500Z">
<Target type="DEFAULT_BOOT">
<handle>
<DeviceId pluginId="Default" identifier="serial=192.168.11.180:37459;connection=024bbef4" />
<DeviceId pluginId="Default" identifier="serial=192.168.11.180:43825;connection=7831d20c" />
</handle>
</Target>
</DropdownSelection>

1
.idea/misc.xml generated
View File

@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">

View File

@@ -46,6 +46,7 @@ dependencies {
implementation(libs.androidx.activity.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.ui)
implementation(libs.androidx.webkit)
implementation(libs.androidx.ui.graphics)
implementation(libs.androidx.ui.tooling.preview)
implementation(libs.androidx.material3)

View File

@@ -1,24 +0,0 @@
package com.zefie.zkiosk
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.zefie.zkiosk", appContext.packageName)
}
}

View File

@@ -111,6 +111,28 @@
}
.calendar-day.today {
background-color: #8d2b68; /* Highlight color */
}
#gotify-container {
position: relative;
top: -550px;
left: 1415px;
width: 500px;
height: 300px;
border: 1px solid #ccc;
overflow-y: auto;
padding: 10px;
color: #eee;
font-family: Arial, sans-serif;
border: 1px solid;
}
/* Style each notification block */
.notification {
border-bottom: 1px solid #eee;
padding: 5px 0;
margin-bottom: 5px;
}
.notification:last-child {
border-bottom: none;
}
</style>

View File

@@ -1,22 +1,26 @@
package com.zefie.zkiosk
import android.annotation.SuppressLint
import android.os.Bundle
import android.graphics.Rect
import android.net.Uri
import android.os.Bundle
import android.os.PowerManager
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.floatingactionbutton.FloatingActionButton
import org.videolan.libvlc.util.VLCVideoLayout
import android.os.Build
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
import androidx.webkit.WebViewAssetLoader
import android.widget.PopupWindow
import android.widget.RelativeLayout
import android.widget.SeekBar
import android.widget.TextView
import com.google.android.material.floatingactionbutton.FloatingActionButton
import org.videolan.libvlc.util.VLCVideoLayout
import java.util.Locale
@@ -51,8 +55,8 @@ class MainActivity : AppCompatActivity() {
videoLayout1 = findViewById(R.id.videoLayout1)
videoLayout2 = findViewById(R.id.videoLayout2)
restartButton = findViewById(R.id.restartButton)
vlcPlayer1 = VLCPlayer(this, videoLayout1)
vlcPlayer2 = VLCPlayer(this, videoLayout2)
vlcPlayer1 = VLCPlayer(this, videoLayout1, 1)
vlcPlayer2 = VLCPlayer(this, videoLayout2, 2)
val seekBar = findViewById<SeekBar>(R.id.durationSlider)
setupSliderPopup(seekBar)
@@ -75,8 +79,31 @@ class MainActivity : AppCompatActivity() {
clockWebView.settings.displayZoomControls = false
clockWebView.settings.javaScriptEnabled = true
wxWebView.loadUrl("file:///android_asset/radar.html")
clockWebView.loadUrl("file:///android_asset/clock.html")
val assetLoader = WebViewAssetLoader.Builder()
.addPathHandler("/assets/", WebViewAssetLoader.AssetsPathHandler(this))
.addPathHandler("/res/", WebViewAssetLoader.ResourcesPathHandler(this))
.build()
wxWebView.webViewClient = object : WebViewClient() {
override fun shouldInterceptRequest(
view: WebView,
request: WebResourceRequest
): WebResourceResponse? {
return assetLoader.shouldInterceptRequest(request.url)
}
}
clockWebView.webViewClient = object : WebViewClient() {
override fun shouldInterceptRequest(
view: WebView,
request: WebResourceRequest
): WebResourceResponse? {
return assetLoader.shouldInterceptRequest(request.url)
}
}
wxWebView.loadUrl("https://appassets.androidplatform.net/assets/radar.html")
clockWebView.loadUrl("https://appassets.androidplatform.net/assets/clock.html")
startPlayer(1)
startPlayer(2)

View File

@@ -4,12 +4,13 @@ import android.content.Context
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.widget.Toast
import org.videolan.libvlc.LibVLC
import org.videolan.libvlc.Media
import org.videolan.libvlc.MediaPlayer
import org.videolan.libvlc.util.VLCVideoLayout
class VLCPlayer(context: Context, private val videoLayout: VLCVideoLayout) {
class VLCPlayer(private val context: Context, private val videoLayout: VLCVideoLayout, private val streamId: Int) {
private val libVLC: LibVLC = LibVLC(context, arrayListOf("--rtsp-tcp",
"--quiet",
"--no-drop-late-frames",
@@ -37,7 +38,7 @@ class VLCPlayer(context: Context, private val videoLayout: VLCVideoLayout) {
streamUrl = url
val media = Media(libVLC, Uri.parse(url))
media.setHWDecoderEnabled(true, false)
media.addOption(":network-caching=250") // Adjust caching to handle jitter
media.addOption(":network-caching=500") // Adjust caching to handle jitter
mediaPlayer.media = media
media.release()
mediaPlayer.play()
@@ -65,6 +66,9 @@ class VLCPlayer(context: Context, private val videoLayout: VLCVideoLayout) {
if (stalled) {
val freezeDuration = now - lastProgressCheck
if (freezeDuration > 8000) {
handler.post {
Toast.makeText(context, "Watchdog triggered: Stream ${streamId} stalled, restarting...", Toast.LENGTH_SHORT).show()
}
restartStream()
return
}

View File

@@ -1,5 +1,5 @@
[versions]
agp = "8.8.2"
agp = "8.9.1"
appcompat = "1.7.0"
kotlin = "2.0.0"
coreKtx = "1.15.0"
@@ -11,10 +11,12 @@ lifecycleRuntimeKtx = "2.8.7"
activityCompose = "1.10.1"
composeBom = "2025.03.01"
material = "1.12.0"
webkit = "1.13.0"
[libraries]
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-webkit = { module = "androidx.webkit:webkit", version.ref = "webkit" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }

View File

@@ -1,6 +1,6 @@
#Sun Mar 02 16:14:47 EST 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists