How to completely reset Android webview before load new request - android

I am using Android WebView to load some webpages. In my case, I have to insert some JavaScript codes before loaded webpages. Just like below:
//enable javascript
mWebView.getSettings().setJavaScriptEnabled(true);
//inject my js first.
//I can't inject the js onPageStarted() or onPageFinished() because I need to make sure the js
//is injected before html loaded.
mWebView.loadUrl("javascript:MyJsCode");
//load HTML
mWebView.loadUrl("http://example.com/demos/index.html");
The code works fine first time, but failed when run it more than one time. Because the HTML can't find my JS.
I think because the previous HTML is not clear completely, so mWebView.loadUrl("javascript:MyJsCode") inject MyJsCode to previous HTML instead of the new HTML.
So I thought if I could completely reset the WebView(to clear the previous HTML), will solve my issue.
I tried WebView.ClearView(), loadUrl("about:blank"), they all doesn't work.
Anyone suggestion?

Though this is a a tiny bit late, I offer the following. Perhaps it may be helpful . . .
Your question does not specifically mention using any of the callbacks in the WebChromeClient, but you do mention JS, so the following may help. In SDK level 16 and below, you can use the callbacks without specifically "clearing" them. However, starting with SDK level 17, I observe that you must act to clear the events -- specifically alert(), which, of course, results in onJSAlert() being fired in your WebChromeClient if you override it. In all the devices I have tested at SDK level 16 and below, you may blithely ignore the callback, and all will go to plan.
However, you will note that onJSAlert, when overridden, delivers a JSResult object in the last parameter, thus:
boolean onJsAlert(WebView view, String url, String message, JsResult result)
I observe that the JsResult object has two methods exposed, thus:
Public Methods
final void cancel()
Handle the result if the user cancelled the dialog.
final void confirm()
Handle a confirmation response from the user
Assuming that one returns true in the callback (indicating that the callback consumed the onJsAlert event), and assuming that you are using SDK 16 or before, then WebView.destroy() will do the expected things.
I observe, however, that SDK 17 (4.2.x) seems to want some further proof that the callback did, in face, handle the event. Failing to call result.cancel() or result.confirm(), will leave your WebView (or, more to the point, the WebViewCore) stuck permanently. Nothing I have tried will reawaken the WebViewCore, and, thereafter, nothing will load in any WebView, new or otherwise. (Attempted explanation: WebView is merely a wrapper class for WebViewProvider, which, in turn instruments a WebViewCore object. It's that last fellow, WebViewCore, that does all the work. Through wandering the source code, and through reflection, you can burrow your way into that object, if you are keen to do so. WebViewCore is a static, thus, there is exactly one WebViewCore for the whole of your application. Ergo, if your one-and-only WebViewCore gets stuck, no WebView in your application will work thereafter. Once it is stuck waiting, for example, for a JSResult method to be called, it will be stuck until the application is destroyed (i.e. even pausing/resuming the app has zero effect). Even calling destroy() on the WebViewCore directly, through access gained through reflection is ineffective. N.B. Calling destroy() on the WebView has the side-effect of calling destroy() on the WebViewCore but that, too, does nothing helpful).
So, the symptom is that
you create a WebView
some clever JS runs, perhaps calling alert()
you handle the alert() in your onJsAlert override method
you fail to call either result.confirm() or result.cancel()
you destroy the WebView
thereafter, no WebView in your application will load anything.
The good news is that if you are sure to "clear" the events in whatever callbacks you override by invoking the appropriate JsResult method, then the WebViewCore will not permanently stop, and your application will be happy.

I think there is no way to do this except re-new a WebView.

Related

what is relation between android WebView and WebViewClassic

I am having a problem in copy-paste on long click on text inside my class extending Android WebView.
I'm able to copy, but paste is not working.
While investigating, somewhere on net got suggestion to look into android.webkit.WebViewClassic.
In WebViewClassic, there's a method named pasteFromClipboard().
I think actual pasting of code happens in that method, but not sure.
So can anyone please tell me Am I right, i.e. whether investigating in WebViewClassic is worth for me?
If yes, please tell me what is relation between WebView and WebViewClassic, i.e. how long click in WebView goes to WebViewClassic.
And sorry, I cant expose my code or log.
WebViewClassic is the default WebViewProvider for WebView. From the implementation notes:
The WebView is a thin API class that delegates its public API to a backend WebViewProvider
class instance. WebView extends {#link AbsoluteLayout} for backward compatibility reasons.
Methods are delegated to the provider implementation: all public API methods introduced in this
file are fully delegated, whereas public and protected methods from the View base classes are
only delegated where a specific need exists for them to do so.
Basically, touch handling is forwarded from the WebView to a WebViewClassic instance. If you read through it's onTouchEvent implementation, and its inner WebViewInputDispatcher implementation PrivateHandler you can trace where the touch handling will lead to a call to pasteFromClipboard() on the WebViewClassic instance.
So yes, you are correct. When you tap the paste button on the PastePopupWindow, there will be a call to WebViewClassic's pasteFromClipboard(); method.

getProgress method of WebView object returning incorrect result

I am having trouble using a WebView that I need to periodically update, as the application I am programming requires a real-time display. The WebView needs to be updated every 600 seconds or so. I am using the getProgress method of my WebView object in order to check if it had loaded properly, because if it does not, the WebView shows a blank white screen for that update period (this can get very annoying for any end user). However, the getProgress method of the WebView object seems to be returning a result of 100 when there is only a blank screen displayed in the WebView. Why is the getProgress method reporting incorrect information like this?

RoboSpice and android life cycle trouble

I use robospice like this:
ProjectInfoRequest request = new ProjectInfoRequest(mProfile);
spiceManager.execute(request, PROJECT_INFO_LISTENER);
It downloads data and almost everything is ok.
However there are some things that makes me unhappy:
When I press home button, SpiceManager.shouldStop() is called accordingly to the documentation. But when the task is executed listener does not get call, which is right(I guess, because the activity may be destroyed by OS) but how do I save downloaded data? I don't see any in-memory persister in 1.4.0 version
When I try to specify cacheKey like this
spiceManager.execute(request, "projectInfo", DurationInMilis.NEVER, PROJECT_INFO_LISTENER);
the request won't even start executing. However I really need it cause i'd like to use addListenerIfReqeustPending method. What are posible reasons not to start execute request?
Which version do you use ? 1.4.1 has just been released. And which service do you use ? Which cache manager is used by the SpiceService ?

Determine element of url from webview shouldOverRideUrlLoading

I am displaying a html in a custom activity with a webview. I am overriding
public boolean shouldOverrideUrlLoading(WebView view, String url) {
to intercept certain urls. Now I would like to be able to figure out some more details about the html around that url.
In my case I would like to get the html element that contains the url. E.g. if the url comes from
Manfred Moser
I would like to be able to somehow retrieve the value "Manfred Moser" from within the anchor tag. Is there a way to do that. I found that you do not have access to the DOM from Java.
One way I can think of would be to download the page separately and parse it all before even loading it in webview. However that is an ugly hack at best. Is there a better way?
There is a dirty hack:
Bind some Java object so that it can be called from Javascript with WebView:
addJavascriptInterface(javaObjectExposed, "JSname")
Force execute javascript within an existing page by
WebView.loadUrl("javascript:window.JSname.passData("some data");");
Described here: http://lexandera.com/2009/01/extracting-html-from-a-webview/
Note: this is a security risk - any JS code in this web page could access/call your binded Java object. Best to pass some one-time cookies to loadUrl() and pass them back your Java object to check that it's your code making the call.
In addition to #Peter Knego's approach, there is the inverse:
Use addJavascriptInterface(), per his step #1
For your link, use an onClick attribute on your <a> tag to call out some method on the Java object from step #1, where the Java object turns around and loads the URL into the WebView, and supplies whatever sort of identifying information you want.
Suffice it to say, there's no way to get the information you want from shouldOverrideUrlLoading().

Keyboard in HTML text-input disappear when WebView call 'loadUrl' again

I use WebView for my Androind App. I got a problem and request a solution for help.
There is a textfield in the HTML page. When it gets 'focus' and then I call
mWebView.setFocusableInTouchMode(true);
in Java code so that the Android soft-keyboard will pop-up to let me key in.
The problem is I need using multi-thread for some processes in Java and call
mWebView.loadUrl(strJSCall);
as callback to execute JavaScript function, but the keyboard gets hidden!
The way I try is to force the keyboard to show again. But how can the keyboard always show when 'loadUrl' is called?
Dose anyone meet the same issue and solve it already?
Sincerely,
Jr.
The problem with loadUrl is that it interrupts the UI thread and will still close the input method. The only solid way to do this is to check what the cursor is on the webview, and override the default loadUrl behaviour on your webview.
Inside your custom webview:
#Override
public void loadUrl(String url) {
HitTestResult testResult = this.getHitTestResult();
if (url.startsWith("javascript:)" && testResult != null && testResult.getType() == HitTestResult.EDIT_TEXT_TYPE)
{
//Don't do anything right now, we have an active cursor on the EDIT TEXT
//This should be Input Method Independent
}
else
{
super.loadUrl(url);
}
}
This will prevent the native side from loading Javascript from firing when you have focus on a text field in webkit. It's not perfect but it avoids the mess of trying to figure out whether your text field is visible either by the resizing of the WebView. The Javascript executing in the webview should still work fine.
Again, if you need something to update while you're typing, you may have to find another way for Java to communicate with Javascript that doesn't block the UI thread. This is a hard problem that I still haven't solved properly yet.
I have the same problem and haven't fully solved it yet.
I have been able to force the keyboard to show after calling webView.loadUrl, first you need to find out if the keyboard is showing, I used a modified version of this How to check visibility of software keyboard in Android?
then call
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(webview, InputMethodManager.SHOW_IMPLICIT);
But if like me you need to communicate with the JavaScript in the WebView after each key press then this approach causes the keyboard to flicker as it tries to animate up and down. It also misses some of the input depending on how fast you type.
In Android, executing javascript from WebView is one-way: calling WebView.loadUrl("javascript:sub(1,1)"); You can not get the return value directly.
There's a async way to get the JavaScript function return value:
How to get return value from javascript in webview of android?
But in most cases, we need a sync method instead of the async way. For example, while click event is passed into Android WebView's onTouch
method, we want to execute a JavaScript to reading the element information clicked on.
I have tried two solutions:
1. Use Java P/V variable to wrap a sync method from the async on, the solution looks like:
How to get return value from javascript in webview of android?
The solution is totally not working, because wait method will block the execution of JavaScript and JavaScriptInterface. So if we want to get the result of a js
method in a UI Thread. it's not possible.
Use Java Reflection to get the Native Interface of stringByEvaluatingJavaScriptFromString.
Exist stringByEvaluatingJavaScriptFromString for Android
Works very well, the only thing need to care is to initial reflection method when page loaded finished. I tried to initial the reflection inside constructor of WebView, but failed. I think the constructor is async method.

Categories

Resources