Compare commits
2 Commits
4964c7e207
...
31ffe13029
| Author | SHA1 | Date |
|---|---|---|
|
|
31ffe13029 | |
|
|
e091197527 |
|
|
@ -34,6 +34,7 @@ public class FirstActivity extends BaseActivity {
|
||||||
private static final String TAG = "FirstActivity";
|
private static final String TAG = "FirstActivity";
|
||||||
private WebView webView;
|
private WebView webView;
|
||||||
protected WebViewLogger webViewLogger;
|
protected WebViewLogger webViewLogger;
|
||||||
|
private final Handler handler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
// 扩展的 MIME 类型映射
|
// 扩展的 MIME 类型映射
|
||||||
private static final Map<String, String> MIME_TYPES = new HashMap<>();
|
private static final Map<String, String> MIME_TYPES = new HashMap<>();
|
||||||
|
|
@ -52,6 +53,27 @@ public class FirstActivity extends BaseActivity {
|
||||||
MIME_TYPES.put("woff2", "font/woff2");
|
MIME_TYPES.put("woff2", "font/woff2");
|
||||||
MIME_TYPES.put("ttf", "font/ttf");
|
MIME_TYPES.put("ttf", "font/ttf");
|
||||||
MIME_TYPES.put("wasm", "application/wasm");
|
MIME_TYPES.put("wasm", "application/wasm");
|
||||||
|
|
||||||
|
MIME_TYPES.put("pdf", "application/pdf");
|
||||||
|
MIME_TYPES.put("zip", "application/zip");
|
||||||
|
MIME_TYPES.put("rar", "application/x-rar-compressed");
|
||||||
|
MIME_TYPES.put("7z", "application/x-7z-compressed");
|
||||||
|
MIME_TYPES.put("csv", "text/csv");
|
||||||
|
MIME_TYPES.put("txt", "text/plain");
|
||||||
|
MIME_TYPES.put("mp3", "audio/mpeg");
|
||||||
|
MIME_TYPES.put("mp4", "video/mp4");
|
||||||
|
MIME_TYPES.put("mov", "video/quicktime");
|
||||||
|
MIME_TYPES.put("webm", "video/webm");
|
||||||
|
MIME_TYPES.put("ogg", "audio/ogg");
|
||||||
|
MIME_TYPES.put("wav", "audio/wav");
|
||||||
|
MIME_TYPES.put("eot", "application/vnd.ms-fontobject");
|
||||||
|
MIME_TYPES.put("otf", "font/otf");
|
||||||
|
MIME_TYPES.put("doc", "application/msword");
|
||||||
|
MIME_TYPES.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
|
||||||
|
MIME_TYPES.put("xls", "application/vnd.ms-excel");
|
||||||
|
MIME_TYPES.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||||
|
MIME_TYPES.put("ppt", "application/vnd.ms-powerpoint");
|
||||||
|
MIME_TYPES.put("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -215,10 +237,23 @@ public class FirstActivity extends BaseActivity {
|
||||||
// || url.endsWith(".xlsx")
|
// || url.endsWith(".xlsx")
|
||||||
// || url.contains("/api/file/");
|
// || url.contains("/api/file/");
|
||||||
}
|
}
|
||||||
|
private long currentDownloadId = -1; // 保存当前下载任务ID
|
||||||
|
|
||||||
private void downloadFile(String url) {
|
private void downloadFile(String url) {
|
||||||
try {
|
try {
|
||||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
|
if (TextUtils.isEmpty(url)) {
|
||||||
|
Toast.makeText(this, "下载地址为空", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.startsWith("blob:") || url.startsWith("data:")) {
|
||||||
|
Toast.makeText(this, "无法直接下载 Blob 文件,请检查前端下载逻辑", Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uri uri = Uri.parse(url);
|
||||||
|
DownloadManager.Request request = new DownloadManager.Request(uri);
|
||||||
|
|
||||||
String fileName = URLUtil.guessFileName(url, null, null);
|
String fileName = URLUtil.guessFileName(url, null, null);
|
||||||
request.setTitle(fileName);
|
request.setTitle(fileName);
|
||||||
request.setDescription("正在下载文件...");
|
request.setDescription("正在下载文件...");
|
||||||
|
|
@ -227,16 +262,73 @@ public class FirstActivity extends BaseActivity {
|
||||||
request.allowScanningByMediaScanner();
|
request.allowScanningByMediaScanner();
|
||||||
request.addRequestHeader("User-Agent", System.getProperty("http.agent"));
|
request.addRequestHeader("User-Agent", System.getProperty("http.agent"));
|
||||||
|
|
||||||
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||||
dm.enqueue(request);
|
request.setRequiresCharging(false);
|
||||||
|
request.setAllowedOverMetered(true);
|
||||||
|
request.setAllowedOverRoaming(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
String mimeType = getMimeTypeForUrl(url);
|
||||||
|
request.setMimeType(!TextUtils.isEmpty(mimeType) ? mimeType : "application/octet-stream");
|
||||||
|
|
||||||
|
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
|
||||||
|
if (dm != null) {
|
||||||
|
currentDownloadId = dm.enqueue(request);
|
||||||
|
Toast.makeText(this, "文件已开始下载,请等待", Toast.LENGTH_SHORT).show();
|
||||||
|
startDownloadProgressMonitor(dm, currentDownloadId);
|
||||||
|
} else {
|
||||||
|
Toast.makeText(this, "系统下载服务不可用", Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
Toast.makeText(this, "文件已开始下载,完成后可在通知栏查看", Toast.LENGTH_SHORT).show();
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Toast.makeText(this, "下载失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
Toast.makeText(this, "下载失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ✅ 监控下载进度,每秒回调一次到前端
|
||||||
|
*/
|
||||||
|
private void startDownloadProgressMonitor(DownloadManager dm, long downloadId) {
|
||||||
|
new Thread(() -> {
|
||||||
|
DownloadManager.Query query = new DownloadManager.Query();
|
||||||
|
query.setFilterById(downloadId);
|
||||||
|
boolean downloading = true;
|
||||||
|
|
||||||
|
while (downloading) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
android.database.Cursor cursor = dm.query(query);
|
||||||
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
|
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
|
||||||
|
long total = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
|
||||||
|
long downloaded = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
|
||||||
|
if (status == DownloadManager.STATUS_RUNNING && total > 0) {
|
||||||
|
int progress = (int) ((downloaded * 100L) / total);
|
||||||
|
handler.post(() -> sendProgressToJs(progress));
|
||||||
|
} else if (status == DownloadManager.STATUS_SUCCESSFUL) {
|
||||||
|
downloading = false;
|
||||||
|
handler.post(() -> sendProgressToJs(100));
|
||||||
|
} else if (status == DownloadManager.STATUS_FAILED) {
|
||||||
|
downloading = false;
|
||||||
|
handler.post(() -> sendProgressToJs(-1));
|
||||||
|
}
|
||||||
|
cursor.close();
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendProgressToJs(int progress) {
|
||||||
|
try {
|
||||||
|
if (webView != null) {
|
||||||
|
String js = String.format("if(window.onDownloadProgress){window.onDownloadProgress(%d);}", progress);
|
||||||
|
webView.evaluateJavascript(js, null);
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
public static class JsBridge {
|
public static class JsBridge {
|
||||||
private final WeakReference<FirstActivity> activityRef;
|
private final WeakReference<FirstActivity> activityRef;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue