【问题标题】:App crashes on Cordova alert科尔多瓦警报上的应用程序崩溃
【发布时间】:2012-12-19 19:14:39
【问题描述】:

在某些 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。

【问题讨论】:

    标签: android cordova


    【解决方案1】:

    这是因为您试图在活动完成时显示警报对话框。

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

    我在 Github 上创建了一个项目来解决这个错误: 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);
        }
    }
    }
    

    【讨论】:

    • 谢谢。一个问题:我假设子类会阻止对话框出现是否正确?如果是这种情况,我需要想办法解决这个问题,因为我仍然需要提示用户推送通知。
    • 是的,它将取消对话框。您可以包含导致此异常的代码吗?这有助于了解您的活动被破坏的原因。
    • 我实际上不能,因为它是专有代码。但我已将推送通知提示移至原生 Java 并至少消除了该崩溃。
    猜你喜欢
    • 1970-01-01
    • 2017-06-08
    • 1970-01-01
    • 2017-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多