android.view.WindowManager$BadTokenException Exception. Any pointer?
I have two webviews and to cut out the common functionality from both the webviews I created a super class with all methods in the super class and use it in the two webviews.
Once when I create the object and set the variables from the 1st webview, the WebView displays properly and when I press the 'BACK' button and go to the 2nd WebView I get the folling exception.
Any help?
First WebView Code
public class firstWebView extends Activity {
private static final String LOG_TAG = "FirstWebView";
public static final int VIDEO_PLAY = 0;
private WebView mWebView;
private NicuWebView _nicuWebView;
private static final String URL = mainMenuActivity.urlSelected+"todo.html";
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.webview);
getWindow().setFeatureInt(Window.FEATURE_PROGRESS, Window.PROGRESS_VISIBILITY_ON);
mWebView = (WebView) findViewById(R.id.webview);
_nicuWebView = NicuWebView.getNicuWebView(mWebView);
// mWebView.setWebChromeClient(new MyWebChromeClient());
final Activity activity = this;
NicuWebView.setContext(activity);
setProgressBarVisibility(true);
int count = (int) _nicuWebView.loadUrl(URL);
Toast.makeText(this, "Count = "+count, Toast.LENGTH_SHORT).show();
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
// startActivity(new Intent(getApplication(), mainMenuActivity.class));
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
Code for Second is similar to the first one but the URL points to a different html page.
E/AndroidRuntime( 7913): android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@447d2a98 is not valid; is your activity running?
E/AndroidRuntime( 7913): at android.view.ViewRoot.setView(ViewRoot.java:468)
E/AndroidRuntime( 7913): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
E/AndroidRuntime( 7913): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
E/AndroidRuntime( 7913): at android.view.Window$LocalWindowManager.addView(Window.java:424)
E/AndroidRuntime( 7913): at android.app.Dialog.show(Dialog.java:239)
E/AndroidRuntime( 7913): at android.app.AlertDialog$Builder.show(AlertDialog.java:802)
E/AndroidRuntime( 7913): at android.webkit.CallbackProxy.handleMessage(CallbackProxy.java:483)
E/AndroidRuntime( 7913): at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 7913): at android.os.Looper.loop(Looper.java:123)
E/AndroidRuntime( 7913): at android.app.ActivityThread.main(ActivityThread.java:4363)
E/AndroidRuntime( 7913): at java.lang.reflect.Method.invokeNative(NativeMethod)
E/AndroidRuntime( 7913): at java.lang.reflect.Method.invoke(Method.java:521)
E/AndroidRuntime( 7913): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
E/AndroidRuntime( 7913): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
E/AndroidRuntime( 7913): at dalvik.system.NativeStart.main(Native Method)
Code for NicuWebView is
public class NicuWebView {
private static NicuWebView _nicuWebView;
private static WebView _webView;
private static HashMap<String,Long> _urls;
private static Context contextName;
private static final int VIDEO_PLAY = 0;
private NicuWebView(WebView myWebView) {
_urls = new HashMap<String,Long>(10);
_webView = myWebView;
_webView.setWebViewClient(new NicuWebViewClient());
_webView.getSettings().setJavaScriptEnabled(true);
_webView.clearCache(true);
WebSettings webSettings = _webView.getSettings();
webSettings.setSavePassword(true);
webSettings.setSaveFormData(true);
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportZoom(true);
_webView.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");
_webView.clearCache(true);
_webView.setWebViewClient(new WebViewClient() {
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(contextName, "Super Class TOAST message", Toast.LENGTH_LONG).show();
}
@Override
public void onPageFinished(WebView view, String url)
{
_webView.loadUrl("javascript:(function () { " +
"setVariable("+mainMenuActivity.numberSelected+");" +
"})()");
}
});
_webView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView view, int progress) {
// Activities and WebViews m开发者_运维技巧easure progress with different scales.
// The progress meter will automatically disappear when we reach 100%
((Activity) contextName).setProgress(progress * 1000);
}
});
_webView.setWebViewClient(new WebViewClient() {
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
Toast.makeText(contextName, "Oh no! " + description, Toast.LENGTH_SHORT).show();
}
@Override
public void onPageFinished(WebView view, String url) {
_webView.loadUrl("javascript:(function () { " +
"setVariable("+mainMenuActivity.numberSelected+");" +
"})()");
}
});
}
// allow clicking on link to remain in app instead of launching android browser
private class NicuWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}
public static NicuWebView getNicuWebView(WebView myWebView){
if (_nicuWebView == null) _nicuWebView = new NicuWebView(myWebView);
return _nicuWebView;
}
// loads the requested URL and maintains a 'history' of pages visited.
// returns number of times page was loaded.
public long loadUrl(String url) {
long count = incrementCounter(url);
_webView.loadUrl(url);
return count;
}
//helper to
private static long incrementCounter(String url){
if (url != null) {
if (_urls.get(url)==null) _urls.put(url,new Long(0));
long count = _urls.put(url,_urls.get(url) +1L);
return count;
}
else {
Toast.makeText(contextName, "Null URL", Toast.LENGTH_SHORT).show();
return 0;
}
}
/// return the number of times the given URL has been visited
public long getUrlVisitCount(String url) {
if (_urls.get(url)==null) return 0L;
return _urls.get(url);
}
//returns to the previous URL, returns that URL
public String goBack(){
if (_webView.canGoBack()) _webView.goBack();
String url = _webView.getUrl();
incrementCounter(url);
return url;
}
//returns to next forward URL, returns that URL
public String goForward(){
if (_webView.canGoForward()) _webView.goForward();
String url = _webView.getUrl();
incrementCounter(url);
return url;
}
public static boolean setContext(Context context) {
contextName = context;
return true;
}
public Context getContext(){
if (contextName == null) return null;
return contextName;
}
final class DemoJavaScriptInterface {
public void setPlayVideo(String option) {
Toast.makeText(contextName, "Playing Video = "+option, Toast.LENGTH_SHORT).show();
Intent intent = new Intent ( contextName, playVideo.class );
((Activity) contextName).startActivityForResult(intent, VIDEO_PLAY);
}
}
public boolean canGoBack() {
return _webView.canGoBack();
}
}
The problem is that the dialog need to have the "base" context of your activity, not necessarily the one you're launching it from.
Here's one solution which often works
Activity a = this;
while(a.getParent() != null) {
a = a.getParent();
}
_nicuWebView.setContext(a);
One way to see what's going on with this is to modify that example as follows
Activity a = this;
while(a.getParent() != null) {
Log.i("ActivityTree",a.getClass().getSimpleName());
a = a.getParent();
}
_nicuWebView.setContext(a);
adb
will then show you the hierarchy of activities which you're inside.
use this :
private Handler myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case DISPLAY_DLG:
if (!isFinishing()) {
showDialog(MY_DIALOG);
}
break;
}
}
};
You just have to add:
public void onResume() {
super.onResume();
mContext = this;
}
When you create the WebView
you are currently using the context of the application. You should be using the context of the Activity
. To solve the problem, replace getApplicationContext()
with this when you create the WebView
.
精彩评论