Android Webview, working with Anchors - java

I am loading a webpage into a webview from the database with the loadDataWithBaseURL() function and am trying to subsequently jump to an Anchor point. When I place a button just below the webview that uses the loadUrl()-function, it jumps to the Anchor point just fine. But if I place the loadUrl() after the loadDataWithBaseURL() it says page not found.
webview.loadDataWithBaseURL("app:myhtml", data, "text/html", "UTF-8", null);
webview.loadUrl("app:myhtml#tips");
I assumed it was because the load had not completed, and thus it couldn't find the Anchor, but I tried a loop to wait for it to getProgress() to equal 100, and have verified it's reaching 100 before that command executes, but it still won't find the page unless it's associated with the button click.
Any Ideas out there on how I can load a page from the database and then jump to an anchor point at the same time. I'm working with the Android 2.1 SDK.
Thanks to your help I got it to load directly to my anchor by adding this little bit of code. However I can't scroll around on the page, it starts to move and then snaps back. I suspect because it is reloading the page to that anchor each time. I'm fairly new to Android, and Java even, so this may be the wrong implementation of your suggestion, but I'd certainly appreciate a little more direction. Here is the code I used:
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(webview, "app://data");
webview.loadUrl("app://data#tips");
}
});
It seems this is making an infinite loop.

Try using valid URL as a base URL in loadDataWithBaseURL(), such as app://myhtml.
Also, to make sure the data was loaded implement WebViewCLient.onPageFinished().

It was getting in an infinite onPageFinished loop before. It had nothing to do with me scrolling, it was just continuously loading the same page. This code allows it to load without without getting stuck in a loop.
webview.setWebViewClient(new WebViewClient() {
#Override
public void onPageFinished(WebView view, String url) {
if(url.contains("#") != true){
webview.loadUrl("app://data#tips");
}
}
});

Related

How do I get access to the html contents of a popup displayed in a webview?

