From 04b4e489e4e34489e009ef0169371c2ec682f051 Mon Sep 17 00:00:00 2001 From: frank wang <425294756@qq.com> Date: Mon, 13 Oct 2025 17:40:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=B8=8B=E8=BD=BD=E6=8F=90?= =?UTF-8?q?=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 3 +- .../java/com/pxkj/jwzs/FirstActivity.java | 152 ++++++++---------- 2 files changed, 67 insertions(+), 88 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ed93d76..e56234b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,8 +2,9 @@ - + + MIME_TYPES = new HashMap<>(); static { MIME_TYPES.put("js", "text/javascript"); - MIME_TYPES.put("mjs", "text/javascript"); // 模块JavaScript + MIME_TYPES.put("mjs", "text/javascript"); MIME_TYPES.put("css", "text/css"); MIME_TYPES.put("html", "text/html"); MIME_TYPES.put("png", "image/png"); @@ -58,31 +59,11 @@ public class FirstActivity extends BaseActivity { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - // 初始化Toolbar -// androidx.appcompat.widget.Toolbar toolbar = findViewById(R.id.toolbar); -// setSupportActionBar(toolbar); // 关键:将Toolbar设为ActionBar - - // 显示返回按钮 -// if (getSupportActionBar() != null) { -// getSupportActionBar().setDisplayHomeAsUpEnabled(true); -// getSupportActionBar().setDisplayShowHomeEnabled(true); -// } - - // 设置返回按钮点击事件 -// toolbar.setNavigationOnClickListener(v -> { -// if (webView.canGoBack()) { -// webView.goBack(); -// } else { -// finish(); -// } -// }); - initWebView(); loadLocalH5(); verifyAssets(); } - @Override public void onBackPressed() { if (webView.canGoBack()) { @@ -91,26 +72,11 @@ public class FirstActivity extends BaseActivity { super.onBackPressed(); } } + private void verifyAssets() { try { String[] files = getAssets().list("web"); Log.d(TAG, "Assets/web 目录内容: " + java.util.Arrays.toString(files)); - - if (files != null) { - boolean hasIndexHtml = false; - boolean hasAssetsDir = false; - for (String file : files) { - if (file.equals("index.html")) hasIndexHtml = true; - if (file.equals("assets")) hasAssetsDir = true; - } - Log.d(TAG, "index.html 存在: " + hasIndexHtml); - Log.d(TAG, "assets 目录存在: " + hasAssetsDir); - - if (hasAssetsDir) { - String[] assetFiles = getAssets().list("web/assets"); - Log.d(TAG, "Assets/web/assets 目录内容: " + java.util.Arrays.toString(assetFiles)); - } - } } catch (IOException e) { Log.e(TAG, "无法读取 assets 目录", e); } @@ -120,7 +86,6 @@ public class FirstActivity extends BaseActivity { webView = findViewById(R.id.webview); WebSettings settings = webView.getSettings(); - // 基本设置 settings.setJavaScriptEnabled(true); settings.setDomStorageEnabled(true); settings.setDatabaseEnabled(true); @@ -130,30 +95,21 @@ public class FirstActivity extends BaseActivity { settings.setLoadsImagesAutomatically(true); settings.setBlockNetworkImage(false); settings.setBlockNetworkLoads(false); - - // 缓存设置 settings.setCacheMode(WebSettings.LOAD_DEFAULT); - // 跨域设置 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { settings.setAllowFileAccessFromFileURLs(true); settings.setAllowUniversalAccessFromFileURLs(true); } - - // 混合内容设置 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } - - // 对于Android 10+的暗黑模式设置 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { settings.setForceDark(WebSettings.FORCE_DARK_OFF); } - // 添加JS接口 webView.addJavascriptInterface(new JsBridge(this), "AndroidBridge"); - // 启用WebView调试 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { WebView.setWebContentsDebuggingEnabled(true); } @@ -168,16 +124,23 @@ public class FirstActivity extends BaseActivity { @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { - // 忽略SSL错误(仅用于开发环境) handler.proceed(); } + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + if (isDownloadUrl(url)) { + downloadFile(url); + return true; + } + return super.shouldOverrideUrlLoading(view, url); + } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) @Override public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { String url = request.getUrl().toString(); log(TAG, "拦截请求: " + url); - return handleResourceRequest(url); } @@ -194,52 +157,37 @@ public class FirstActivity extends BaseActivity { if (url.startsWith("file:///android_asset/")) { try { String assetPath = url.replace("file:///android_asset/", ""); - - // 标准化路径处理 - assetPath = assetPath.replace("web/./", "web/") - .replace("/./", "/"); - - // 确保路径以web/开头 - if (!assetPath.startsWith("web/")) { - assetPath = "web/" + assetPath; - } + assetPath = assetPath.replace("web/./", "web/").replace("/./", "/"); + if (!assetPath.startsWith("web/")) assetPath = "web/" + assetPath; InputStream inputStream = getAssets().open(assetPath); String mimeType = getMimeTypeForUrl(url); - log(TAG, "成功加载资源: " + assetPath + " | MIME: " + mimeType); return new WebResourceResponse(mimeType, "UTF-8", inputStream); } catch (IOException e) { log(TAG, "资源加载失败: " + url + ", 错误: " + e.getMessage()); - return null; // 返回null让WebView尝试其他方式加载 + return null; } } return null; } }); + + // DownloadListener 备用 + webView.setDownloadListener((url, userAgent, contentDisposition, mimeType, contentLength) -> { + downloadFile(url); + }); } private String getMimeTypeForUrl(String url) { - // 特殊处理模块脚本 - if (url.contains("index-DJSXJc-t.js") || url.contains(".mjs") || - (url.contains("module") && url.endsWith(".js"))) { + if (url.contains("index-DJSXJc-t.js") || url.contains(".mjs") || (url.contains("module") && url.endsWith(".js"))) { return "text/javascript"; } - - // 移除URL中的查询参数和哈希 String cleanUrl = url.split("[?#]")[0]; - - // 从文件扩展名获取MIME类型 String extension = ""; int dotIndex = cleanUrl.lastIndexOf('.'); - if (dotIndex > 0) { - extension = cleanUrl.substring(dotIndex + 1).toLowerCase(); - } - - // 从预设映射中获取MIME类型 + if (dotIndex > 0) extension = cleanUrl.substring(dotIndex + 1).toLowerCase(); String mimeType = MIME_TYPES.get(extension); - - // 默认值 return mimeType != null ? mimeType : "text/plain"; } @@ -251,13 +199,46 @@ public class FirstActivity extends BaseActivity { private void loadLocalH5() { runOnUiThread(() -> { - // 直接使用loadUrl加载,确保路径解析正确 String localUrl = "file:///android_asset/web/index.html"; log(TAG, "使用 loadUrl 加载: " + localUrl); webView.loadUrl(localUrl); }); } + private boolean isDownloadUrl(String url) { + if (TextUtils.isEmpty(url)) return false; + + return true; + +// return url.endsWith(".pdf") +// || url.endsWith(".doc") +// || url.endsWith(".docx") +// || url.endsWith(".xls") +// || url.endsWith(".xlsx") +// || url.contains("/api/file/"); + } + + private void downloadFile(String url) { + try { + DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url)); + String fileName = URLUtil.guessFileName(url, null, null); + request.setTitle(fileName); + request.setDescription("正在下载文件..."); + request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); + request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName); + request.allowScanningByMediaScanner(); + request.addRequestHeader("User-Agent", System.getProperty("http.agent")); + + DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); + dm.enqueue(request); + + Toast.makeText(this, "文件已开始下载,完成后可在通知栏查看", Toast.LENGTH_SHORT).show(); + } catch (Exception e) { + e.printStackTrace(); + Toast.makeText(this, "下载失败: " + e.getMessage(), Toast.LENGTH_SHORT).show(); + } + } + public static class JsBridge { private final WeakReference activityRef; @@ -271,8 +252,7 @@ public class FirstActivity extends BaseActivity { if (activity != null) { showLog("[Android] 开始获取资源地址..."); String baseUrl = SpUtils.getString(activity, "TARGET_URL", ""); - String logMsg = "[Android] 获取到资源地址: " + baseUrl; - showLog(logMsg); + showLog("[Android] 获取到资源地址: " + baseUrl); return baseUrl; } return null; @@ -280,7 +260,7 @@ public class FirstActivity extends BaseActivity { @JavascriptInterface public void callApiWithAddress(String apiPath) { - // 实现保持不变 + // 保持空实现 } @JavascriptInterface @@ -288,9 +268,7 @@ public class FirstActivity extends BaseActivity { FirstActivity activity = activityRef.get(); if (activity != null) { activity.runOnUiThread(() -> { - // 安全转义 - String escapedMessage = message - .replace("\\", "\\\\") + String escapedMessage = message.replace("\\", "\\\\") .replace("'", "\\'") .replace("\"", "\\\"") .replace("\n", "\\n") @@ -307,7 +285,7 @@ public class FirstActivity extends BaseActivity { protected void refresh() { // 空实现 } - +// // private void log(String tag, String message) { // Log.d(tag, message); // if (webViewLogger != null) { @@ -330,4 +308,4 @@ class WebViewLogger { Log.d(tag, message); handler.post(() -> bridge.showLog("[" + tag + "] " + message)); } -} \ No newline at end of file +}