我对 Java 概念不熟悉。我正在尝试下载 Android 资产中 html 文件的 JavaScript 生成的内容,但是当我单击下载按钮时应用程序崩溃了。我想我必须创建一个 JavaScript 接口来与 Java 进行通信,但是我不知道如何做到这一点,并且希望获得有关这方面的帮助。如何在webview中下载JavaScript生成的文件?
package com.fun.fun;
import androidx.appcompat.app.AppCompatActivity;
import android.Manifest;
import android.app.DownloadManager;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.webkit.CookieManager;
import android.webkit.DownloadListener;
import android.webkit.URLUtil;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private WebView web;
// application crashes if I download a file generated from script side of the following url;
String webUrl = "file:///android_asset/indexi.html";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
web = (WebView) findViewById(R.id.myweb);
web.loadUrl(webUrl);
WebSettings mywebsettings = web.getSettings();
mywebsettings.setJavaScriptEnabled(true);
web.setWebViewClient(new WebViewClient());
//improve webview performance
web.getSettings().setRenderPriority(WebSettings.RenderPriority.HIGH);
web.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
web.getSettings().setAppCacheEnabled(true);
web.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
mywebsettings.setDomStorageEnabled(true);
mywebsettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
mywebsettings.setUseWideViewPort(true);
mywebsettings.setSavePassword(true);
mywebsettings.setSaveFormData(true);
mywebsettings.setEnableSmoothTransition(true);
//External storage permission for saving file
if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.M){
if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED){
Log.d("permission","permission denied to WRITE_EXTERNAL_STORAGE - requesting it");
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
requestPermissions(permissions,1);
}
}
//handle downloading
web.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setMimeType(mimeType);
String cookies = CookieManager.getInstance().getCookie(url);
request.addRequestHeader("cookie",cookies);
request.addRequestHeader("User-Agent",userAgent);
request.setDescription("Downloading file....");
request.setTitle(URLUtil.guessFileName(url,contentDisposition,mimeType));
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS,URLUtil.guessFileName(url, contentDisposition, mimeType));
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(request);
Toast.makeText(getApplicationContext(),"Downloading File",Toast.LENGTH_SHORT).show();
}
});
}
@Override
public void onBackPressed() {
if(web.canGoBack()){
web.goBack();
}
else {
super.onBackPressed();
}
}
}
我在 webview 中加载的 html 文件是;
<html>
<div id="disp"></div>
<script>
function objectsToCSV(arr) {
const array = [Object.keys(arr[0])].concat(arr)
return array.map(row => {
return Object.values(row).map(value => {
return typeof value === 'string' ? JSON.stringify(value) : value }).toString()
}).join('\n') }
var items = [
{ "name": "Item 1", "color": "Green", "size": "X-Large" },
{ "name": "Item 2", "color": "Green", "size": "X-Large" },
{ "name": "Item 3", "color": "Green", "size": "X-Large" }];
var csv = objectsToCSV(items);
document.getElementById("disp").innerHTML = csv;
function downloadCSV(csv) {
const blob = new Blob([csv], { type: 'text/csv' });
const anchor = document.createElement('a');
anchor.href = window.URL.createObjectURL(blob);
anchor.download = 'my_data.csv';
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
}
const downloadButton = document.createElement('button');
downloadButton.textContent = 'Download CSV';
downloadButton.addEventListener('click', () => {
downloadCSV(csv);
});
document.body.appendChild(downloadButton);
</script>
</html>
您无法使用 DownloadManager 来实现您想要的目的。你会得到类似的东西:
java.lang.IllegalArgumentException: Can only download HTTP/HTTPS URIs: blob:null/11d27a3a-c76e-4b6f-9030-f3c0dfe1dd61
现在通过谷歌搜索,我们发现所有问题之前都已报告并解决了。
我刚刚尝试了这些建议,并且使用您的indexi.html 文件对我有用:
无法在 Android 上的 WebView 中下载 Blob 文件类型
从 Android WebViewClient 内的网站下载 Blob 文件
只需更改一些内容即可使其适用于从资产加载的 html 文件。
请编辑帖子的主题,包括从资产加载 html 以及将 pdf 更改为 csv 或 txt。