Android blank screen on onBack in a loadDataWithBaseURL - android

Probably it will have a simple solution but I've read many threads here but no way.
In a ListView, if i tap on a row it opens a new Activity. In that activity I make an httpget and I create an html string with what I need from that httpget (a portion of the web page retrieved).
So I simply make a loadDataWithBaseURL("http://base_path.com/", html, mime, encoding, null).
It works as expected and I view the web page with links and images.
Now the problems come... If I tap on an image I see the large image in that windows but once i press the "back" on the phone I see a white page. I know that it is caused by the "null" argument but... what I should put to see the html page again? I tried to put "html" instead of null but I see the html code inside the webview!
This is my onKeyDown to override the back button:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// Check if the key event was the BACK key and if there's history
if ((keyCode == KeyEvent.KEYCODE_BACK) && webView.canGoBack()) {
webView.goBack();
return true;
}
// If it wasn't the BACK key or there's no web page history, bubble up to the default
// system behavior (probably exit the activity)
return super.onKeyDown(keyCode, event);
}

I found some information at this answer:
Android: WebView's method goBack() shows a blank page
You need to provide a URL to back into when you call
loadDataWithBaseURL("http://base_path.com/", html, mime, encoding, null);
You are passing null so defaults to 'about:blank'. Try this instead:
String baseUrl = "http://base_path.com/";
loadDataWithBaseURL(baseUrl, html, mime, encoding, baseUrl + filename);

As a workaround i made the following activities.
removed the onKeyDown function
removed the myWebView.setWebViewClient(new WebViewClient());
In this way the image loads in the default Android browser and i can close it with the back button.
It is not fine to go outside the WebView but i had no other choices.

As Gadgeteer mentioned passing null on loadDataWithBaseURL() will add the 'about:blank' into the stack of webview history.
To avoid this problem, I clear webview history as soon as I call loadDataWithBaseURL() by calling
webview.clearHistory()
as per document
public void clearHistory ()
Tells this WebView to clear its internal back/forward list.
If you call clearHistory() after calling loadDataWithBaseURL() the webview not go back to blank page and canGoBack() also return false; because there is no back stack in the webview after clearHistory()

Try this:
webview.loadUrl("file:///android_asset/your_html.html");
instead of your loadDataWithBaseURL

Related

Crosswalk: how to get URL of non-web resource opened in new tab/window

Let's say my Crosswalk view in my Android activity is showing a page like this:
<html>
<body>
<a target="_blank" href='http://some-website.com/document.pdf'>Download a PDF</a>
</body>
</html>
How can I intercept the URL of that link?
Note that because it is opening the link in a new "window", the callbacks like XWalkResourceClient.shouldOverrideUrlLoading or shouldInterceptLoadRequest are not called, probably because Crosswalk is loading an entirely new document.
There is a callback for window creation, XWalkUIClient.onCreateWindowRequested, but that doesn't contain any parameter that contains the URL that is being loaded in the new window.
I'm also aware that, when a new window is created, the user code can instantiate a new XWalkView to be used to load the destination document, and I should set the custom resource client and UI client.
What I tried so far:
All methods in XWalkResourceClient and XWalkUIClient with a URL parameter, in both the origin and destination views. Either they are not called, or the parameter is null or empty;
In XWalkUIClient.onCreateWindowRequested, return a subclass of XWalkView that overrides load() so it can intercept the url. That method is not called.
Any suggestion is greatly appreciated. Thanks!
I am sure override shouldOverrideUrlLoading will intercept the url in your html.
I did nothing special, and add code like below:
mXWalkView.setResourceClient(new XWalkResourceClient(mXWalkView) {
#Override
public boolean shouldOverrideUrlLoading(XWalkView view, String url) {
Log.i(LOGTAG, "shouldOverrideUrlLoading ");
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
return true;
}
});
And then load the html you provide:
mXWalkView.load("file:///android_asset/download.html", null);
When I click the link in the XWalkView, shouldOverrideUrlLoading will be called and the UI like below,

Android's WebView can't go back in local assets

I have a problem with WebView. My app has build in help files made with html in local assets. And I show html file with WebView.
My problem is, WebView's goBack() function can't go back to previous page when it tries to return to bookmarked position.
For example:
Page1 has link to bookmark1 in Page1.
And Page1 has link to Page2.
Showing Page1 and hit link to Page2, then goBack() can go back to Page1. Fine.
Showing Page1 and hit link to bookmark1, and then hit link to Page2, then goBack() can't go back to page1. WebView shows error like it can't find url with #bookmark1.
I suspect WebView is not handing viewing history for local files. I'm using OS 4.0.3.
Any solutions?
I have found a (compromising) solution for this issue. This issue was discussed here and one solution can be found here (Japanese page, sorry). In my case, after knowing it's a bug in some range of Android OS, going back to previous page (not to exact anchor position) is fine. So I ended up with next code.
webView = (WebView)findViewById(R.id.webview);
webView.setWebViewClient(new WebViewClient()
{
// https://stackoverflow.com/questions/6542702/basic-internal-links-dont-work-in-honeycomb-app
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
{
super.onReceivedError(view, errorCode, description, failingUrl);
String url = failingUrl;
int index = url.indexOf("#");
if (index != -1)
{
url = url.substring(0, index);
}
webView.loadUrl(url);
}
});
With this code when it can't go back to previous page with anchor, it goes back to previous page without anchor. I compromised with it. I tried to make it better with other solutions using Java Script but did not work.

How to load this URL into WebView?

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.

Inject Content into WebView Before Loading Url

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.

How to handle callbacks in webview

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();")

Categories

Resources