まず、Android ではアプリケーションを強制終了/再起動してはいけないことはわかっています。私のユースケースでは、サーバーが特定の情報をクライアントに送信する特定のケースで、アプリケーションを工場出荷時の状態にリセットしたいと考えています。
ユーザーは、アプリケーションの 1 つのインスタンスでのみサーバーにログインできます (つまり、複数のデバイスは許可されません)。別のインスタンスが「ログイン」ロックを取得した場合、一貫性を維持するために、そのユーザーの他のすべてのインスタンスはデータを削除 (工場出荷時設定にリセット) する必要があります。
ユーザーがアプリを削除して再インストールするとインスタンス ID が変わり、ユーザーはロックを解除できなくなるため、強制的にロックを取得することが可能です。したがって、強制的にロックを取得することが可能です。
強制の可能性のため、具体的なインスタンスでロックが保持されているかどうかを常に確認する必要があります。これは、サーバーへの (ほぼ) 各リクエストで実行されます。サーバーは「間違ったロック ID」を送信する可能性があります。これが検出されると、クライアント アプリケーションはすべてを削除する必要があります。
それがユースケースでした。
Activity
sharedPrefs 値に応じて、ログインActivity
L またはアプリのメインB を起動する AがありますActivity
。L または B を起動した後、L または B のみが実行されるようにそれ自体が閉じられます。したがって、ユーザーがすでにログインしている場合は、B が現在実行されています。
B が C を開始します。C がDstartService
を呼び出しますIntentService
。その結果、次のスタックが生成されます。
(A) > B > C > D
DのonHandleIntentメソッドから、イベントが送信されます。結果受信者R.
R は、ユーザーにアプリケーションを工場出荷時の状態にリセットする (データベース、sharedPrefs などを削除する) ことを選択できるダイアログを提供することで、そのイベントを処理するようになりました。
工場出荷時の状態にリセットした後、アプリケーションを再起動して(すべてのアクティビティを閉じるため)、A のみを再度起動し、ログインActivity
L を起動して終了します。
(あ) > L
ダイアログの onClick メソッドは次のようになります。
@Override
public void onClick(DialogInterface dialog, int which) {
// Will call onCancelListener
MyApplication.factoryReset(); // (Deletes the database, clears sharedPrefs, etc.)
Intent i = new Intent(MyApp.getContext(), A.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
MyApp.getContext().startActivity(i);
}
これがそのMyApp
クラスです:
public class MyApp extends Application {
private static Context context;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
public static Context getContext() {
return context;
}
public static void factoryReset() {
// ...
}
}
問題は、FLAG_ACTIVITY_NEW_TASK
アクティビティ B と C を使用すると、アクティビティ B と C がまだ実行されていることです。ログイン時に [戻る] ボタンを押すとActivity
C が表示されますが、ホーム画面に戻りたいのです。
設定しないとFLAG_ACTIVITY_NEW_TASK
エラーが発生します:
07-07 12:27:12.272: ERROR/AndroidRuntime(9512): android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
D は によって開始されるバックグラウンド タスクからも呼び出される可能性があるためContext
、アクティビティの は使用できません。ServiceIntent
AlarmManager
では、アクティビティ スタックが (A) > L になるようにこれを解決するにはどうすればよいですか?
ベストアンサー1
使用できますPendingIntent
将来的に開始アクティビティを起動するように設定し、アプリケーションを閉じる
Intent mStartActivity = new Intent(context, StartActivity.class);
int mPendingIntentId = 123456;
PendingIntent mPendingIntent = PendingIntent.getActivity(context, mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
System.exit(0);