Download Blob file from website in Android WebViewClient

I have an HTML web page with a button that launches a POST request when the user clicks. When the request is completed, the following code will be run:

window.open(fileUrl); 

Everything works fine in the browser, but when implemented inside the Webview component, a new tab does not open.

FYI: In my Android app, I asked the following things:

 webview.getSettings().setJavaScriptEnabled(true); webview.getSettings().setSupportMultipleWindows(true); webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); 

On AndroidManifest.xml , I have the following permissions:

 <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/> 

I am also trying to use setDownloadListener to catch a load. Another approach was replaced with WebViewClient() for WebChromeClient() , but the behavior was the same.

+7
source share
3 answers

Well, I had the same problem with webviews, I realized that WebViewClient cannot load "blob urls" as the Chrome Desktop client does, I decided to use Javascript interfaces. You can do this in accordance with these steps, it works fine in this application with minSdkVersion: 17. First, convert the Blob URL data to Base64 string via JS. Secondly, send this line to the Java class and finally convert it to an accessible format, in this case I converted it to a ".pdf" file.

Primarily. You have to set up your webview, in my case I load the webpages into a snippet:

 public class WebviewFragment extends Fragment { WebView browser; ... // invoke this method after set your WebViewClient and ChromeClient private void browserSettings() { browser.getSettings().setJavaScriptEnabled(true); browser.setDownloadListener(new DownloadListener() { @Override public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) { browser.loadUrl(JavaScriptInterface.getBase64StringFromBlobUrl(url)); } }); browser.getSettings().setAppCachePath(getActivity().getApplicationContext().getCacheDir().getAbsolutePath()); browser.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); browser.getSettings().setDatabaseEnabled(true); browser.getSettings().setDomStorageEnabled(true); browser.getSettings().setUseWideViewPort(true); browser.getSettings().setLoadWithOverviewMode(true); browser.addJavascriptInterface(new JavaScriptInterface(getContext()), "Android"); browser.getSettings().setPluginState(PluginState.ON); } } 

Having this, let's create JavaScriptInterface.class, this class will have our script that will be executed on our web page.

 public class JavaScriptInterface { private Context context; private NotificationManager nm; public JavaScriptInterface(Context context) { this.context = context; } @JavascriptInterface public void getBase64FromBlobData(String base64Data) throws IOException { convertBase64StringToPdfAndStoreIt(base64Data); } public static String getBase64StringFromBlobUrl(String blobUrl){ if(blobUrl.startsWith("blob")){ return "javascript: var xhr = new XMLHttpRequest();" + "xhr.open('GET', 'YOUR BLOB URL GOES HERE', true);" + "xhr.setRequestHeader('Content-type','application/pdf');" + "xhr.responseType = 'blob';" + "xhr.onload = function(e) {" + " if (this.status == 200) {" + " var blobPdf = this.response;" + " var reader = new FileReader();" + " reader.readAsDataURL(blobPdf);" + " reader.onloadend = function() {" + " base64data = reader.result;" + " Android.getBase64FromBlobData(base64data);" + " }" + " }" + "};" + "xhr.send();"; } return "javascript: console.log('It is not a Blob URL');"; } private void convertBase64StringToPdfAndStoreIt(String base64PDf) throws IOException { final int notificationId = 1; String currentDateTime = DateFormat.getDateTimeInstance().format(new Date()); final File dwldsPath = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_DOWNLOADS) + "/YourFileName_" + currentDateTime + "_.pdf"); byte[] pdfAsBytes = Base64.decode(base64PDf.replaceFirst("^data:application/pdf;base64,", ""), 0); FileOutputStream os; os = new FileOutputStream(dwldsPath, false); os.write(pdfAsBytes); os.flush(); if(dwldsPath.exists()) { NotificationCompat.Builder b = new NotificationCompat.Builder(context, "MY_DL"); .setDefaults(NotificationCompat.DEFAULT_ALL) .setWhen(System.currentTimeMillis()) .setSmallIcon(R.drawable.ic_file_download_24dp) .setContentTitle("MY TITLE") .setContentText("MY TEXT CONTENT"); nm = (NotificationManager) this.context.getSystemService(Context.NOTIFICATION_SERVICE); if(nm != null) { nm.notify(notificationId, b.build()); Handler h = new Handler(); long delayInMilliseconds = 5000; h.postDelayed(new Runnable() { public void run() { nm.cancel(notificationId); } }, delayInMilliseconds); } } } } 

Sources:

fooobar.com/questions/1269959 / ...

fooobar.com/questions/79530 / ...

fooobar.com/questions/805718 / ...

+10
source

Kevin Perez .. Please give some clarity where we need to add "Android.getBase64FromBlobData (base64data);"

0
source

I used this in my code:

 ngOnInit() { let webview: WebView = this.webViewRef.nativeElement; if (isAndroid) { webview.on(WebView.loadStartedEvent, function () { webview.android.getSettings().setBuiltInZoomControls(false); webview.android.getSettings().setJavaScriptEnabled(true); webview.android.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); webview.android.getSettings().setAllowFileAccess(true); webview.android.getSettings().setPluginsEnabled(true); webview.android.getSettings().setAllowContentAccess(true); webview.android.getSettings().setAllowFileAccess(true); webview.android.getSettings().setAllowFileAccessFromFileURLs(true); webview.android.getSettings().setAllowUniversalAccessFromFileURLs(true); webview.android.getSettings().setDomStorageEnabled(true); webview.android.getSettings().setDefaultTextEncodingName("utf-8"); webview.android.setDownloadListener(new android.webkit.DownloadListener({ onDownloadStart(url, userAgent, contentDisposition, mimetype, contentLength) { let request = new android.app.DownloadManager.Request(android.net.Uri.parse(url)); request.setMimeType(mimetype); let cookies = android.webkit.CookieManager.getInstance().getCookie(url); request.addRequestHeader("cookie", cookies); request.addRequestHeader("User-Agent", userAgent); request.setDescription("Downloading file..."); request.setTitle(android.webkit.URLUtil.guessFileName(url, contentDisposition, mimetype)); request.allowScanningByMediaScanner(); request.setNotificationVisibility(android.app.DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); request.setDestinationInExternalPublicDir(android.os.Environment.DIRECTORY_DOWNLOADS, android.webkit.URLUtil.guessFileName(url, contentDisposition, mimetype)); let dm = utils.ad.getApplicationContext().getSystemService(android.content.Context.DOWNLOAD_SERVICE); dm.enqueue(request); } })); }); } 
-1
source

Source: https://habr.com/ru/post/1269940/


All Articles