如何在 Android 上的 WebView 中读取 Blob 中的数据?

Posted

技术标签:

【中文标题】如何在 Android 上的 WebView 中读取 Blob 中的数据?【英文标题】:How to read the data in a Blob in WebView on Android? 【发布时间】:2016-05-25 20:19:09 【问题描述】:

我有一个在浏览器上创建对象 blob 的服务器,我想在 android 应用程序的 WebView 中下载它。我尝试将请求重定向到浏览器实例以及使用下载管理器来执行此操作,但它们似乎都不起作用(即使我在 Chrome 中打开同一页面,下载操作也可以在那里进行)。

我尝试了以下代码,它抛出错误:

Android.content.ActivityNotFoundException: 没有找到处理 Intent 的活动 act=android.intent.action.VIEW dat=blob:https%3A//111.111.111.111%3A8080/40b63131-63b1-4fa4-9451-c6297bbd111a"

编辑

Android.content.ActivityNotFoundException:未找到处理 Intent 的 Activity act=android.intent.action.VIEW dat=blob:http://digitalinsensu.com/0f0d6127-a0f1-44c3-af85-72f648258d6d


代码:

mWebView.setDownloadListener(new DownloadListener() 
public void onDownloadStart(String url, String userAgent,String contentDisposition, String mimetype,long contentLength) 
    Intent i = new Intent(Intent.ACTION_VIEW);
    i.setData(Uri.parse(url));
    startActivity(i);

);

这会引发 java.lang.IllegalArgumentException: Can only download HTTP/HTTPS URIs 错误:

mWebView.setDownloadListener(new DownloadListener() 
    public void onDownloadStart(String url, String userAgent,String contentDisposition, String mimetype,long contentLength) 
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        request.allowScanningByMediaScanner();
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "download");
        DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
        dm.enqueue(request);

    
);

我应该如何下载 blob?任何帮助,将不胜感激。

【问题讨论】:

您希望发生什么而不是崩溃? 为什么要使用 webview 来下载对象?它不知道如何解析网页以外的任何内容。请改用 DownloadManager。 @GabeSechan 我在我的 webview 中加载了一个 url,它做了很多事情并创建了一个 blob,我想把它下载到设备上。 @DougStevenson 我知道该代码不起作用,因为它试图对保存在浏览器上的 blob 而不是 HTTP 地址进行操作,但我无法找到如何下载 blob安卓。 @GulizTuncay 如果 url 字符串只是“blob:”,我不认为你可以用它来获取你想要的数据。 【参考方案1】:

是的,应该可以。在您的情况下,URL 如下所示,一旦删除 blob: 前缀,其余部分将被 URL 解码:

blob:http://digitalinsensu.com/0f0d6127-a0f1-44c3-af85-72f648258d6d

请注意,此 URL 仅在用户的设备上运行有响应请求的网络服务器时才有效,即unlikely in case of blob: URLs。如果你想这样做,你需要先删除blob:,使用Java的String.replace(..)或类似的。要解码 URL,请使用 URLDecoder.decode(url, "UTF-8"); 之类的内容,有关详细信息,请参阅 here。

问题在于 DownloadListener 确实需要一个 URI(例如 http://server.com/file.pdf)。但是,用户单击的链接不会传递该格式的 URI。传递的 URL 表示附加到浏览器的 DOM 的 blob。因此,该解决方案将无法按设计工作。

您可能还有其他选择。这取决于您如何为 blob 生成字节。您提到您正在使用 javascript 执行此操作。如果是这样,我会完全跳过使用 Blob 和 URL.createObjectURL 并编写一个 Javascript/Native interface,它允许您将字节(例如 n 个 255 字节的数组)以块的形式传输到 Java 代码。这将降低客户端的内存消耗。

我对如何创建接口有一个想法,但我首先需要了解如何为 blob 生成字节。如果您可以发布一个字节数组,我可以进一步尝试。

有关此检查的完整详细信息here

【讨论】:

我尝试过类似的方法,但在 macOS WebView 上没有成功,但在这里遇到同样的问题 - ***.com/questions/49988202/…【参考方案2】:

你需要像这样拦截回调来处理 url 点击:

webView.setWebViewClient(new WebViewClient() 
    @Override
    public void onPageStarted(WebView view, String url, Bitmap favicon) 
        super.onPageStarted(view, url, favicon);
        shouldOverrideUrlLoading(view, Uri.parse(url));
    

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) 
        return shouldOverrideUrlLoading(view, request.getUrl());
    

    // legacy callback
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) 
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) 
            return shouldOverrideUrlLoading(view, Uri.parse(url));
        
        return super.shouldOverrideUrlLoading(view, url);
    

    private boolean shouldOverrideUrlLoading(final WebView view, final Uri request) 
        if(request.getScheme().equals("blob")) 
            // do your special handling for blob urls here
            return true;
        
    
);

shouldOverrideUrlLoading()你可以做你的特殊处理。

【讨论】:

请说明哪种类型的特殊处理? bdw shouldOverrideUrlLoading() 根本没有被调用:-( 你想用那个网址做什么? 尝试这种特殊处理:webView.loadUrl(request.toString().substring(5)); 正确的http地址应该是什么样子的?我的意思是没有官方的blob协议。 shouldOverrideUrlLoading() 根本不会触发此下载(使用 Webview 66 测试)

以上是关于如何在 Android 上的 WebView 中读取 Blob 中的数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何在nativescript vue中处理webview上的android后退按钮

如何从不在 Android 的 API 26 上的 WebView 获取 WebviewClient 实例?

如何在 Android 上的 WebView 中读取 Blob 中的数据?

取消在 Android 上的 WebView 中加载

如何在 Android/iOS 上的 webview/移动浏览器中最好地预缓存视频?

如何将html字符串传递给android上的webview