应用程序崩溃Cordova警报

时间:2012-12-19 19:14:40

标签: android cordova

在某些Android设备上,基于Cordova的应用程序崩溃的时候我会提示用户,如果他们想要收到通知,这会在第一个应用启动时发生。这是典型的堆栈跟踪:

android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@<i>[eight hex digits]</i> is not valid; is your activity running?
at android.view.ViewRoot.setView(ViewRoot.java:535)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:177)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
at android.view.Window$LocalWindowManager.addView(Window.java:424)
at android.app.Dialog.show(Dialog.java:241)
at android.app.AlertDialog$Builder.show(AlertDialog.java:802)
at org.apache.cordova.Notification$2.run(Notification.java:245)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3806)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
at dalvik.system.NativeStart.main(Native Method)

JavaScript代码:

navigator.notification.confirm(
     'Do you wish to receive push notifications?',
     function(btnIndex) {
         if (btnIndex == 1) {
             push.enablePush();
             localStorage.pushAsked = true;
         } else {
             push.disablePush();
             localStorage.pushAsked = true;
         }
     },
     'Push Notifications',
     'Yes,No'
);

有什么想法吗?我不知道哪些设备或Android版本会受到影响,但这个问题已经出现在报告它的人身上。

我正在使用Cordova 2.2.0。

1 个答案:

答案 0 :(得分:3)

这是因为您正在尝试在活动结束时显示警告对话框。

您可以继承CordovaChromeClient并检查onJsAlert()上的activity.isFinishing()

我在Github上创建了一个解决这个bug的项目: https://github.com/kruyvanna/CordovaAlertBug_Android

您可以在下面看到一个示例。

class CordovaOnJsAlertBug extends DroidGap{
@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    super.loadUrl("file:///android_asset/www/index.html");
}

@Override
public void init() {
    Log.e(TAG, "init()");
    CordovaWebView webView = new CordovaWebView(CordovaOnJsAlertBug.this);
    CordovaWebViewClient webViewClient;
    if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB)
    {
        webViewClient = new CordovaWebViewClient(this, webView);
    }
    else
    {
        webViewClient = new IceCreamCordovaWebViewClient(this, webView);
    }
    this.init(webView, webViewClient, new MyCordovaChromeClient(this, webView));
}

private class MyCordovaChromeClient extends CordovaChromeClient{
    private CordovaInterface cordova;
    public MyCordovaChromeClient(CordovaInterface ctx, CordovaWebView app) {
        super(ctx, app);
        this.cordova = ctx;
    }


    @Override
    public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
        if(cordova.getActivity().isFinishing()){
            Log.w(TAG, "Trying to alert while activity is finishing!! -> ignore");
            result.cancel();
            return true;
        }

        return super.onJsAlert(view, url, message, result);
    }
}
}