Compare commits

...

2 Commits

6 changed files with 96 additions and 0 deletions
+3
View File
@@ -15,6 +15,9 @@ android {
buildTypes { release { isMinifyEnabled = false } }
compileOptions { sourceCompatibility = JavaVersion.VERSION_17; targetCompatibility = JavaVersion.VERSION_17 }
kotlinOptions { jvmTarget = "17" }
// 本地单元测试中 android.* 桩方法返回默认值(避免 Log.d 抛 "not mocked"
// android.* stub methods return default values in local unit tests (avoid Log.d "not mocked")
testOptions { unitTests { isReturnDefaultValues = true } }
}
dependencies {
implementation("androidx.core:core-ktx:1.13.1")
@@ -1,10 +1,13 @@
package top.yeij.hearth
import android.app.Activity
import android.content.res.Configuration
import android.os.Bundle
import android.util.Log
import android.view.WindowInsets
import android.view.WindowInsetsController
import top.yeij.hearth.webview.JsBridge
import top.yeij.hearth.webview.WebViewManager
// HOME 桌面 activity,后续 Task 挂载 WebView 与 JsBridge
// HOME launcher activity; later tasks mount WebView and JsBridge
@@ -18,6 +21,28 @@ class MainActivity : Activity() {
super.onCreate(savedInstanceState)
Log.d(TAG, "onCreate: enter immersive mode")
enterImmersive()
setupWebView()
}
// 创建 JsBridge 并挂载 WebView 桌面层
// Create JsBridge and mount the WebView launcher layer
private fun setupWebView() {
val dm = resources.displayMetrics
val darkMode =
(resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) ==
Configuration.UI_MODE_NIGHT_YES
val bridge = JsBridge(
deviceWidthPx = dm.widthPixels,
deviceHeightPx = dm.heightPixels,
density = dm.density,
darkMode = darkMode,
)
WebViewManager(this).attach(bridge)
Log.d(
TAG,
"setupWebView: attached WebView ${dm.widthPixels}x${dm.heightPixels}" +
" density=${dm.density} darkMode=$darkMode"
)
}
// 进入沉浸式全屏:隐藏状态栏与导航栏,滑动可临时唤出
@@ -0,0 +1,25 @@
package top.yeij.hearth.webview
import android.util.Log
class JsBridge(
private val deviceWidthPx: Int,
private val deviceHeightPx: Int,
private val density: Float,
private val darkMode: Boolean,
) {
private val gson = com.google.gson.Gson()
@android.webkit.JavascriptInterface
fun getDeviceInfo(): String {
Log.d("HearthBridge", "getDeviceInfo called")
return gson.toJson(
mapOf(
"widthPx" to deviceWidthPx,
"heightPx" to deviceHeightPx,
"density" to density,
"darkMode" to darkMode
)
)
}
}
@@ -0,0 +1,26 @@
package top.yeij.hearth.webview
import android.annotation.SuppressLint
import android.app.Activity
import android.webkit.WebView
import android.webkit.WebSettings
import android.webkit.WebViewClient
class WebViewManager(private val activity: Activity) {
@SuppressLint("SetJavaScriptEnabled")
fun attach(bridge: JsBridge): WebView {
val webView = WebView(activity)
webView.settings.apply {
javaScriptEnabled = true
useWideViewPort = true
loadWithOverviewMode = true
setSupportZoom(false)
domStorageEnabled = true
}
webView.addJavascriptInterface(bridge, "HearthBridge")
webView.webViewClient = WebViewClient()
webView.loadUrl("file:///android_asset/h5/index.html")
activity.setContentView(webView)
return webView
}
}
@@ -0,0 +1,14 @@
package top.yeij.hearth.webview
import org.junit.Assert.assertTrue
import org.junit.Test
class JsBridgeTest {
@Test
fun getDeviceInfo_returnsJsonWithDarkMode() {
val bridge = JsBridge(deviceWidthPx = 800, deviceHeightPx = 480, density = 2.0f, darkMode = true)
val json = bridge.getDeviceInfo()
assertTrue(json.contains("\"widthPx\":800"))
assertTrue(json.contains("\"darkMode\":true"))
}
}
+3
View File
@@ -1,3 +1,6 @@
org.gradle.jvmargs=-Xmx2048m
android.useAndroidX=true
android.aapt2FromMavenOverride=/home/Aska/Android/Sdk/build-tools/34.0.0/aapt2
# 禁用 AGP 自动下载 SDK 组件(本机无法访问 dl.google.com,避免配置阶段卡死)
# Disable AGP auto-download of SDK components (dl.google.com unreachable, avoid hang during config)
android.builder.sdkDownload=false