Mam ekran powitalny na zegarze. Mój problem polega na tym, że przed wykonaniem finish()
czynności muszę sprawdzić, czy rozpoczęło się kolejne działanie, ponieważ wyskakuje systemowe okno dialogowe i chcę tylko finish()
; po wybraniu przez użytkownika opcji w oknie dialogowym?
Wiem, że jest wiele pytań dotyczących tego, jak sprawdzić, czy twoja aktywność jest na pierwszym planie, ale nie wiem, czy to pozwala również na okna dialogowe u góry działania.
Oto problem, czerwony to moja aktywność, która jest w tle, podczas gdy dialog jest na pierwszym planie:
EDYCJA: Próbowałem po prostu nie używać, finish()
ale wtedy moja aktywność może wrócić do stosu aplikacji, których staram się uniknąć.
android
android-activity
dialog
activity-finish
Nacięcie
źródło
źródło
Odpowiedzi:
Oto, co jest zalecane jako właściwe rozwiązanie:
W swojej
finish()
metodzie chcesz użyć,isActivityVisible()
aby sprawdzić, czy aktywność jest widoczna, czy nie. Tam możesz również sprawdzić, czy użytkownik wybrał opcję, czy nie. Kontynuuj, gdy oba warunki zostaną spełnione.Źródło wspomina również o dwóch błędnych rozwiązaniach ... więc unikaj tego.
Źródło: stackoverflow
źródło
onPause
,onStop
anionResume
wydarzeniem jest tzw. Więc co zrobisz, jeśli żadne z tych wydarzeń nie zostanie zwolnione ?!Jeśli kierujesz się na poziom interfejsu API 14 lub wyższy, możesz użyć android.app.Application.ActivityLifecycleCallbacks
źródło
UPD : zaktualizowano do stanu
Lifecycle.State.RESUMED
. Dzięki za to @htafoya .W 2019 z pomocą nowej biblioteki wsparcia
28+
lub AndroidX możesz po prostu użyć:Możesz przeczytać więcej w dokumentacji, aby zrozumieć, co wydarzyło się pod maską.
źródło
activity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)
lub ROZPOCZĄĆ.INITIALIZED
nie gwarantuje, że jest na pierwszym planie.Activity :: hasWindowFocus () zwraca wartość logiczną, której potrzebujesz.
Oto przykładowe zajęcia, aby sprawdzić widoczność swoich działań z dowolnego miejsca.
Pamiętaj, że jeśli pokażesz okno dialogowe , wynik będzie fałszywy, ponieważ okno dialogowe będzie miało główny fokus. Poza tym jest naprawdę poręczny i bardziej niezawodny niż sugerowane rozwiązania.
źródło
To jest dokładnie różnica między
onPause
ionStop
wydarzenia z działalności opisane w dokumentacji klasy aktywny .Jeśli dobrze Cię rozumiem, to co chcesz zrobić, to zadzwonić
finish()
ze swojej działalności,onStop
aby ją zakończyć. Zobacz załączony obraz aplikacji Activity Lifecycle Demo . Tak to wygląda, gdy aktywny B jest uruchamiany z działalności A. Kolejność zdarzeń jest od dołu do góry, dzięki czemu można zobaczyć, że aktywność naonStop
nazywa po Działalność BonResume
już została wywołana.W przypadku wyświetlenia okna dialogowego Twoja aktywność jest wygaszona w tle i tylko
onPause
jest wywoływana.źródło
Dwa możliwe rozwiązania:
1) Wywołania zwrotne cyklu życia działania
Użyj aplikacji, która implementuje ActivityLifecycleCallbacks i użyj jej do śledzenia zdarzeń cyklu życia działań w aplikacji. Zwróć uwagę, że ActivityLifecycleCallbacks są dla interfejsu API systemu Android> = 14. W przypadku poprzedniego interfejsu API systemu Android musisz zaimplementować go samodzielnie we wszystkich swoich działaniach ;-)
Użyj aplikacji, gdy chcesz udostępniać / przechowywać stany w różnych działaniach.
2) Sprawdź, czy są uruchomione informacje o procesie
Możesz sprawdzić stan uruchomionego procesu za pomocą tej klasy RunningAppProcessInfo
Pobierz listę uruchomionych procesów za pomocą ActivityManager.getRunningAppProcesses () i przefiltruj listę wyników, aby sprawdzić żądane RunningAppProcessInfo i sprawdź jego „ważność”
źródło
Stworzyłem projekt na github app-foreground-background-listen
który używa bardzo prostej logiki i działa dobrze na wszystkich poziomach Android API.
źródło
Użyj przerwy czasowej między wstrzymaniem a wznowieniem z tła, aby określić, czy jest wybudzony z tła
W aplikacji niestandardowej
W klasie BaseActivity
źródło
Myślę, że mam lepsze rozwiązanie. Ponieważ możesz wbudować po prostu MyApplication.activityResumed (); do każdego działania o jeden zakres.
Najpierw musisz stworzyć (jak CyberneticTwerkGuruOrc)
Następnie musisz dodać klasę Application do AndroidManifest.xml
Następnie utwórz klasę ActivityBase
Wreszcie, kiedy tworzysz nową aktywność, możesz ją po prostu rozszerzyć o ActivityBase zamiast Activity.
Dla mnie to lepsza metoda, bo trzeba tylko pamiętać o rozszerzeniu o ActivityBase. Ponadto w przyszłości możesz rozszerzyć swoją podstawową funkcję. W moim przypadku dodałem odbiorniki do mojej usługi i alerty o sieci w jednej klasie.
Jeśli chcesz sprawdzić widoczność swojej aplikacji, możesz po prostu zadzwonić
źródło
Można to osiągnąć w efektywny sposób przy użyciu Application.ActivityLifecycleCallbacks
Na przykład, weźmy nazwę klasy Activity jako ProfileActivity pozwala sprawdzić, czy jest na pierwszym planie, czy w tle
najpierw musimy stworzyć naszą klasę aplikacji, rozszerzając Application Class
które implementuje
Niech moja klasa aplikacji będzie następująca
Klasa aplikacji
w powyższej klasie jest methord przesłanianie onActivityResumed z ActivityLifecycleCallbacks
gdzie można znaleźć wszystkie instancje aktywności, które są aktualnie wyświetlane na ekranie, po prostu sprawdź, czy Twoja aktywność jest na ekranie, czy nie, za pomocą powyższej metody.
Zarejestruj klasę aplikacji w pliku manifest.xml
Aby sprawdzić pogodę Aktywność jest na pierwszym planie lub w tle, zgodnie z powyższym rozwiązaniem, wywołaj następującą metodę w miejscach, które musisz sprawdzić
źródło
Jeśli chcesz wiedzieć, czy jakakolwiek aktywność Twojej aplikacji jest widoczna na ekranie, możesz zrobić coś takiego:
Po prostu utwórz singletona tej klasy i ustaw go w swojej instancji Application, jak poniżej:
Następnie możesz użyć metody isAnyActivityVisible () swojej instancji MyAppActivityCallbacks wszędzie!
źródło
Czy próbowałeś nie wywoływać finish i umieszczać w manifeście „android: noHistory =„ true ”? Zapobiegnie to przeniesieniu aktywności na stos.
źródło
Muszę powiedzieć, że twój przepływ pracy nie jest w standardowy sposób na Androida. W Androidzie nie musisz wykonywać
finish()
swojej aktywności, jeśli chcesz otworzyć inną aktywność z Intent. Jeśli chodzi o wygodę użytkownika, system Android umożliwia użytkownikowi użycie klawisza „Wstecz”, aby cofnąć się z otwartej czynności w aplikacji.Po prostu pozwól systemowi zatrzymać Twoją aktywność i zapisz wszystko, co jest potrzebne, gdy Twoja aktywność zostanie odwołana.
źródło
Zapisz flagę, jeśli jesteś wstrzymany lub wznowiony. Jeśli zostaniesz wznowiony, oznacza to, że jesteś na pierwszym planie
źródło
Jednym z możliwych rozwiązań może być ustawienie flagi podczas wyświetlania okna dialogowego systemu, a następnie w metodzie onStop cyklu życia działania sprawdzenie flagi, jeśli prawda, zakończenie działania.
Na przykład, jeśli systemowe okno dialogowe jest uruchamiane przez jakieś kliknięcie przycisku, wówczas odbiornik onclick może wyglądać tak
i po zakończeniu działalności:
źródło
Dlaczego nie wykorzystać do tego transmisji? druga czynność (ta, która musi być włączona) może wysyłać lokalną transmisję w następujący sposób:
następnie napisz prosty odbiornik w ramach działania splash:
i zarejestruj swój nowy odbiornik w LocalBroadcastManager, aby słuchać transmisji z drugiej czynności:
PAMIĘTAJ, że można użyć stałej lub łańcuchowej dla ciągu „identyfikatora emisji”.
źródło
LocalBroadcastManager
tutajJeśli używasz
finish()
tylko w celu uniknięcia uruchamiania nowej aplikacji na stosie (zadaniu) swojej aplikacji, możesz użyćIntent.FLAG_ACTIVITY_NEW_TASK
flagi podczas uruchamiania nowej aplikacji i nie wywoływaćfinish()
w ogóle. Zgodnie z dokumentacją jest to flaga, która ma być używana do implementacji zachowania w stylu „programu uruchamiającego”.źródło
Użyj tych metod wewnątrz pliku
Activity
.isDestroyed()
isFinishing()
Częstym błędem
AsyncTask
jest uchwycenie silnego odniesienia do hostaActivity
(lubFragment
):Jest to problem, ponieważ
AsyncTask
może łatwo przeżyć rodzicaActivity
, na przykład jeśli zmiana konfiguracji nastąpi podczas działania zadania.Właściwy sposób to uczynić swoje zadanie
static
klasą, która nie wychwytuje rodzica, i utrzymywać słabe odniesienie do hostaActivity
:źródło
Oto rozwiązanie wykorzystujące
Application
klasę.Możesz go po prostu użyć w następujący sposób,
Jeśli masz odniesienie do wymaganego działania lub używając kanonicznej nazwy działania, możesz dowiedzieć się, czy jest ono na pierwszym planie, czy nie. To rozwiązanie może nie być niezawodne. Dlatego Twoje komentarze są naprawdę mile widziane.
źródło
Nie wiem, dlaczego nikt nie mówił o sharedPreferences, dla Działania A, ustawiając SharedPreference w ten sposób (na przykład w onPause ()):
Myślę, że jest to niezawodny sposób śledzenia widoczności działań.
źródło
Przydałby
Activity.onWindowFocusChanged(boolean hasFocus)
się tutaj? To, plus flaga na poziomie klasy, coś wisFocused
tym rodzajuonWindowFocusChanged
, byłoby łatwym sposobem na stwierdzenie w dowolnym momencie twojej aktywności, czy jest skupiona, czy nie. Po przeczytaniu dokumentów wygląda na to, że poprawnie ustawiłoby to „fałsz” w każdej sytuacji, w której działanie nie znajduje się bezpośrednio na fizycznym „pierwszym planie”, na przykład w przypadku wyświetlania okna dialogowego lub opuszczania zasobnika powiadomień.Przykład:
źródło
Jeśli używasz EventBus , jest to metoda wywoływana,
hasSubscriberForEvent
której można użyć do sprawdzenia, czyActivity
jest fokus.źródło
Lubiłem
jeśli działanie nie jest na pierwszym planie
zwróci wartość null. : = P
źródło