Erstens weiß ich, dass man eine Anwendung auf Android nicht wirklich beenden sollte. In meinem Anwendungsfall möchte ich meine Anwendung in einem bestimmten Fall auf die Werkseinstellungen zurücksetzen, in dem ein Server bestimmte Informationen an den Client sendet.
Der Benutzer kann nur mit EINER Instanz der Anwendung am Server angemeldet sein (dh mehrere Geräte sind nicht zulässig). Wenn eine andere Instanz diese "angemeldete" Sperre erhält, müssen alle anderen Instanzen dieses Benutzers ihre Daten löschen (auf die Werkseinstellungen zurücksetzen), um die Konsistenz aufrechtzuerhalten.
Es ist möglich, die Sperre zwangsweise zu erhalten, da der Benutzer die App möglicherweise löschen und neu installieren kann, was zu einer anderen Instanz-ID führen würde und der Benutzer die Sperre nicht mehr aufheben kann. Daher ist es möglich, das Schloss gewaltsam zu bekommen.
Aufgrund dieser Kraftmöglichkeit müssen wir immer in einer konkreten Instanz überprüfen, ob sie das Schloss hat. Dies geschieht bei (fast) jeder Anfrage an den Server. Der Server sendet möglicherweise eine "falsche Sperr-ID". Wenn dies erkannt wird, muss die Clientanwendung alles löschen.
Das war der Anwendungsfall.
Ich habe ein Activity
A, das das Login Activity
L oder das Haupt- Activity
B der App abhängig von einem sharedPrefs-Wert startet. Nach dem Start von L oder B schließt es sich so, dass nur L oder B läuft. Für den Fall, dass der Benutzer bereits angemeldet ist, wird B jetzt ausgeführt.
B startet C. C fordert startService
das IntentService
D. Das ergibt diesen Stapel:
(A)> B> C> D.
Von der onHandleIntent-Methode von D wird ein Ereignis an einen ResultReceiver R gesendet .
R behandelt dieses Ereignis jetzt, indem es dem Benutzer einen Dialog zur Verfügung stellt, in dem er die Anwendung auf die Werkseinstellungen zurücksetzen kann (Löschen der Datenbank, sharedPrefs usw.).
Nach dem Zurücksetzen auf die Werkseinstellungen möchte ich die Anwendung neu starten (um alle Aktivitäten zu schließen) und erst wieder A starten, das dann das Login Activity
L startet und sich selbst beendet:
(A)> L.
Die onClick-Methode des Dialogs sieht folgendermaßen aus:
@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);
}
Und das ist die MyApp
Klasse:
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() {
// ...
}
}
Das Problem ist, wenn ich FLAG_ACTIVITY_NEW_TASK
die Aktivitäten B und C verwende, laufen sie noch. Wenn ich beim Anmelden auf die Schaltfläche "Zurück" drücke, wird Activity
C angezeigt, ich möchte jedoch zum Startbildschirm zurückkehren.
Wenn ich das nicht einstelle, FLAG_ACTIVITY_NEW_TASK
erhalte ich den Fehler:
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?
Ich kann die Aktivitäten nicht verwenden Context
, da das ServiceIntent
D möglicherweise auch von einer Hintergrundaufgabe aufgerufen wird, die von der gestartet wird AlarmManager
.
Wie könnte ich das lösen, damit der Aktivitätsstapel (A)> L wird?