I usualy use shouldOverrideUrlLoading to block ads in webview, but this time, the ads links in a new website doesn't captured in
public boolean shouldOverrideUrlLoading(WebView view, String url)
and
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
but it captured in
public WebResourceResponse shouldInterceptRequest(final WebView view, String url)
so, i used this method
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public WebResourceResponse shouldInterceptRequest(final WebView view, String url) {
Log.d("soidfzs", url);
WebResourceResponse webResourceResponse = null;
if (url.contains("https://googleads") || url.contains("doubleclick") || url.contains("google-analytics.com") || url.contains("adservice") || url.contains("securepubads")) {
Log.d("soidfzs", "here");
return webResourceResponse;
} else {
return super.shouldInterceptRequest(view, url);
}
}
but, links still loading and ads showing
So, what should i return ?
You are returning webResourceResponse which you set to null prior to your if statement where you check whether the request might be for an ad.
The documentation for shouldInterceptRequest however states:
* #return A {#link android.webkit.WebResourceResponse} containing the
* response information or {#code null} if the WebView should load the
* resource itself.
So in returning null, you are telling the WebViewClient to load the resource itself, i.e., fulfil the ad request and load the ad.
In order to let the request slide and return your own value, you have to return your own WebResourceResponse instance which must not be null for this to work.
return new WebResourceResponse(
"text/html",
"UTF-8",
null
);
Here, I set the mimeType (first argument) to "text/html", although it could probably also be something else, like "text/plain".
I set the second argument—encoding—to "UTF-8"(same as before: could probably be something else).
And now for the most important part: I set data, the third argument, to null.
This results in the WebView getting a valid WebResourceResponse instance which is not null but has no data which in turn results in nothing loading.
Be aware that this will trigger WebViewClient#onReceivedError as the WebView client essentially couldn’t load anything. This is not a problem per se, but something to look out for in case you override onReceivedError.
Related
I am trying to parse every click event, intercept the http url that attempts to load into the webview, and decide if it should be shown depending on a set of logic as per how the url parses. I have followed the advice on these 3 StackOverflow links:
1) Intercept and override HTTP requests from WebView
2) Android Web-View shouldOverrideUrlLoading() Deprecated.(Alternative)
3) https://stackoverflow.com/a/32711309/2480714
without it fixing my issue. The main issue is that a user clicks on the webview to load a hyperlink and it is seems like the shouldOverrideUrlLoading method is not being called or is not intercepting the url properly every time.
I created my Custom WebViewClient and overrode it first with the intent of stopping all loads without my approval, but I have run into a snag; some urls are loading and bypassing my override methods and some are not. I have no clue why this is happening.
Here is my WebviewClient class:
public class CustomWebViewClient2 extends WebViewClient {
public CustomWebViewClient2(){
}
#Override
public void onPageFinished(WebView view, String url) {
Log.d("log", "(CustomWebViewClient) onPageFinished, URL == " + url);
}
#SuppressLint("NewApi")
#Nullable
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
Log.d("log", "shouldInterceptRequest hit");
return null;
}
#Nullable
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
Log.d("log", "shouldInterceptRequest hit");
return null;
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
Log.d("log", "(CustomWebViewClient) shouldOverrideUrlLoading");
return true;
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
Log.d("log", "(CustomWebViewClient) shouldOverrideUrlLoading");
return true;
}
#Override
public void onLoadResource(WebView view, String url) {
Log.d("log", "intercepting onLoadResource, url == " + url);
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
Log.d("log", "onPageStarted url == " + url);
}
}
As you can see, it is overriding the correct methods and should (in theory) never load a URL unless I pass it to the webview to load, but unfortunately some websites are loading, and others are not.
I also tried disabling the cache as per this comment in one of the answers:
"A word of CAUTION! If you intercept an attempt by the browser to
retrieve an image (or probably any resource) and then return null
(meaning let the WebView continue retrieving the image), any future
requests to this resource might just go to the cache and will NOT
trigger shouldInterceptRequest(). If you want to intercept EVERY image
request, you need to disable the cache or (what I did) call
WebView.clearCache(true)"
but to no avail. Why are some URLs loading in and bypassing the override, but others are not?
Update 1: Here is a sample URL https://cookpad.com/us that mirrors the issue I am referring to. It seems to be related to Turbolinks being implemented on the server-side.
I'm trying to get a POST response of a request in WebView. Here are my codes.
mWebview.setWebViewClient(new WebViewClient() {
#Override
public WebResourceResponse shouldInterceptRequest (final WebView view, String url) {
WebResourceResponse w = super.shouldInterceptRequest(view, url);
Log.i("type", w.getMimeType());
return super.shouldInterceptRequest(view, url);
}
});
But the program crashes and the error is w is null. Could anyone tell me why is that or give me any solution to get a POST response of a request in WebView?
Thank you.
shouldInterceptRequest() return null, means that no one intercept the request, and the webview will load the origin URL.
if you want to intercept the request, you should make your own WebResourceResponse with the information from the URL param.
In the documentation, it states that "If the return value is null, the WebView will continue to load the resource as usual.". In the case that something should intercept the request, the response is returned by the override method.
https://developer.android.com/reference/android/webkit/WebViewClient.html#shouldInterceptRequest(android.webkit.WebView, android.webkit.WebResourceRequest)
In my android app I am connecting to a secure site where my login credentials are contained in custom headers. I am able to log in successfully because the custom headers are sent with the new page request.
Based on my custom header information there is specific page functionality which is enabled for my device. The problem is that when I load resources from the home page after login the custom headers that I specify in the webview.LoadUrl(); are not sent. So the end result is that I can log in but do not receive the special functionality that is associated with my device.
I have tried both of these overrides. shouldOverrideUrlLoading seems to work when changing URL's but shouldInterceptRequest does not seem to get called on resource requests? If it is my implementation does not work?
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
request.getRequestHeaders().putAll(getExtraHeaders());
return super.shouldInterceptRequest(view, request);
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url, getExtraHeaders());
return false;
}
See if this works a little better for you:
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.post(new Runnable() {
#Override
public void run() {
view.loadUrl(url, getExtraHeaders());
}
});
// true means: yes, we are overriding the loading of this url
return true;
}
This additional code is just a suggestion/outline and should not be taken as cut/paste ready code
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
String mimetype;
String encoding;
Map<String, String> headers = new HashMap<>();
headers.putAll(request.getRequestHeaders());
headers.putAll(getExtraHeaders());
URL url = request.getUrl().toString();
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
for (String key : headers.keySet()) {
conn.setRequestProperty(k, headers.get(k));
// TODO look for the mimetype and encoding header information and set mimetype and encoding
}
return new WebResourceResponse(mimetype, encoding, conn.getInputStream());
// return null here if you decide to let the webview load the resource
}
Maybe try a different approach, store whatever your need in a cookie for your host using WebKit's CookieManager and use the request's cookie header instead of your custom headers
It is possible to measure the load time of all the resources of a webview?
For example for loading the complete web, I use:
public void onPageStarted(WebView view, String url, Bitmap favicon) {
startingTime = System.currentTimeMillis();
super.onPageStarted(view, url, favicon);
}
public void onPageFinished(WebView view, String url) {
timeElapsed = System.currentTimeMillis() - startingTime;
super.onPageFinished(view, url);
}
but to measure the load of CSS, images, etc. I use
public HashMap<String, Long> resources = new HashMap<String, Long>();
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request){
resources.put(request.getUrl().toString(), System.currentTimeMillis());
WebResourceResponse response = super.shouldInterceptRequest(view, request);
return response;
}
public void onLoadResource(WebView view, String url) {
if(resources.containsKey(url)){
Long timeStartResource = resources.get(url);
Long timeElapseResource = System.currentTimeMillis() - timeStartResource;
}
super.onLoadResource(view, url);
}
I thought the onLoadResource method is executed when the resource was loaded but according to documentation
public void onLoadResource (WebView view, String url).
Notify the host application that the WebView will load the resource specified by the given url.
And
public WebResourceResponse shouldInterceptRequest (WebView view, WebResourceRequest request)
Notify the host application of a resource request and allow the application to return the data. If the return value is null, the WebView will continue to load the resource as usual. Otherwise, the return response and data will be used.
Both they run before loading the resource. Is there any way to measure these times?
There is a great HTML5 API for that accessible to your page. See http://www.sitepoint.com/introduction-resource-timing-api/
Starting from KitKat, WebView is based on Chromium, which supports this API. To check that, open remote web debugging for your app (assuming that you have enabled JavaScript for your WebView), and try evaluating in console:
window.performance.getEntriesByType('resource')
You will get an array of PerformanceResourceTiming objects for each resource your page has loaded.
In order to transport your information to Java side, you can use an injected Java object.
That you can done using onPageFinished() and answer of this question is already given description here.
I have some logic I want my WebView to apply whenever I try to change its url. For links within loaded pages it's fine, I can just do it by using shouldOverrideUrlLoading method on my custom WebViewClient.
But when I explicitly call loadUrl on my WebView, shouldOverrideUrlLoading is not fired (obviously, or it would produce an endless loop when calling loadUrl from within this method).
Is there a way to "preload" a url manually so the shouldOverrideUrlLoading method is called?
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.startsWith("myapp://")
{
//Do something
}
else {
view.loadUrl(url);
}
return true;
}
This works fine when I click a link from within the rendered page. But if I call:
mWebView.loadUrl("myapp://whatever");
shouldOverrideUrlLoading() is not called. What I am asking is whether there's a way that I can pass a url to my webView so it gets passed through to shouldOVerrideUrlLoading() before actually loading it. (i.e. shouldOVerrideUrlLoading() is called whenever a new url is about to be loaded. That's the event I want to fire)
REF: Android's official WebView documentation
if your app version greater then 'N' you should use this function
shouldOverrideUrlLoading(WebView view, WebResourceRequest request)
check you function and version
If all you're trying to do is re-use your logic, just extract it into your WebViewClient and use that to load the url and then just delegate to this in shouldOverrideUrlLoading():
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return loadUrl(view, url);
}
public boolean loadUrl(WebView view, String url) {
if(url.startsWith("myapp://")
{
//Do something
}
else {
view.loadUrl(url);
}
return true;
}
Then instead of
mWebView.loadUrl("myapp://whatever");
You do:
mWebViewClient.loadUrl(mWebView, "myapp://whatever");