1

サーバーとの同期プロセスを開始するAndroidアプリケーションでのアクティビティがあります。このプロセスは多くのメモリと処理を消費し、完了するまでに時間がかかります。

プロセスが完了すると、AlertDialogがユーザーに表示され、プロセスが正常に完了したかどうかが示されます。

アクティビティをフォアグラウンドのままにすると、すべてが常に期待どおりに機能します。ただし、アプリケーションを終了すると、バックグラウンドプロセスは引き続き機能しますが、アプリケーションに戻ると、次のエラーでクラッシュすることがあります。

android.view.WindowManager $ BadTokenException:ウィンドウを追加できません-トークンandroid.os.BinderProxy@4086ea48は無効です。あなたの活動は実行されていますか?

アクティビティがOSによって破壊されたために、このエラーが発生する可能性がありますか?はいの場合、プロセス(別のスレッドで実行されている)はどのように実行を継続できますか?また、問題の原因がアクティビティの破壊であることが確認された場合でも、このシナリオを処理し、クラッシュを回避してユーザーにダイアログを表示するにはどうすればよいですか?

ここにいくつかのコードがあります...

public class ActSincronizacao extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.sincronizacao);

        //Prepare so starts the process
        [...]

        // Defines a Handler that will be called when the process gets finished
        oSocketEngine.addProgressUpdateFinishListener(new ProgressUpdateFinishListener() {

            @Override
            public void ProgressUpdateFinishOccurred(final ProgressUpdateFinish evt) {

                //Do some processing that doesn´t envolve UI
                [...]

                // Process that envolves UI
                runOnUiThread(new Runnable() {

                    public void run() {

                        if ((boolean)evt.getArgs().getResult()) {

                            //If the process gets Success
                            AlertDialog.Builder builder = new AlertDialog.Builder(ActSincronizacao.this);
                            builder.setIcon(android.R.drawable.ic_dialog_info);
                            builder.setTitle("Informação");
                            builder.setMessage("Sincronização concluida com sucesso.");

                            // Defines a button handler
                            builder.setNeutralButton("OK", new OnClickListener() {

                                @Override
                                public void onClick(DialogInterface dialog, int which) {

                                    //Go to another Activity
                                    [...]


                                }
                            });

                            //Call the Dialog
                            builder.create().show();

                        } else {


                            //If something wrong hapenned

                            StringBuilder stb = new StringBuilder();
                            stb.append("Some error ocurrend while running the sync process.");

                            if (evt.getArgs().getMessage() != null) {
                                stb.append("\n\n");
                                stb.append(evt.getArgs().getMessage());
                            } else {
                                stb.append("\n\n");
                                stb.append("Try again...");
                            }

                            AlertDialog.Builder builder = new AlertDialog.Builder(ActSincronizacao.this);
                            builder.setIcon(android.R.drawable.ic_dialog_alert);
                            builder.setTitle("Error");
                            builder.setMessage(stb.toString());
                            builder.setNeutralButton("OK", null);
                            builder.create().show();            //<<<<<<<<<<<<<<<<< Crash is reported here

                        }
                    }
                });
            }
        });

        //Starts the process in backgroud (Thread)
        oSocketEngine.StartCommunication(oDeviceConfig);

    }

}

ログに記録された完全なスタックトレースは次のとおりです。

android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@4086ea48 is not valid; is your activity running?
at android.view.ViewRoot.setView(ViewRoot.java:532)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:200)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:114)
at android.view.Window$LocalWindowManager.addView(Window.java:424)
at android.app.Dialog.show(Dialog.java:241)
at PortalExecutivoSales.Android.ActSincronizacao$3$1.run(ActSincronizacao.java:138)
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:3687)
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:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
at dalvik.system.NativeStart.main(Native Method)
4

1 に答える 1

8

この問題の解決策をまだ探している人のために:

次のリンクは、この問題が発生している理由とその理由を説明しています。 http://vinnysoft.blogspot.com.br/2010/11/androidviewwindowmanagerbadtokenexcepti.html

この問題を解決するために私がしたこと:

1)。クラス上に、アクティビティが実行されているかどうかを通知するために使用される、ActSincronizacaoと呼ばれるブール変数を作成しました。isActivityRunningこの変数は、次のようにonPauseイベントとonResumeイベントで設定されます。

@Override
protected void onPause() {
    isActivityActive = false;
    super.onPause();
}

@Override
protected void onResume() {
    isActivityActive = true;
    super.onResume();
}

2)。プロセスが終了したら、ダイアログを呼び出す前に、isActivityActive変数のステータスを確認します。もしそうならtrue、私はいつものように対話を呼びます。そうでない場合は、次の例のように通知を作成します。

http://developer.android.com/guide/topics/ui/notifiers/notifications.html#NotificationResponse

3)。ユーザーが通知をクリックしたときに、エラーメッセージ(ある場合)を含むアラートをユーザーに表示したいと思います。したがって、通知は、呼び出されているアクティビティにErrorMessageを渡す必要があります。extraこれは、にを追加して行うことができますNotification Intent。以下の例を見て、通知によって作成されたエクストラを渡す方法(@Vidar Vestnesの質問)と消費する方法(@ pinaiseの回答)を確認してください。

通知クリックからアクティビティにパラメータを送信する方法は?

4)。最後に、ユーザーが通知をクリックしたときに、アプリケーションが実行されていない場合は、アプリケーションを起動したいと思います。実行中の場合は、フォアグラウンドに戻したいと思います。デフォルトの動作では、通知をクリックすると、通知インテントに渡されたアクティビティの新しいインスタンスが作成されます。新しいアクティビティの作成を回避してアプリをフォアグラウンドにするには、以下の@santhoshの応答を参照してください。

通知項目を介してバックグラウンドアプリケーションを再度開きます

これが将来他の人に役立つことを願っています。

よろしく。

于 2012-10-16T17:38:55.107 に答える