Po pierwsze wiem, że tak naprawdę nie należy zabijać / restartować aplikacji na Androidzie. W moim przypadku chcę przywrócić ustawienia fabryczne mojej aplikacji w konkretnym przypadku, w którym serwer wysyła określone informacje do klienta.
Użytkownik może być zalogowany tylko na serwerze z JEDNĄ instancją aplikacji (tzn. Wiele urządzeń nie jest dozwolonych). Jeśli inna instancja otrzyma tę blokadę „zalogowanego”, wówczas wszystkie inne instancje tego użytkownika muszą usunąć swoje dane (przywrócone do ustawień fabrycznych), aby zachować spójność.
Możliwe jest przymusowe uzyskanie blokady, ponieważ użytkownik może usunąć aplikację i zainstalować ją ponownie, co spowoduje inny identyfikator instancji, a użytkownik nie będzie już w stanie zwolnić blokady. Dlatego można siłą dostać blokadę.
Z powodu tej możliwości siły musimy zawsze sprawdzić w konkretnym przypadku, czy ma zamek. Odbywa się to (prawie) przy każdym żądaniu do serwera. Serwer może wysłać „błędny identyfikator blokady”. Jeśli zostanie wykryty, aplikacja kliencka musi usunąć wszystko.
To był przypadek użycia.
Mam Activity
A, który rozpoczyna logowanie Activity
L lub główny Activity
B aplikacji, w zależności od wartości sharedPrefs. Po uruchomieniu L lub B zamyka się tak, że działa tylko L lub B. Więc w przypadku, gdy użytkownik jest zalogowany, już działa B.
B uruchamia C. C wzywa startService
na IntentService
D. To powoduje następujący stos:
(A)> B> C> D
Z metody onHandleIntent D zdarzenie jest wysyłane do ResultReceiver R.
R obsługuje teraz to zdarzenie, udostępniając użytkownikowi okno dialogowe, w którym może zresetować aplikację do ustawień fabrycznych (usunąć bazę danych, sharedPrefs itp.)
Po przywróceniu ustawień fabrycznych chcę ponownie uruchomić aplikację (aby zamknąć wszystkie działania) i uruchomić ponownie tylko A, który następnie uruchamia logowanie Activity
L i kończy się:
(A)> L
Metoda onClick okna dialogowego wygląda następująco:
@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);
}
I to jest MyApp
klasa:
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() {
// ...
}
}
Problem polega na tym, że jeśli korzystam FLAG_ACTIVITY_NEW_TASK
z działań B i C, nadal działają. Po naciśnięciu przycisku Wstecz przy logowaniu Activity
widzę C, ale chcę wrócić do ekranu głównego.
Jeśli nie ustawię FLAG_ACTIVITY_NEW_TASK
, otrzymuję błąd:
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?
Nie mogę użyć działań ' Context
, ponieważ ServiceIntent
D może być również wywołane z zadania w tle, które jest uruchamiane przez AlarmManager
.
Jak więc rozwiązać ten problem, zmieniając stos aktywności na (A)> L?