Intercept and Change Request Location in Android WebView - android

After looking around, I am unable to find an easy way to intercept requests made by the WebView and change the URL.
For example, I would like requests *.melange to actually route to localhost:8080 while keeping the original URL as the Host header.
It appears, at first glance, that the easiest method to achieve this sort of URL rewriting would be to use the "new" (API Level 21 or higher) shouldInterceptRequest, copy the values out of the WebResourceRequest to make the HTTP request manually then return a WebResourceResponse with the correct values. In my mind, there "should" be an easier way to do this.
Please let me know if I am missing something obvious. Thanks!

private class MyWebviewclient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.contains("melange"){
String newUrl = "http://localhost:8080"+url.split("melange")[1];
loadUrl(newUrl);
}
return false;
}
}
Now,
yourWebView.setWebViewClient(new MyWebviewclient());

Related

How to set webviewClient for webView dynamically?

For instance, there is a WebView component in my fragment. I use it to load all webpages by the different urls, sort of stupid but efficient. As you know, we specify our webviewclient (like WvjbWebViewClient or jsBridge) to handle all requests. Now that we want to load third-platform websites with our WebView sometimes, however, we don't want to supply our business function for them, not for anything else, but for our safety of communication.
Our company domain is xxx.com. What I want to do is: when the webview loads those webpages on this domain, use our customer WebViewClient, otherwise use a simple WebViewClient(new a instance). How to resolve it? (Should we consider url redirection?)
WebViewClient allows you to upload any specified URL, selected in the WebView, in WebView itself, and do not run the browser. For this functionality meets shouldOverrideUrlLoading(WebView, String) method. If it returns true - we do not need to launch a third-party browser, and upload their own content here.
Here is an example where we choose if we can open the content in our app, or we need to open browser:
public class MyWebViewClient extends WebViewClient {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(Uri.parse(url).getHost().endsWith("xxx.com")) {
return false;
}
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
view.getContext().startActivity(intent);
return true;
}
}
This can help if think.

Is shouldOverrideUrlLoading called for links within the same domain?

I have a hybrid application where I have a WebView which is implementing the shouldOverrideUrlLoading method (both the deprecated and the newest version). This should take over control before loading any external links or certain links within my domain. Without going into specifics, the code looks roughtly like this:
private WebView mWebView;
mWebView.setWebViewClient(new myWebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if(url.isExternal() || url.contains("#specialCase")) {
// Do actions
return true;
}
return super.shouldOverrideUrlLoading(view, url);
}
});
I have noticed that all external links work properly, however shouldOverrideUrlLoading is not being called at all when the link is within my domain, so there is no way for me to detect those cases where I want to take over control.
The android documentation states
Give the host application a chance to take over the control when a new
url is about to be loaded in the current WebView.
Does that new mean different domain? Is there anything I am missing or doing wrong? Any ideas on how to detect the user has clicked a link pointing to the same domain?
Thank you in advance.
Finally found the reason why shouldOverrideUrlLoading was never been called.
Apparently the method is only called when the actual loading is about to start. Our web application is a single-page application, hence even though the URL changes, no new page is loaded and shouldOverrideUrlLoading is not called.

Adding custom header to all requests in shouldInterceptRequest Android webview

I want to add custom Headers to requests in the webview. I think it should be possible to do it in shouldInterceptRequest.. Since my minimum API level is less than 21 shouldInterceptRequest (final WebView view, final String url) is also called and therefore I need to add headers here as well but I am not sure how.
#Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
request.getRequestHeaders().put("ClientId", "ANDROID");
request.getRequestHeaders().put("Tokon", token);
}
return super.shouldInterceptRequest(view, request);
}
#Override
public WebResourceResponse shouldInterceptRequest(final WebView view, final String url) {
// I need to updated the header here
return super.shouldInterceptRequest(view, url);
}
There is a suggestion to use view.loadUrl(url,headers) but this does not work either.
The difficulty you run into with pre API 21 is the shouldInterceptRequest only provides the intercepted URL and the webview without the body of the request. I ran into this same issue and discovered the following GitHub repository
https://github.com/KeejOow/android-post-webview
The important part of this project is interceptheader.html in the assets folder. This html contains javascript that is inserted at the top of every html response the webview loads. This JS intercepts every form and ajax submission from the page and loads the body data into a java class. Next the shouldInterceptRequest method determines whether the request is POST or GET (you only get those two, unfortunately) based on whether there is any data in the body.
Finally, once it has marshalled all the relevant information, it performs the request by itself (instead of passing it off to Android), returning the resulting WebResourceResponse.
Be warned that the repository has seen some aging. I had to do some fiddling to get pages to work as I wanted them.
The best place to add your headers is in the InterceptingWebViewClient class under shouldInterceptRequest.
conn.setRequestProperty("header-name", value);

