Jak symulować Androida zabijającego mój proces

174

Android zabije proces, jeśli będzie działał w tle, a system operacyjny zdecyduje, że potrzebuje zasobów (RAM, procesor itp.). Muszę móc symulować to zachowanie podczas testowania, aby upewnić się, że moja aplikacja działa poprawnie. Chcę móc to robić w sposób zautomatyzowany, aby móc sprawdzić, czy aplikacja zachowuje się poprawnie, ilekroć tak się stanie, co oznacza, że ​​będę musiał to testować w każdym działaniu itp.

Wiem, jak zabić swój proces. To nie jest problem. Problem polega na tym, że kiedy zabić mojego procesu (stosując DDMS, adb shell kill, Process.killProcess(), itd.) Android nie uruchomić go w ten sam sposób, że jeżeli będzie Android OS zabił sama.

Jeśli system operacyjny Android zabije proces (ze względu na wymagania dotyczące zasobów), gdy użytkownik wróci do aplikacji, system Android odtworzy proces, a następnie ponownie utworzy najwyższą aktywność na stosie aktywności (wywołanie onCreate()).

Z drugiej strony, jeśli ja zabić proces, Android zakłada, że działalność na wierzchu stosu aktywność była źle wychowane , więc automatycznie odtwarza proces, a następnie usuwa aktywność top ze stosu działalności i odtwarza czynność, która była pod spodem najważniejsze działanie (wywołanie onCreate () `). Nie jest to zachowanie, którego chcę. Chcę takiego samego zachowania, jak wtedy, gdy Android zabija proces.

Aby wyjaśnić obrazowo, jeśli mój stos aktywności wygląda następująco:

    ActivityA -> ActivityB -> ActivityC -> ActivityD

Jeśli system Android zabije proces, a użytkownik wróci do aplikacji, system Android ponownie utworzy proces i utworzy ActivityD.

Jeśli zabiję proces, Android odtwarza proces i tworzy ActivityC.

David Wasser
źródło
4
Czy nie mógłbyś po prostu stworzyć w tle ilości procesów wymaganych do zabicia twojego?
Alex W,
2
@Pang Myślę, że nie rozumiesz. Wiem, jak wykryć, że Android zabił ten proces. Mam kod, który obsługuje te warunki. To, co chcę zrobić, to poprawnie (iw sposób zautomatyzowany) przetestować ten kod . Aby to zrobić, potrzebuję jakiegoś sposobu na sprowokowanie Androida do zabicia mojego procesu w dokładnie taki sam sposób, jak zrobiłby to normalnie pod presją zasobów. Powiązane pytanie, choć interesujące, nie wnosi tutaj żadnej wartości.
David Wasser,
@IgorGanapolsky Dzięki za linki, ale w rzeczywistości żaden z nich nie zawiera rozwiązania problemu.
David Wasser,

Odpowiedzi:

127

Najlepszym sposobem, aby to przetestować, było zrobienie tego:

  • Otwórz ActivityD w swojej aplikacji
  • Naciśnij przycisk Home
  • Naciśnij Terminate Applicationw oknie Logcat w Android Studio (spowoduje to zabicie procesu aplikacji, upewnij się, że wybierasz swoje urządzenie i proces w menu rozwijanym Logcat u góry)
  • Wróć do aplikacji przez długie naciśnięcie ekranu głównego lub otwarte aplikacje (w zależności od urządzenia)
  • Aplikacja uruchomi się w odtworzonym ActivityD (ActivityA, ActivityB, ActivityC są martwe i zostaną odtworzone, gdy do nich wrócisz)

Na niektórych urządzeniach możesz również wrócić do aplikacji (ActivityD) za pomocą aplikacji -> ikona programu uruchamiającego, ale na innych urządzeniach zamiast tego uruchomi się ActivityA.

Oto, co mówią na ten temat dokumentacja Androida:

Zwykle system czyści zadanie (usuwa wszystkie działania ze stosu nad działaniem roota) w pewnych sytuacjach, gdy użytkownik ponownie wybiera to zadanie na ekranie głównym. Zwykle dzieje się tak, jeśli użytkownik nie odwiedził zadania przez określony czas, na przykład 30 minut.

znak
źródło
2
Dziękuję za odpowiedź, ale nie jest to dla mnie przydatne, ponieważ potrzebuję zautomatyzowanego sposobu, aby to zrobić, do automatycznego testowania.
David Wasser
1
To było dla mnie bardzo pomocne.
John Roberts,
6
To nie jest zautomatyzowane, ale działało idealnie do moich celów. Bardzo ważne jest, aby nie pomijać kroku 2 . Aby to zadziałało, musisz wysłać aplikację do działania w tle przed zatrzymaniem procesu w DDMS. Dla tych, którzy zastanawiają się, skąd pochodzą cytaty z dokumentu, jest tutaj . Chociaż nie jestem pewien, czy są rzeczywiście związane z tematem, ponieważ dotyczy <activity>tagu w manifeście.
Tony Chan
1
Dokładnie to, czego potrzebowałem. Dziękuję Ci. Dla tych, którzy nie wiedzą, DDMS jest w Eclipse, przejdź do Window -> Open Perspective i powinieneś go tam znaleźć.
Richard,
4
Alternatywnie możesz przejść do „Opcji rozwoju” i ustawić limit tła na „brak procesów w tle”, a następnie za każdym razem, gdy naciśniesz przycisk home, proces zakończy się.
Joao Gavazzi
56

To wydaje się działać dla mnie:

adb shell am kill <package_name>

Różni się to od adb shell killwspomnianego w PO.

Zwróć uwagę, że pomoc do am killpolecenia mówi:

am kill: Kill all processes associated with <PACKAGE>.  Only kills.
  processes that are safe to kill -- that is, will not impact the user
  experience.

Tak więc nie zabije procesu, jeśli znajduje się na pierwszym planie. Wydaje się, że działa to tak, jak chciał OP, ponieważ jeśli opuszczę moją aplikację, a następnie uruchomię adb shell am kill <package_name>ją, zabije aplikację (potwierdziłem to psna urządzeniu). Następnie, jeśli wrócę do aplikacji, wrócę do działania, w którym byłem wcześniej - tj. W przykładzie OP proces zostaje odtworzony i tworzy ActivityD (zamiast ActivityC, jak większość innych metod zabijania wydaje się wyzwalać).

Przepraszam, że spóźniłem się kilka lat na OP, ale mam nadzieję, że inni uznają to za przydatne.

HexAndBugs
źródło
Dzięki! to jest to, czego szukałem! Chcę określić, że to polecenie zachowuje się inaczej niż adb shell am force-stop. Ta ostatnia usunie również wszystkie oczekujące Intencje związane z Twoją aplikacją (takie jak Powiadomienia), podczas gdy pierwsza nie.
bonnyz
Wskazuje każdemu, kto bada kod źródłowy systemu operacyjnego, aby zobaczyć, jaki kod uruchamia, gdy zabija proces odzyskiwania pamięci - zakładam, że jest to ten sam kod, co am kill.
androidguy
nie działa na Androidzie 7.1 Samsung J5. pspokazuje moją aplikację
Valgaal
17

Inna metoda, prawdopodobnie taka, która jest skryptowalna, ponieważ nie wymaga DDMS:

Konfiguracja jednorazowa: przejdź do opcji programisty, wybierz ustawienie limitu procesów w tle, zmień wartość z „Standardowy limit” na „Brak procesów w tle”.

Kiedy musisz ponownie uruchomić proces, naciśnij przycisk home. Proces zostanie zabity (możesz to sprawdzić w logcat / Android Monitor w studio - proces zostanie oznaczony jako [DEAD]). Następnie wróć do aplikacji za pomocą przełącznika zadań.

Merk
źródło
2
Ciekawy. Myślę, że to nie ma wpływu na usługi pierwszego planu, prawda?
IgorGanapolsky,
Muszę to zrobić na rzeczywistych urządzeniach z Androidem w wersji 2.3.3, więc to nie jest żadna pomoc.
David Wasser,
13

To pytanie jest stare, ale istnieje na nie odpowiedź, która nie wymaga adb, Android Studio itp. Jedynym wymaganiem jest API 23 lub nowsze.

Aby zasymulować ponowne uruchomienie aplikacji przez system operacyjny, przejdź do ustawień aplikacji, gdy aplikacja jest uruchomiona, wyłącz (a następnie możesz włączyć) uprawnienia i zwróć aplikację z ostatnich aplikacji. Gdy uprawnienia są wyłączone, system operacyjny zabija aplikację, ale zachowuje zapisane stany instancji. Gdy użytkownik zwraca aplikację, aplikacja i ostatnia aktywność (z zapisanym stanem) są odtwarzane.

Metoda „bez procesów w tle” czasami powoduje to samo zachowanie, ale nie zawsze. Na przykład, jeśli aplikacja działa w tle, „Brak procesów w tle” nic nie robi. Ale aplikacja może zostać zabita przez system, w tym jego usługi. Metoda uprawnień działa, nawet jeśli aplikacja ma usługę.

Przykład:

Nasza aplikacja ma dwa rodzaje aktywności. Działanie A jest głównym działaniem, które jest uruchamiane z programu uruchamiającego. AktywnośćB rozpoczyna się od Aktywności A. Pokażę tylko metody onCreate, onStart, onStop, onDestroy. Android wywołuje onSaveInstanceState zawsze przed wywołaniem onStop, ponieważ działanie, które jest w stanie zatrzymania, może zostać zabite przez system. [ https://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle]

Metoda pozwolenia:

<start app from launcher first time>
Application onCreate
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart
<open ActivityB>
ActivityB onCreate WITHOUT savedInstance
ActivityB onStart
ActivityA onStop (the order is like this, it is stopped after new one is started)
<go settings>
ActivityB onStop
<disable a permission>
//Application is killed, but onDestroy methods are not called.
//Android does not call onDestroy methods if app will be killed.
<return app by recent apps>
Application onCreate (this is the important part. All static variables are reset.)
ActivityB onCreate WITH savedInstance (user does not notice activity is recreated)
//Note that ActivityA is not created yet, do not try to access it.
ActivityB onStart
<return ActivityA by back>
ActivityA onCreate WITH savedInstance (user does not notice activity is recreated)
ActivityA onStart
ActivityB onStop
ActivityB onDestroy
<press back again, return launcher>
ActivityA onStop
ActivityA onDestroy
<open app again>
//does not call Application onCreate, app was not killed
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart

Chcę porównać inne metody, które są wymienione w innych odpowiedziach.

Nie zachowuj działań: nie powoduje to zabicia aplikacji.

<start app from launcher first time>
Application onCreate
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart
<open ActivityB>
ActivityB onCreate WITHOUT savedInstance
ActivityB onStart
ActivityA onStop
ActivityA onDestroy (do not keep)
<return launcher by home button>
ActivityB onStop
ActivityB onDestroy (do not keep) 
<retun app from recent apps>
// NO Application onCreate
ActivityB onCreate WITH savedInstance (user does not notice activity recreated)
ActivityB onStart
<return ActivityA by back>
ActivityA onCreate WITH savedInstance (user does not notice activity recreated)
ActivityA onStart
ActivityB onStop
ActivityB onDestroy
<press back again, return launcher>
ActivityA onStop
ActivityA onDestroy
<open app again>
//does not call Application onCreate, app was not killed
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart

Metoda wymuszania zatrzymania: nie przechowuje zapisanych stanów instancji

<start app from launcher first time>
Application onCreate
ActivityA onCreate WITHOUT savedInstance
ActivityA onStart
<open ActivityB>
ActivityB onCreate WITHOUT savedInstance
ActivityB onStart
ActivityA onStop
<go settings>
ActivityB onStop
<force stop, return app from recent apps>
Application onCreate
ActivityA onCreate WITHOUT savedInstance 
//This is important part, app is destroyed by user.
//Root activity of the task is started, not the top activity.
//Also there is no savedInstance.
fthdgn
źródło
~ " aplikacja może zostać zabita przez system łącznie z jej usługą ". Usługa nie na pierwszym planie ...
IgorGanapolsky
@DavidWasser Przeczytaj specyfikację! developer.android.com/guide/components/services.html#Foreground Usługa pierwszego planu to usługa, o której użytkownik jest aktywnie świadomy i która nie jest kandydatem do zabicia przez system, gdy brakuje pamięci.
IgorGanapolsky,
3
@IgorGanapolsky Dokumentacja jest fajna, zwłaszcza jeśli jest kompletna i poprawna (czego niestety nie jest), ale zwykle bardziej polegam na rzeczywistych osobistych obserwacjach. Wiele razy widziałem Servicezabijanie pierwszego planu . Nawet jeśli w systemie nie brakuje pamięci. Większość producentów urządzeń napisała własne „optymalizacje” i „ulepszenia” systemu operacyjnego Android w celu oszczędzania energii baterii. Wiele urządzeń ma znacznie bardziej agresywnych „zabójców” niż standardowy Android.
David Wasser,
@DavidWasser Uczciwa obserwacja. Czy po tych wszystkich latach znalazłeś rozwiązanie?
IgorGanapolsky,
@IgorGanapolsky Nie. Nie znalazłem rozwiązania tego problemu. Dlatego pytanie jest nadal otwarte.
David Wasser,
7

Jestem bardzo spóźniony na imprezę i kilka przede mną dało tę samą poprawną odpowiedź, ale aby uprościć to, kto przyjdzie po mnie, po prostu naciśnij przycisk home i uruchom to polecenie:

adb shell ps | grep <package name> | awk '{print $2}' | xargs adb shell run-as <package name again> kill

Aplikacja nie straci stanu iz własnego doświadczenia działa to tak samo, jak system operacyjny zabił aplikację w tle. Działa to tylko w przypadku aplikacji do debugowania

Hirschen
źródło
Dostaję'grep' is not recognized as an internal or external command, operable program or batch file.
Dale
Ale zrobiłem to będąc w powłoce run-as <package name> kill 7379, ale przeniosło mnie do poprzedniej czynności, a nie do czynności, w której byłem, kiedy nacisnąłem przycisk Home.
Dale
6

Tak to się robi w Android Studio.

  1. Podłącz urządzenie w trybie debugowania do komputera.
  2. Otwórz aplikację na swoim urządzeniu i przejdź do dowolnego działania, które chcesz przetestować, „Wróć do tego z martwych”.
  3. Naciśnij przycisk Home na swoim urządzeniu.
  4. W Android Studio przejdź do Android Monitor -> Monitory i naciśnij ikonę Zakończ aplikację.
  5. Teraz możesz wrócić do swojej aplikacji za pośrednictwem ostatnich aplikacji lub klikając ikonę programu uruchamiającego, zachowanie było takie samo w moich testach.
dbar
źródło
2
To nie jest żadna pomoc. Muszę to zrobić programowo, w zestawie testów. Ale i tak dzięki.
David Wasser
Ponadto ta odpowiedź jest prawie taka sama, jak odpowiedź Marka.
David Wasser
Masz pomysł, jak to zrobić przez UIAutomator lub Espresso?
IgorGanapolsky,
Nie mogę znaleźć Android Monitor - Monitors. To musi być coś, czego się pozbyli. Jestem w wersji 3.2.1
Dale
1
@Dale Android Device Monitor został wycofany w Android Studio 3.1 i usunięty z Android Studio 3.2.
Valgaal
5

Umieść aplikację w tle za pomocą przycisku HOME

Wybierz proces w trybie „Logcat” w Android Studio, a następnie kliknij Zakończ aplikację w lewym dolnym rogu

przycisk zakończenia

Teraz uruchom aplikację z programu uruchamiającego na urządzeniu z Androidem


EDYCJA: Według internetu działa również:

 adb shell am kill [my-package-name]

EDYCJA z przyszłości: Coś do odnotowania, nastąpiła zmiana w Android Studio 4.0, jeśli używasz Runz AS, to Terminatewyda plik Force Stop.

Jeśli jednak później uruchomisz program uruchamiający, a NASTĘPNIE spróbujesz to zasymulować w ten sposób, uzyskasz pożądane wyniki (zachowanie małej ilości pamięci).

EpicPandaForce
źródło
To jest zduplikowana odpowiedź
Onik
@Onik Wszyscy inni mają mnóstwo niepotrzebnych puchów, takich jak ddms i cokolwiek. Chociaż technicznie tak, stackoverflow.com/a/41975750/2413303 mówi to samo. Może powinienem dodać zdjęcia.
EpicPandaForce,
To nie jest pomocne. Mam uprząż testową i nie mogę wykonać tych czynności z uprzęży testowej. Ponadto zachowanie nie jest takie samo, jak to, co dzieje się, gdy Android zabija proces.
David Wasser,
the behaviour is not the same as what happens when Android kills the processtak, to jest
EpicPandaForce,
Ten proces pokazuje mi poprzednią czynność, a nie aktywność po naciśnięciu przycisku strony głównej.
Dale
2

Możesz wykonać kolejne kroki, aby odtworzyć pożądane zachowanie:

  1. Otwórz aplikację, przejdź do najwyższej aktywności
  2. Użyj panelu powiadomień, aby przejść do dowolnej innej aplikacji pełnoekranowej (na przykład do ustawień systemu - w prawym górnym rogu)
  3. Zakończ proces aplikacji
  4. Naciśnij przycisk Wstecz
Igor Kostomin
źródło
1
Dziękuję za odpowiedź, ale nie jest to dla mnie przydatne, ponieważ potrzebuję zautomatyzowanego sposobu, aby to zrobić, do automatycznego testowania.
David Wasser,
Jest to więc jedyna metoda, którą znalazłem, która faktycznie symuluje czyszczenie pamięci Androida i zabijanie aplikacji (mój poziom API to 19, więc nie mogę użyć polecenia send-trim-memory). Inne polecenia, takie jak adb shell am force-stop com.my.app.package lub kill, nie będą odtwarzać dokładnie tego samego procesu, co po wykonaniu powyższej procedury!
Mark Garcia,
2

W opcjach programisty w Ustawieniach wybierz „Nie zachowuj działań”, co spowoduje zniszczenie działań, gdy tylko odejdziesz od nich.

Uwaga: zgodnie z pomocnym komentarzem poniżej, używaj tego tylko wtedy, gdy nie zależy Ci na czyszczeniu wartości statycznych.

MSpeed
źródło
W praktyce jest to to samo, co rozwiązanie już opublikowane - i odrzucone - rok temu. Jedyną różnicą wydaje się być aplikacja używana do ustawienia go na emulatorze, w porównaniu z nowszymi telefonami, które go obsługują.
Chris Stratton
1
Przepraszam, jak mówi Chris Stratton, jest to prawie taka sama sugestia, jak druga odpowiedź. Tu nie chodzi o działania wykańczające Androida. Chodzi o Androida, który zabija cały proces (co robi, dość regularnie i skutecznie, szczególnie na urządzeniach HTC z systemem Android 4.x).
David Wasser
6
Ten jest prawie dobry, ale nie zabije procesu, a jedynie niszczy aktywność. Co to znaczy? Twoja aktywność zostanie otwarta za pomocą saveInstanceState, ale wszystkie zmienne statyczne są nadal przetwarzane. Po zabiciu procesu wszystkie zmienne statyczne są również usuwane.
Mark
1

Naciśnij przycisk Początek i najpierw umieść aplikację w tle. Następnie zatrzymaj lub zakończ proces z DDMS lub ADB.

Monstieur
źródło
Dziękuję za odpowiedź, ale nie jest to dla mnie przydatne, ponieważ potrzebuję zautomatyzowanego sposobu, aby to zrobić, do automatycznego testowania.
David Wasser,
Android nigdy nie zabije twojego procesu, jeśli twoja aktywność jest obecnie na pierwszym planie. Próbujesz przetestować stan, który nigdy nie wystąpi. Jeśli twoja aktywność jest w tle, to jej stan został już zapisany i nie ma różnicy między tym, że zabijasz ją ręcznie, a Androidem zabijasz ją przy małej ilości pamięci, tj. Proces jest właśnie zabijany; nie ma nic specjalnego w niskim zabiciu pamięci. Gdy pamięć będzie ponownie dostępna, usługi Sticky Notes zostaną ponownie uruchomione (z wyjątkiem wersji 4.4), a po dotknięciu ikony lub ostatniego zadania stos i stan aktywności zostaną przywrócone.
Monstieur,
3
W twoim przykładzie wraca do działania C, ponieważ zabiłeś proces, gdy działanie D było widoczne na ekranie (to nigdy nie nastąpi nawet przy małej ilości pamięci), a stan działania C został zapisany, ponieważ jest w tle. Twój proces zostanie zabity tylko wtedy, gdy w ogóle nie znajduje się na pierwszym planie, tj. Stan działania D zostałby zapisany, gdy przeszedł w tło, a zatem zostanie przywrócony, nawet jeśli proces zostanie zabity. Aby przeprowadzić testy na każdym działaniu, MUSISZ najpierw wysłać aplikację w tło, zanim ją zabijesz.
Monstieur,
Co masz na myśli, mówiąc ~ „ i najpierw umieść aplikację w tle ”?
Igor Ganapolsky
1

Możesz także połączyć się ze swoim urządzeniem / emulatorem z terminala za pomocą adb shell, a następnie uzyskać PID swojego procesu ps | grep <your_package_namei wykonać kill -9 <pid>. Następnie otwórz zminimalizowaną aplikację z selektora ostatnich aplikacji i uruchom ponownie ostatnią aktywność

qbasso
źródło
Czy to to samo, co Android zabija proces w warunkach małej ilości pamięci? Myślę, że OP specjalnie tego chciał ...
IgorGanapolsky
1
@IgorGanapolsky teoretycznie jest, chociaż nie można tego zrobić na rzeczywistym urządzeniu, jeśli nie jest zrootowane.
Fran Marzoa
0

Wydaje się, że źródłem twojego problemu jest to, że jesteś Activityna pierwszym planie, gdy zabijasz proces.

Możesz to zaobserwować, naciskając przycisk zatrzymania w DDMS, gdy Activityjest widoczny (dzieje się dokładnie tak, jak opisujesz ) i porównując to z naciśnięciem przycisku zatrzymania po powrocie do domu i późniejszym powrotem do aplikacji.

Po prostu upewnij się, że moveTaskToBack(true)jakoś w swoich testach.

MaciejGórski
źródło
0

Nie jestem pewien, czy to jest odpowiedź, której szukasz, to bardziej jak myślenie logiczne.

Nie sądzę, że naprawdę można wykonać w pełni zautomatyzowany test, jedynym sposobem na jego symulację będzie jego odtworzenie, AKA ma tak wiele działań, że Android zabije twoją aplikację.

Więc moim pomysłem lub sugestią jest zrobienie kolejnej małej aplikacji, która ciągle wyskakuje nowe działania, dopóki Androidowi nie zabraknie pamięci i zacznie zabijać proces w tle.

Coś wśród linii:

Rozpocznij czynność i -> Sprawdź uruchomiony proces, czy aplikacja znajduje się na liście, zwiększ i ponownie uruchom pętlę bez zamykania bieżącej czynności, w przeciwnym razie -> zmniejsz i i zamknij bieżącą czynność, wróć do poprzedniej i sprawdź ponownie ...

Emil Borconi
źródło
0

Kiedy proces aplikacji kończy się, Android przegląda rekordy działań (wpisy reprezentują działania na stosie historii) i podejmuje decyzję które z nich zachować w historii, a które usunąć z niej.

Jednym z kluczowych punktów jest tutaj ActivityRecordzwane pole haveState, które inżynierowie Android Framework opisują jako „czy uzyskaliśmy ostatni stan aktywności?”.

Domyślnie system Android uważa, że aktywność ma stan. Aktywność staje się bezstanowa, gdy aplikacja zgłasza do usługi menedżera zadań działań, że działanie zostało wznowione i jest to ważne, dopóki aplikacja nie powiadomi struktury, że działanie weszło w stan zatrzymania. W prostych słowach, haveStatewartość znajduje się falsemiędzy aktywnością onResume()jest wywoływana i / onStop()lub onSaveInstanceState()jest wywoływana, w zależności od wersji docelowej aplikacji.

Jeśli zabiję proces, Android odtwarza proces i tworzy ActivityC.

W tym przypadku ActivityD nie ma android:stateNotNeeded="true"atrybutu w manifeście aplikacji i obecnie działa na pierwszym planie, więc Android usuwa go z historii, ponieważ system nie uzyskał ostatniego stanu.

Jak symulować Androida zabijającego mój proces

Jak już kilkakrotnie wspominano, wystarczy po prostu przenieść aplikację w tło, dzięki czemu najwyższa aktywność w stosie aktywności zapisze jej stan, a następnie można zabić proces aplikacji za pomocą Android Debug Bridge, Android Studio lub za pomocą Właściwość Limit procesów w tle w Opcjach programisty. Następnie Twoja ostatnia aktywność zostanie pomyślnie odtworzona.

Mimo to istnieje również inny prosty sposób na przetestowanie scenariusza śmierci procesu aplikacji. Znając wszystkie opisane powyżej i fakt, że jeśli uruchomisz nowe ActivityE z aktualnie uruchomionego ActivityD, wtedy onStop()wywołanie zwrotne ActivityD zostanie wywołane dopiero po onResume()metodzie ActivityE , możesz wykonać następującą sztuczkę.

class TerminatorActivity : Activity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val isPrePie = applicationInfo.targetSdkVersion < Build.VERSION_CODES.P
        val callbacks = TerminatorLifecycleCallbacks(isPrePie)
        (applicationContext as Application).registerActivityLifecycleCallbacks(callbacks)
    }

    private class TerminatorLifecycleCallbacks(
        // Before P onSaveInstanceState() was called before onStop(), starting with P it's
        // called after
        // Used to schedule the death as app reports server that activity has stopped
        // after the latest of these was invoked
        private val isPrePie: Boolean
    ) : ActivityLifecycleCallbacksDefault {

        private val handler = Handler(Looper.getMainLooper())

        override fun onActivityPostStopped(activity: Activity) {
            if (isPrePie) {
                terminate()
            }
        }

        override fun onActivityPostSaveInstanceState(activity: Activity, outState: Bundle) {
            if (!isPrePie) {
                terminate()
            }
        }

        fun terminate() {
            handler.postDelayed(
                {
                    Process.killProcess(Process.myPid()) // This is the end... 
                },
                LAST_MILLIS
            )
        }

        companion object {
            // Let's wait for a while, so app can report and server can handle the update
            const val LAST_MILLIS = 100L
        }

    }

    private interface ActivityLifecycleCallbacksDefault : Application.ActivityLifecycleCallbacks {
        override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
        override fun onActivityStarted(activity: Activity) {}
        override fun onActivityResumed(activity: Activity) {}
        override fun onActivityPaused(activity: Activity) {}
        override fun onActivityStopped(activity: Activity) {}
        override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
        override fun onActivityDestroyed(activity: Activity) {}
    }
}

Następnie po prostu zacznij, TerminatorActivitygdy chcesz zabić aplikację.

Na końcu znajduje się lekkie narzędzie, które upraszcza testowanie śmierci procesu aplikacji, zwane Venom .

ivkil
źródło