Sfoglia il codice sorgente

添加网络监听功能

cc12458 1 mese fa
parent
commit
502fe29d79

+ 15 - 7
library/browser/src/main/java/com/hzliuzhi/applet/browser/ui/KioskScreen.kt

@@ -10,6 +10,7 @@ import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.zIndex
+import com.hzliuzhi.applet.browser.ui.components.NetworkMask
 import com.hzliuzhi.applet.browser.ui.components.ProgressBar
 import com.hzliuzhi.applet.browser.webview.WebContent
 import com.hzliuzhi.applet.browser.webview.WebView
@@ -32,13 +33,20 @@ fun KioskScreen(
       if (constraints.hasFixedWidth) LayoutParams.MATCH_PARENT else LayoutParams.WRAP_CONTENT,
       if (constraints.hasFixedHeight) LayoutParams.MATCH_PARENT else LayoutParams.WRAP_CONTENT,
     )
-    WebView(
-      layoutParams = layoutParams,
-      controller = controller,
-      onCreated = { controller.connected(it, content) },
-      onDispose = { controller.unconnected(it) }
-    )
 
-    ProgressBar(state.load, modifier = Modifier.zIndex(1f))
+    NetworkMask(
+      waitSecond = 5,
+      modifier = Modifier.zIndex(2f),
+      onRefresh = { controller.navigator.reload() }
+    ) {
+      WebView(
+        layoutParams = layoutParams,
+        controller = controller,
+        onCreated = { controller.connected(it, content) },
+        onDispose = { controller.unconnected(it) }
+      )
+
+      ProgressBar(state.load, modifier = Modifier.zIndex(1f))
+    }
   }
 }

+ 149 - 0
library/browser/src/main/java/com/hzliuzhi/applet/browser/ui/components/NetworkMask.kt

@@ -0,0 +1,149 @@
+package com.hzliuzhi.applet.browser.ui.components
+
+import android.content.Context
+import android.content.Intent
+import android.net.ConnectivityManager
+import android.net.Network
+import android.net.NetworkCapabilities
+import android.net.NetworkRequest
+import android.provider.Settings
+import android.widget.Toast
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material3.AlertDialog
+import androidx.compose.material3.Button
+import androidx.compose.material3.CircularProgressIndicator
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.MutableState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import kotlinx.coroutines.delay
+
+@Composable
+fun NetworkMask(
+  modifier: Modifier = Modifier,
+  onOpenSettings: (() -> Unit)? = null,
+  onRefresh: (() -> Unit)? = null,
+  waitSecond: Int = 0,
+  content: (@Composable () -> Unit)? = null,
+) {
+  val context = LocalContext.current
+  val networkAvailable by rememberNetworkAvailable(context)
+
+  var lastNetworkAvailable by remember { mutableStateOf<Boolean?>(null) }
+
+
+  var loaded by remember { mutableStateOf(false) }
+  var showDialog by remember { mutableStateOf(false) }
+  var showLoading by remember { mutableStateOf(false) }
+
+  // 默认跳转到系统设置的方法
+  val defaultOpenSettings: () -> Unit = {
+    Intent(Settings.ACTION_WIRELESS_SETTINGS).apply {
+      addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+      context.startActivity(this)
+    }
+  }
+
+  LaunchedEffect(networkAvailable, waitSecond) {
+    val last = lastNetworkAvailable
+    if (last == null && waitSecond > 0) {
+      showLoading = !networkAvailable
+      showDialog = false
+      if (showLoading) delay(waitSecond * 1000L)
+    }
+
+    lastNetworkAvailable = networkAvailable
+    showDialog = !networkAvailable
+    showLoading = false
+
+    when (last) {
+      false -> /* 网络从断开(false)变为连接(true)时 */ if (networkAvailable) onRefresh?.invoke()
+      null -> /* 首次连接时 */ loaded = true
+      else -> loaded = true
+    }
+  }
+
+  showLoading.takeIf { it }?.let {
+    Box(
+      modifier = modifier.fillMaxSize(),
+      contentAlignment = Alignment.Center
+    ) {
+      Column(horizontalAlignment = Alignment.CenterHorizontally) {
+        CircularProgressIndicator()
+        Text("正在检测网络...")
+      }
+    }
+  }
+
+  showDialog.takeIf { it }?.let {
+    AlertDialog(
+      modifier = modifier,
+      onDismissRequest = {},
+      title = { Text("无网络连接") },
+      text = { Text("请检查您的网络设置。") },
+      confirmButton = {
+        Button(onClick = onOpenSettings ?: defaultOpenSettings) {
+          Text("打开设置")
+        }
+      },
+      dismissButton = {
+        Button(onClick = {
+          if (checkNetworkConnected(context)) {
+            showDialog = false
+            onRefresh?.invoke()
+          } else {
+            Toast.makeText(context, "网络未连接", Toast.LENGTH_SHORT).show()
+          }
+        }) {
+          Text("刷新")
+        }
+      }
+    )
+  }
+
+  if (loaded) content?.invoke()
+}
+
+@Composable
+fun rememberNetworkAvailable(context: Context = LocalContext.current): MutableState<Boolean> {
+  val networkAvailable = remember { mutableStateOf(true) }
+
+  DisposableEffect(context) {
+    val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+    val callback = object : ConnectivityManager.NetworkCallback() {
+      override fun onAvailable(network: Network) {
+        networkAvailable.value = true
+      }
+
+      override fun onLost(network: Network) {
+        networkAvailable.value = checkNetworkConnected(context)
+      }
+    }
+    val request = NetworkRequest.Builder()
+      .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+      .build()
+    cm.registerNetworkCallback(request, callback)
+    networkAvailable.value = checkNetworkConnected(context)
+    onDispose {
+      cm.unregisterNetworkCallback(callback)
+    }
+  }
+  return networkAvailable
+}
+
+private fun checkNetworkConnected(context: Context): Boolean {
+  val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+  val network = cm.activeNetwork ?: return false
+  val capabilities = cm.getNetworkCapabilities(network) ?: return false
+  return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+}

+ 1 - 1
library/browser/src/main/java/com/hzliuzhi/applet/browser/webview/WrapperWebViewClient.kt

@@ -30,7 +30,7 @@ open class WrapperWebViewClient : WebViewClient() {
   override fun onPageFinished(view: WebView?, url: String?) {
     super.onPageFinished(view, url)
     // 只处理首次次加载的 url
-    url?.takeUnless { finished.add(it) }?.also {
+    url?.takeIf { finished.add(it) }?.also {
       view?.also { controller.bridge.inject(it) }
     }
     controller.state.apply {