Android WebView loadDataWithBaseURL shouldInterceptRequest - android

I am using a WebView to display an HTML string with img tags. These tags must display pictures stored in a ZIP archive, so I need to intercept the images requests to return a ZipInputStream.
I'm thus using loadDataWithBaseURL and shouldInterceptRequest, but shouldInterceptRequest is never called for my pictures requests. Here's my WebViewClient client:
webView.webViewClient = object : WebViewClient() {
override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest?): WebResourceResponse? {
println("shouldInterceptRequest1 url: ${request?.url}")
return super.shouldInterceptRequest(view, request)
}
override fun shouldInterceptRequest(view: WebView?, url: String?): WebResourceResponse? {
println("shouldInterceptRequest2 url: $url")
#Suppress("DEPRECATION")
return super.shouldInterceptRequest(view, url)
}
}
And here's what I do to load the HTML:
webView.loadDataWithBaseURL(null, "<div><img src='file://path/to/my/image.png'/></div>", "text/html", "UTF-8", null)
All I get in the logcat is this:
shouldInterceptRequest1 url: data:text/html;charset=utf-8;base64,
shouldInterceptRequest2 url: data:text/html;charset=utf-8;base64,
The img request does not trigger shouldInterceptRequest.
What's wrong?

Despite the doc says this:
This callback is invoked for a variety of URL schemes (e.g., http(s):,
data:, file:, etc.), not only those schemes which send requests over
the network. This is not called for javascript: URLs, blob: URLs, or
for assets accessed via file:///android_asset/ or file:///android_res/
URLs.
In my very basic sample code shouldInterceptRequest isn't called for file:// URIs when using loadDataWithBaseURL... Using a http:// scheme works.

Related

Android WebView does not display web page even though the page has successfully finished loading

I have added internet-permissions and I also used the WebViewClient.onPageFinished method to check whether the page has loaded which turns out it did. JavaScript is also enabled for my WebView.
The code I use to set up my web view
webView.webChromeClient = KeplerWebChromeClient(progressBar)
webView.webViewClient = keplerWebViewClient
webView.settings.javaScriptEnabled = true
webView.settings.useWideViewPort = true
webView.settings.loadWithOverviewMode = true
webView.settings.setSupportZoom(true)
webView.settings.setSupportMultipleWindows(true)
webView.scrollBarStyle = View.SCROLLBARS_INSIDE_OVERLAY
webView.setBackgroundColor(Color.WHITE)
I am using KeplerWebChromeClient to display web page loading progress.
keplerWebViewClient is an object of WebViewClient class which I use to load webpages and to track for whether the webpage has finished loading or not.
And I must mention that this issue doesn't always arise. Sometimes when I run my app, the WebView does work and it does load and display the web page correctly and other times it doesn't. I have found the below stated logcat entries to be unique to when the web page isn't displayed.
E/chromium: [ERROR:tile_manager.cc(778)] WARNING: tile memory limits exceeded, some content may not draw
[ERROR:tile_manager.cc(778)] WARNING: tile memory limits exceeded, some content may not draw
E/chromium: [ERROR:tile_manager.cc(778)] WARNING: tile memory limits exceeded, some content may not draw
E/chromium: [ERROR:tile_manager.cc(778)] WARNING: tile memory limits exceeded, some content may not draw
What is the issue here and how do I fix it? Thanks in advance.
Edit:
I cleared all the app data from my phone and then I restarted my app. After doing so, everything was working just fine. I was able to browse using the WebView but after using the app a few more times i.e. closing and opening it, the problem reappeared. Clearing all data solves the problem temporarily. What aid can this be in solving the problem?
I have to try and it's working fine for me.
private fun setupWebView(url: String) {
webView.settings.javaScriptEnabled = true
webView.settings.domStorageEnabled = true
webView.settings.setPluginState(WebSettings.PluginState.ON);
webView.settings.allowFileAccess = true;
webView.webViewClient = WebClient()
webView.webChromeClient = CustomWebChromeClient()
webView.loadUrl(url)
}
private inner class WebClient : WebViewClient() {
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
}
override fun onPageCommitVisible(view: WebView, url: String) {
super.onPageCommitVisible(view, url)
}
override fun shouldOverrideUrlLoading(
view: WebView,
url: String
): Boolean {
view.loadUrl(url)
return true
}
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
}
}
private inner class CustomWebChromeClient : WebChromeClient() {
override fun onJsAlert(
view: WebView,
url: String,
message: String,
result: JsResult
): Boolean {
return false
}
}
I hope it's work for you!

