如何从WebView下载JavaScript生成的文件

问题描述 投票:0回答:1

我对 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>
javascript java android webview
1个回答
0
投票

您无法使用 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。

© www.soinside.com 2019 - 2024. All rights reserved.