diff --git a/sdk-webview/src/main/java/com/xuqm/sdk/webview/XWebViewView.kt b/sdk-webview/src/main/java/com/xuqm/sdk/webview/XWebViewView.kt index 46ed28d..12dd8ad 100644 --- a/sdk-webview/src/main/java/com/xuqm/sdk/webview/XWebViewView.kt +++ b/sdk-webview/src/main/java/com/xuqm/sdk/webview/XWebViewView.kt @@ -2,6 +2,8 @@ package com.xuqm.sdk.webview import android.Manifest import android.annotation.SuppressLint +import android.content.Context +import android.content.Intent import android.content.pm.PackageManager import android.net.Uri import android.os.Handler @@ -30,6 +32,7 @@ import androidx.compose.ui.viewinterop.AndroidView import androidx.core.content.ContextCompat import androidx.core.content.FileProvider import java.io.File +import java.util.Locale // JS injected into every page to bridge dialog APIs and download interception. // Uses addJavascriptInterface("ReactNativeWebView") for the JS→Native channel. @@ -107,6 +110,21 @@ true; internal fun buildInjectedJs(config: XWebViewConfig): String = DIALOG_OVERRIDE_JS + "\n" + (config.injectedJavaScript ?: "") + "\ntrue;" +internal fun shouldLoadInWebView(uri: Uri): Boolean { + val scheme = uri.scheme?.lowercase(Locale.ROOT) ?: return true + return scheme in setOf("http", "https", "about", "data", "blob", "javascript") +} + +internal fun openExternalScheme(context: Context, uri: Uri): Boolean { + return runCatching { + val intent = Intent(Intent.ACTION_VIEW, uri).apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + context.startActivity(intent) + true + }.getOrDefault(false) +} + // Routes window.ReactNativeWebView.postMessage() calls to [onMessage]. // @JavascriptInterface methods are called on a background thread; we post to main. internal class XWebViewJsBridge( @@ -224,7 +242,12 @@ fun XWebViewView( } override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean { - return false + val uri = request?.url ?: return false + if (shouldLoadInWebView(uri)) { + return false + } + openExternalScheme(ctx, uri) + return true } }