Android WebView: Should shouldInterceptRequest be triggered by XmlHttpRequest

I'm trying to integrate a javascript plugin that loads some resources by using XmlHttpRequest calls. I want this script to run within a locally loaded page in WebView. As you might have guessed already, XmlHttpRequest calls are not allowed for local resources, so I promptly get the following error:
XMLHttpRequest cannot load file:///android_asset/resources.html. Cross
origin requests are only supported for HTTP.
At this point I thought that I could emulate the web server by intercepting the calls and then just loading the file myself, such as:
webView.setWebViewClient(new WebViewClient() {
#Override
public WebResourceResponse shouldInterceptRequest(final WebView view, String url) {
try {
if (url.contains("resources.html")) { //breakpoint here is not triggering
return new WebResourceResponse("text/html", "UTF-8", getAssets().open("resources.html"));
}
} catch (IOException e) {
return super.shouldInterceptRequest(view, url);
}
return super.shouldInterceptRequest(view, url);
}
});
The problem is that shouldInterceptRequest is not being called. The official documentation is very brief and doesn't specify what type of requests are intercepted. This article sort of implies that the method does intercept XmlHttpRequest calls, but it doesn't appear to be working.
Does anyone know if shouldInterceptRequest should be called after a XmlHttpRequest? If not, is there another way to do this? Thanks
In API level 16 WebSettings added methods setAllowFileAccessFromFileURLs() and setAllowUniversalAccessFromFileURLs(). Setting this to true for the webView might solve your problem.
As my testing on this, it seems that only external requests would be intercepted - you can try to modify the local references to be external as "http://foo.com/..." (instead of "file:///android_asset/...").

An alternative to Android's webview

Does anyone knows an alternative to Android's webview component ? For some reasons, it's functionality's are insufficient for me : I need to be able to catch every single request to some url, when i'm browsing a wml page (wap). Anyway, I need to be able to do stuff that Android's webview is not made for.
I thought "hey, let's play with the source code, I'm pretty sure that webviews are using apache.org librairies to access internet".
Oh boy was I mistaken. Webviews use native code, and that's where I'm stuck.
So I was wondering if anyone knew of another web browser view, in pure java, that would be open source and nice. It's not a problem if it's slow, i'm displaying some basic wap pages...
Thanks in advance.
You can extend WebView's functionality by using setWebViewClient & setWebChromeClient.
WebView.setWebViewClient(new MyWebViewClient());
WebView.setWebChromeClient(new WebChromeClient() {..}
You can handle each and every request sent/received from the WebView by overriding the below methods:
public boolean shouldOverrideUrlLoading(WebView view, String url) {..}
public void onPageStarted(WebView view, String url, Bitmap favicon) {..}
public void onPageFinished(WebView view, String url) {..}
The crosswalk project: https://crosswalk-project.org/ might be what you need. But beware, there are places where it differs from the stock webview. In some ways better, in some ways worse. For example, it supports WebGL (good), but currently the background cannot be transparent (bad). The really good news, it seems to be very actively supported, running it's own Jira to track and fix and Intel seems to be very involved.
Try to see how was Opera Mini programmed.
But I think you must program it if you want another one . But i would be surprised if it has a nice performance.
Try this:
goButton4.setOnClickListener(new OnClickListener() {
public void onClick(View view) {
Uri uri = Uri.parse("http://tory.com/");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
});

Categories

Resources