Can I call super within a Listener Lambda in Android-Kotlin?

I am trying to override the download Listener for a WebView so it gets to open websites not belonging to us in an external browser instead of loading them in the webview. Thing is, I'd like to simplify the code into something like this
webView?.setDownloadListener { url, userAgent, contentDisposition, mimetype, contentLength ->
if (!url.contains("mydomain")) {
CLog.v("InternalWebviewFragment.configWebView().setDownloadListener() isNOTmydomain url: $url")
val i = Intent(Intent.ACTION_VIEW, Uri.parse(url))
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
activity?.startActivity(i)
}else{
super(url, userAgent, contentDisposition, mimetype, contentLength)
}
}
However, that call to super there, which I intend to have for urls that do belong to our domain, says that can only be used on the left hand of a dot. When I try to type
super.onDownloadStart
it gives an unresolved reference error.
How could I get the webview Listener to go on business as usual when the url is part of our domain? Is the super call only available in non-lambda methods?
After many tests, #Demigod's approach turned out to be the right one. It just needed the bit of having both deprecated and current methods of shouldOverrideUrlLoading as found here
// APIs up to 23 need this method
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
if (!url.contains("mydomain")) {
// InternalWebviewFragment external (non mydomain) urls will be dispatched to an external browser
CLog.v("InternalWebviewFragment.getSimpleWebViewClientUrlLoading().shouldOverrideUrlLoadingOLD() isNotmydomain url: $url")
val i = Intent(Intent.ACTION_VIEW, Uri.parse(url))
activity?.startActivity(i)
CLog.v("InternalWebviewFragment.getSimpleWebViewClientUrlLoading().shouldOverrideUrlLoadingOLD() isNotmydomain After Intent")
return true //InternalWebviewFragment this avoids the webview to load the url we've just sent to the browser
}
CLog.v("InternalWebviewFragment.getSimpleWebViewClientUrlLoading().shouldOverrideUrlLoadingOLD() ismydomain url: $url")
// mydomain urls should load fine in the webview
view?.loadUrl(url)
return super.shouldOverrideUrlLoading(view, url)
}
// for APIs 24+
override fun shouldOverrideUrlLoading(
view: WebView?,
request: WebResourceRequest?
): Boolean {
if (!request?.url.toString().contains("mydomain")) {
// InternalWebviewFragment external (non mydomain) urls will be dispatched to an external browser
CLog.v("InternalWebviewFragment.getSimpleWebViewClientUrlLoading().shouldOverrideUrlLoading2() isNotmydomain url: ${request?.url.toString()}")
val i = Intent(Intent.ACTION_VIEW, Uri.parse(request?.url.toString()))
activity?.startActivity(i)
CLog.v("InternalWebviewFragment.getSimpleWebViewClientUrlLoading().shouldOverrideUrlLoading2() isNotmydomain After Intent")
return true //InternalWebviewFragment this avoids the webview to load the url we've just sent to the browser
}
CLog.v("InternalWebviewFragment.getSimpleWebViewClientUrlLoading().shouldOverrideUrlLoading() ismydomain url: $url")
// mydomain urls should load fine in the webview
view?.loadUrl(request?.url.toString())
return super.shouldOverrideUrlLoading(view, request)
}

Why is my Android WebView showing me an 403 Forbidden Error

