feat: webview manager and js bridge skeleton
This commit is contained in:
@@ -15,6 +15,9 @@ android {
|
|||||||
buildTypes { release { isMinifyEnabled = false } }
|
buildTypes { release { isMinifyEnabled = false } }
|
||||||
compileOptions { sourceCompatibility = JavaVersion.VERSION_17; targetCompatibility = JavaVersion.VERSION_17 }
|
compileOptions { sourceCompatibility = JavaVersion.VERSION_17; targetCompatibility = JavaVersion.VERSION_17 }
|
||||||
kotlinOptions { jvmTarget = "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 {
|
dependencies {
|
||||||
implementation("androidx.core:core-ktx:1.13.1")
|
implementation("androidx.core:core-ktx:1.13.1")
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
package top.yeij.hearth
|
package top.yeij.hearth
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import android.content.res.Configuration
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.WindowInsets
|
import android.view.WindowInsets
|
||||||
import android.view.WindowInsetsController
|
import android.view.WindowInsetsController
|
||||||
|
import top.yeij.hearth.webview.JsBridge
|
||||||
|
import top.yeij.hearth.webview.WebViewManager
|
||||||
|
|
||||||
// HOME 桌面 activity,后续 Task 挂载 WebView 与 JsBridge
|
// HOME 桌面 activity,后续 Task 挂载 WebView 与 JsBridge
|
||||||
// HOME launcher activity; later tasks mount WebView and JsBridge
|
// HOME launcher activity; later tasks mount WebView and JsBridge
|
||||||
@@ -18,6 +21,28 @@ class MainActivity : Activity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
Log.d(TAG, "onCreate: enter immersive mode")
|
Log.d(TAG, "onCreate: enter immersive mode")
|
||||||
enterImmersive()
|
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"))
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user