My application needs to retrieve data from a web site.
I use a webview to access the required page. In the page displayed in this webview there are links leading to the detailed info that the app needs. When following a link (using the webView.loadUrl()) a popup is displayed on top of the webview.
The app gets access to the links with the following code:
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new BackgroundScriptInterface(), "HTMLOUT");
webView.setWebViewClient(new WebViewClient(){
#Override
public void onPageFinished(WebView view, String url)
{
webView.loadUrl("javascript:window.HTMLOUT.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
}
});
and
public class BackgroundScriptInterface {
#JavascriptInterface
public void processHTML(String html) {
...
}
But this BackgroundScriptInterface is not called when a popup displays.
How do I get access to the html contents of the popup?
EDIT
As suggested by Eddie below, I've tried
webView.evaluateJavascript(item.competDetailUrl, new ValueCallback<String>() {
#Override
public void onReceiveValue(String s) {
Log.d("competDetail", s);
}
});
The popup is still displayed as expected. However the value passed to the onReceiveValue callback is "null".
Try using webView.evaluateJavascript() instead of webView.loadUrl(), unless you need to work with pre-Kitkat devices
Reference:
Android Calling JavaScript functions in WebView
The info the app retrieves from that site do not need to be displayed on the UI. They are parsed and used in the app logic. Hence I have designed the following work-around: I have replaced the original javascript:apex.navigation.dialog() by a javascript:apex.navigation.redirect() that displays the requested info directly into the webview instead of into a popup window.
As the info now comes into the webview, it can be accessed by the above BackgroundScriptInterface.

Android Studio Webview (Java) - Is there a way to wait until a loading inside a web page is finished before loading url?

I'm trying to get some elements in a web page using webView.loadUrl(...);.
However, I found out that there is a loading that "creates" these elements after the page is already loaded. So, I didn't find a way to get these.
I tried to use onPageFinished but it doesn't look like it is called when the loading inside the web page finishes.
I also tried to put a button that triggers the webView.loadUrl(...);. This tip only works if the user doesn't click too fast on the button, because then the loading doesn't have the time to finish before.
Here is a video of the page booting up, hoping for you to better understand what I mean by a loading inside the page :
https://www.youtube.com/watch?v=q1267dcJai8&feature=youtu.be
If I haven't been clear enough, I'd be happy to clarify things further.
Thank you in advance!
Edit : To clarify something, I'm not exactly asking for a way to get these elements. A way to delay the webView.loadUrl(...); while the webpage is loading would also be perfect for me.
Try onProgressChanged() of WebChromeClient like below.
Documentation link:
https://developer.android.com/reference/android/webkit/WebChromeClient#onProgressChanged(android.webkit.WebView,%20int)
#Override
public void onProgressChanged(WebView view, final int newProgress) {
super.onProgressChanged(view, newProgress);
if (newProgress == 100) {
//Page load done
}
else
{
//Page is still loading wait...
}
}

webpage takes a lot of time to load

In a webview in Android, I first load a webpage and then display only a part of it using some javascript commands. During the whole process a "loading" message is displayed.
Problem : It take s alot of time to load even if the internet speed is fast. (>60 sec always). How to reduce time ?
This is my WebViewClient class that I attach with the webview (and the class contains only 1 method):
#Override
public void onPageFinished(WebView view, String url){
view.loadUrl("javascript:document.getElementsByClassName('menu')[0].innerHTML=''");
view.loadUrl("javascript:document.getElementsByClassName('gbh')[0].innerHTML=''");
view.loadUrl("javascript:document.getElementsByClassName('input')[0].innerHTML=''");
view.loadUrl("javascript:document.getElementsByClassName('card_title')[0].innerHTML=''");
view.loadUrl("javascript:document.getElementsByClassName('cell_input')[0].innerHTML=''");
view.loadUrl("javascript:document.getElementsByName('pre')[0].innerHTML=''");
view.loadUrl("javascript:document.getElementById('footer').innerHTML=''");
view.loadUrl("javascript:document.getElementsByClassName('foot')[0].innerHTML=''");
}
Sir, You could use the YSlow or Google PageLoad plugins for your browser, to get specific tips on how to improve page load and speed up your page.
By default, a WebView provides no browser-like widgets, it does not enable JavaScript and also web page errors are ignored.

Android WebView with Javascript calls behaving oddly

I understand how to call Javascript from my WebView, that isn't the issue.
if(javascriptCall!=null){
String hardCodedexample = "1959602";
webView.loadUrl("http://myappexample+ username);
webView.loadUrl("javascript:" + "window.application.relocateTo({location:'patients/details',params:{EMPIID:"+ hardCodedEMPIID +"}})");
}
javascriptCall is a String which is passed to my webview activity. hardCodedEMPIID is just an example for our testing. My problem is that when I allow the app the run normally on the device my javascript method doesn't seem to work. It loads the myappexample and I can't tell what happened with my javascript call.
When I debug the app and single step through the code it properly calls the method. I'm confused on how this is possible? the different between single step and normal execution.
You should wait for onPageFinished(WebView view, String url) event called by WebViewClient (http://developer.android.com/reference/android/webkit/WebViewClient.html#onPageFinished(android.webkit.WebView, java.lang.String) ) . JavaScript file with your function might not be loaded right away after calling loadUrl.

How to clear the (CSS) visited history of an Android WebView?

I try to reuse an existing WebView by clearing any private data the previous user left behind:
CookieManager.getInstance().removeAllCookie();
webview.clearHistory();
webview.clearFormData();
webview.clearCache(true);
clearHistory seems only to clear the back/forward list, accessible via API, but not the internal list used for coloring links inside the web content.
I even tried the following, suggested by another stackoverflow answer:
deleteDatabase("webview.db");
deleteDatabase("webviewCache.db");
I still have no luck: CSS :visited selectors still work after reloading the page.
An alternative would be to use the API level 11 private browsing feature (new constructor argument), but then I cannot benefit from visited links at all; and can no longer target older versions.
Maybe someone has a solution for this issue? Thanks for your help.
Summary of the answers I got so far:
I tried these two answers, but the first seems to clear HTML5 data storage and the latter seems to be specific to the built-in browser:
WebStorage.getInstance().deleteAllData();
Browser.clearHistory(getContentResolver());
WebChromeClient.getVisitedHistory(ValueCallback<String[]> callback) is only called after the first time I create a new WebView in a recently installed application.
I tried to remove the WebView from view hierachy and create a new one, but unfortunately the visited history seems to be stored for the whole application.
Override WebChromeClient and WebViewClient... Damn that was hidden.
I actually had to dig up a bit to find this out.
WebView webView = (WebView)findViewById(R.id.myWebView);
WebChromeClient myWebChromeClient = new WebChromeClient(){
#Override
public void getVisitedHistory(ValueCallback<String[]> callback) {
// called during webview initialization, original implementation does strictly nothing
// and defaults to the native method WebViewCore.nativeProvideVisitedHistory()
String[] myUserHistory = getVisitedUrlsFromMyOwnDatabase(userId);
callback.onReceiveValue(myUserHistory);
}
};
WebViewClient myWebViewClient = new WebViewClient(){
#Override
public void doUpdateVisitedHistory(WebView view, String url,
boolean isReload) {
// called whenever there is a new link being visited
insertIfNotExistVisitedUrlIntoMyOwnDatabaseForUser(userId);
super(view, url, isReload);
}
}
webView.setWebViewClient(myWebViewClient);
webView.setChromeClient(myWebChromeClient);
webView.getSettings().etc(whatever)...
I think I'm "almost there". Here's the part I managed: what it does so far is remove css history altogether, so we're halfway there. I can't get the browser to recognize the url format I'm providing in "myUserHistory", so in effect the only feature this code does is reset css history altogether, but it's only called once when the WebView is instanciated (or created, didn't check), so for a true multiuser experience you'd need to recreate the webview at each login.
My problem now is that I can't manage to load the urlHistory properly. My Honeycomb Xoom webview seems to ignore my data.
Ah well, I hope it works for you. For me just calling callback.onReceiveValue(new String[]{}); in getVisitedHistory() will be good enough.
EDIT:
I just put twenty more minutes into it because I'm curious. This method is what delegates to the WebChromeClient (mCallbackProxy = WebChromeClient).
protected void populateVisitedLinks() {
ValueCallback callback = new ValueCallback<String[]>() {
public void onReceiveValue(String[] value) {
sendMessage(EventHub.POPULATE_VISITED_LINKS, (Object)value);
}
};
mCallbackProxy.getVisitedHistory(callback);
}
It's protected in WebViewCore, which is a private attribute of WebView with no accessor. The sendMessage delegates to EventHub which is private, and WebViewCore is filled with private native methods, and one of these seems to be the one actually calling the populateVisitedLinks() method during the initialization.
Unless someone at Google adds a public method to WebView to trigger the repopulation, I'm afraid it's practically impossible to achieve your goal. Sorry :(
As a side note, all these native visited history handling really makes me wonder: why do hardware manufacturers care so much about which urls we visited? ;) <<< sarcasm
As an alternate solution, you could try adding your own CSS with the same base colors the default CSS has and switch the CSS by another one (with same color for both "types" of links) when you want to reset the visited links.
A:link{color: "#990000"; text-decoration: none;}
A:visited{color: "#990000"; text-decoration: none;}
A:hover{color: "#ff0000"; text-decoration: none;}
If you can obtain a Browser instance (maybe you can set a WebChromeClient to WebView) you can use its clearHistory() method.
Does WebStorage.clearAllData() have the desired effect? Unfortunately, the documentation on this class is very sparse compared to WebView and doesn't say whether it applies to WebViews.
The exact time you're calling clearHistory() may also have an effect. Clearing it and then navigating to a new page may still keep the first page in history, and you have to call the method after the new page has loaded.
Personally, if privacy is a real issue, I would create a new set of objects from scratch for this new session if possible.

Categories