I'm having some trouble getting my webview to work properly
The webview is supposed to display this url https://mcdonalds.de/deinfeedback , but whenever I try to load it my onReceivedHttpError method returns me an
403 Forbidden
Error. It works just fine for other urls like https://www.google.com, but i can't seem to make it work for this one. At first I thought it had something to do with the ssl certificates, however my WebViewClient's onReceiveSslError is never called. I then tried to change my user agent string to the same one I have on my mobile browser but it still returned me the same 403 error
This is the part in my onCreate where I deal with the WebView
webViewDisplay.settings.builtInZoomControls = true
webViewDisplay.settings.displayZoomControls = false
webViewDisplay.settings.domStorageEnabled = true
webViewDisplay.settings.javaScriptEnabled = true
webViewDisplay.settings.javaScriptCanOpenWindowsAutomatically = true
webViewDisplay.webViewClient = MyWebClient()
webViewDisplay.loadUrl(resources.getString(R.string.web_activation_url_main)) //https://www.mcdonalds.de/deinfeedback
And this is my WebViewClient
inner class MyWebClient : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest): Boolean {
Log.v(TAG, "Overriding Url to ${request.url.toString()}")
return false //continues loading
}
override fun onReceivedSslError(view: WebView?, handler: SslErrorHandler, error: SslError?) {
Log.v(TAG, "Ssl Error")
handler.proceed() //handle error
}
override fun onReceivedHttpError(view: WebView?, request: WebResourceRequest?, errorResponse: WebResourceResponse) {
Log.v(TAG, "Http Error ${errorResponse.statusCode} ${errorResponse.reasonPhrase}")
super.onReceivedHttpError(view, request, errorResponse)
}
}
I hope somebody can help me with this
Edit:
The 403 Error was not the issue. I had set the height of my layout to wrap_content which makes the webView wrap itself on some sites. Changing it to match_parent fixed it.
Credit for this goes to Dani
Are you sure its a WebView issue only? Executing this url in a desktop browser getting one 403 - and seeing exactly the same content as I do in android's WebView. In other words, if you are seeing the same, I think you can safely ignore the error. If you are seeing something else, please attach a snapshot.
Edit: Pretty certain now.
Adding:
#RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun onReceivedHttpError(view: WebView?, request: WebResourceRequest?, errorResponse: WebResourceResponse) {
Log.v("APP", "Http Error ${request?.url} ${errorResponse.responseHeaders} ${errorResponse.reasonPhrase}")
super.onReceivedHttpError(view, request, errorResponse)
}
Produces this:
Http Error https://s3-eu-west-1.amazonaws.com/automation.isc-mcd.svy.do--voc/public/de/.json {Transfer-Encoding=chunked, Server=AmazonS3, Access-Control-Allow-Origin=*, Access-Control-Allow-Methods=GET, Vary=Origin, Access-Control-Request-Headers, Access-Control-Request-Method, x-amz-request-id=AC63B0D940D45EDA, Access-Control-Max-Age=3000, x-amz-id-2=7LKt0WZsaKdyYTQhN5cSmGSdUZMBR+D8mEaAOovorrV5jNJcS0CvNFb08K7QqnTkn4C73MfMWJI=, Date=Fri, 03 Jan 2020 03:17:05 GMT, Content-Type=application/xml} Forbidden
Note this is exactly the same request that results in Forbidden in desktop browsers too. No harmful side effects, can be ignored.

Pdf sometimes not loading with google embedded viewer on Android

I am using the google docs pdf embedded viewer in my android app to display my pdfs. Sometimes the viewer doesn't load my file even though most of the time it does and it's pretty random when it doesn't.
I generate the url with "https://docs.google.com/viewer?embedded=true&url=" + myUrl.
And after that I load the webview :
showLoader()
web_view.settings.javaScriptEnabled = true
web_view.clearCache(true)
web_view.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
hideLoader()
}
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
web_view.loadUrl(url)
return true
}
override fun onReceivedSslError(view: WebView, handler: SslErrorHandler, error: SslError) {
println("before handler")
handler.proceed()
println("after handler")
}
}
web_view.loadUrl(url)
I tried to proceed if I encounter any sslError, to override urlLoading but none of this resolved my problem.
To test here is one of the url which doesn't always load :
http://docdif.fr.grpleg.com/general/MEDIAGRP/NP-FT-GT/LE10061AA.pdf
One thing I tried too is show the url when display on my app and when it doesn't load on my viewer it blocks too on my navigator. But if I reload the page it does charge.
Any idea what the bug might be?
Try this:
public void onPageFinished(WebView view, String url) {
if (view.getTitle().equals(""))
view.reload();
}
I hope that it can help you!

How to link multiple HTML pages in web view from assets folder in android?

Getting error **html exposed beyond app through Intent.getData()** when trying to call another HTML file through html link inside web view from local assets folder in android studio.
Below Code might resolve your issue
webView.settings.javaScriptEnabled = true
webView.webViewClient = object : WebViewClient()
{
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
view.loadUrl(url)
return true
}
// From api level 24
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
// Get the mailto url
val url = request.url.toString()
view.loadUrl(url)
// Return true means, leave the current web view and handle the url itself
return true
}
}
webView.loadUrl("file:///android_asset/sample.html")

Categories

Resources