Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to completely reset Android webview before load new request

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?

like image 568
wayne_bai Avatar asked Jan 15 '23 15:01

wayne_bai


2 Answers

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

  1. you create a WebView
  2. some clever JS runs, perhaps calling alert()
  3. you handle the alert() in your onJsAlert override method
  4. you fail to call either result.confirm() or result.cancel()
  5. you destroy the WebView
  6. 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.

like image 117
Ted Collins Avatar answered Jan 17 '23 04:01

Ted Collins


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

like image 31
wayne_bai Avatar answered Jan 17 '23 03:01

wayne_bai