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
Related
I am using a webview to submit a form and redirect. When the form is submitted successfully it will print a json response to the console.
My question is how can I get the jsonData String from the client?
chromium: [INFO:CONSOLE(1)] "Callback....jsonData, etc"
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Insert your code here
return true;
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
});
You could extend the WebViewClient class and create a method to intercept the POST request made from clicking the form post button in the HTML in your WebView. Then, make the HTTP POST request in the code, rather than in the WebView and parse the results anyway you wish, then refresh the WebView any way you wish at the end of it all. There is an example of doing so here:
https://github.com/KeejOow/android-post-webview/blob/master/PostWebview/postwebview/src/main/java/com/solidsoftware/postwebview/InterceptingWebViewClient.java
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 add authorization headers in every request in WebView. I can override shouldOverrideUrlLoading method for GET request, but I can't get POST request to work. I have tried many answer from this site, and none of them works. Is there a proper way to do this?
Edit:
For GET Request I use:
webView.setWebViewClient(new WebViewClient() {
#Override
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
view.loadUrl(request.getUrl().toString(), getHeader());
return true;
}
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url, getHeader());
return true;
}
}
I used WebViewClient.shouldInterceptRequest() to intercept POST request. But somehow the request I create became GET.
Is there a way if I can check status code for the url I load into a webview?
I want to check if the url has anymore redirects, and if not I want to execute a piece of code.
Iam implementing the WebViewClient and I want to execute a code in the onPageFinished();
EDIT: The url I load is a login screen. I want to check if the user has successfully logged in.
How can I achieve this?
webView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.isEmpty()){
// do your stuff as you want.
}
return true;
}
public void onPageFinished(WebView view, String url) {
// do your stuff as you want
}
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
}
});
Use HttpURLConnection class.
URL url = new URL("http://example.com");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.connect();
int code = connection.getResponseCode();
There you have the http code returned.
Hope this helps.
Try this
public void evaluateJavascript (String script, ValueCallback<String> resultCallback)
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.