开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