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 / ...