I am working on an android project right now and have a question about how to do callbacks in different webviews. I used JSInterface for my project too. Here I have 2 webviews. One has an index page, anther is a overlay(still a html page though.) What I want to do is if any user clicks on some links on the overlay, it should fire a callback function which is written in the java file where the index page was connected to through JSInterface. It might sound confusing, but I have draw something to help make it clear!
Thanks!
You can use a custom URL scheme like myurl://function for your functionality links. Then write an event handler for the WebView's shouldOverrideUrlLoading event in which you decide how to process the URL: either instruct the webview to load it, or do some custom action.
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url)
{
if (url.startsWith("myurl://"))
{
// Parse further to extract function and do custom action
}
else
{
// Load the page via the webview
view.loadUrl(url);
}
return true;
}
I used startsWith to check the URL for this quick and dirty example, but you should consider using android.net.Uri.parse for parsing URLs.
This should allow you to call the Java function foo() without having to go through the first WebView.
If you want to go through the first webview, then you can call a function on the JSInterface like this (where webView1 is the first WebView retrieved through findViewById):
webView1.loadUrl("javascript:myjsinterface.myjsfunc();")
Related
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.
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.
There is a rather specific webpage loaded into WebView which URL is like http://www.site.com/mob/ (basically a mobile-optimized web page). This webpage display 25 articles only and on the bottom is a button "More articles".
When a user presses it, I catch URL http://www.site.com/Web/MobHomeItems.aspx?page=N (where N is 2, 3, 4...) and after that another 25 items have been loaded on the same screen.
Now, when I click on some article and go to article details, and later return to the page via the Back key, the WebView forgets how many articles have been loaded and simply loads the default page with 25 displayed articles. Imagine how frustrating this would be to a user if he came to 100th article.
I tried overriding many methods in WebClient and in WebChromeClient, but so far I have been unable to load N number of pages loaded via "More Articles" button. For example, I first thought this would help, but it did not.
#Override
public void onLoadResource(WebView view, String url) {
//http://www.site.com/Web/MobHomeItems.aspx?page=2
if (url.contains("?page=")) {
//save this URL for later and on return from
// article details, pass it to LoadResource()
super.onLoadResource(view, url);
}
Then I tried similar approach with other method - basically remembering how many pages have been loaded on the main page, and then on return from article details, simply tell webview to load this URL.
Can anyone help me? How to append loaded pages to the main page? Should I use JavaScript here maybe?
PS. Loading mentioned URL http://www.site.com/Web/MobHomeItems.aspx?page=N does not help as it loads this concrete page into the WebView only, and it does not append this Nth page to the main page.
EDIT
As #Raghunandan asked, I do not have problems loading back to 1st page (?page=1). This is default when user presses Back button on article details. I want to load to the page where a user was before pressing article details. If he was on ?page=100, I want to load back to that page e.g. I want to have 25x100 articles open. Again, default is always "open 25 articles or ?page=1 or http://www.site.com".
Override the method shouldOverrideUrlLoading of WebViewClient.
like this:
public boolean shouldOverrideUrlLoading (WebView view, String url) {
if (url is kind of article detail) {
WebView newOne = new WebView(); // create a new Webview for displaying the details.
view.setVisibility(View.INVISIBLE); // hiding current page (article list)
return true; // To tell the WebView we have process this url.
}
return false;
}
The user click one link of article's detail.
shouldOverriderUrlLoading would be triggered.
We created one new WebView to open the url.
Hiding current page
The user reading artical
The user click back key, close the newOne WebView then make the
previous WebView visible.The article list will show up immediately and remained the old statement
.
There is a another way to do this.
The WebSettings has a private method "setPageCacheCapacity" , the default value is 0 , you could enlarge it (may be 5).
You can access this method by using reflection of java.
The method can enable WebView to cache more than one document. In the other word. when user press the back key, the WebView will go back to the older document.
I have an app with a previously-existing, web-based registration process that I am trying to use inside a WebView. I need to add some style tags to the html in order to hide some elements for better displaying the content inside my app. I can get it to work on initial load, but I cannot figure out how to do it from one page to the next inside the WebView. Here is what I have working:
On initial load of the site, I am getting the raw html and appending "<style>MY STYLES HERE</style>" to the string before calling
wv.loadDataWithBaseURL(url, rawHtml, null, "UTF-8", url);
This works perfectly, but if a user clicks a link on the page and it loads another page into the WebView, then this code does not get called and the style tag is lost.
I assume I need to override "shouldOverrideUrlLoading" in the WebViewClient, but I don't know how to intercept the html from here. I thought I would try something like:
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
String rawHtml = getRawHtml(url) + "<style>...</style>";
wv.loadDataWithBaseURL(url, rawHtml, null, "UTF-8", url);
}
But this obviously sends it into an endless loop of intercepting the load to start a new load.
I have also tried overriding onPageFinished and doing:
wv.loadUrl("javascript:(function() { ... })()");
which works, except that it waits until the entire page is loaded before executing. This causes the page to appear loaded with all of the UI elements in tact, and then all of the ones I am trying to hide suddenly disappear. My ultimate goal is to enhance the look and feel of the site on a mobile device, so this is not an option.
Is there something else I can do in "shouldOverrideUrlLoading" to inject style tags? Or if not, what else can I try?
I've run into this problem, and depending on the number of redirects, etc, we have not been able to make the injected JavaScript available all the time.
At minimum, you should use the wv.loadUrl("javascript:(function() { ... })()"); approach, but call it in both onPageStarted() and onPageFinished().
Depending on the complexity of your pages, you might need to inject the JavaScript in onLoadResource() as well.
I'm making an application that contains button's and those buttons control an embedded browser. My problem is that I want to see the button's and the web page in the same layout, but when i click on a button this will open a web page and don't show the button, can anyone help me?
If I understand correctly your problem is that following a link opens the standard browser not your WebView, right ?
Add this to your WebView to change that behavior
// this is to prevent that when clicking a new URL from the displayed
// page the default web browser launches
webView.setWebViewClient(new WebViewClient() {
#Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
});
You need to use a Layout that supports more than one child. Take a look here