サーバーとの同期プロセスを開始する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)