Wie man simuliert, dass Android meinen Prozess beendet

174

Android beendet einen Prozess, wenn er sich im Hintergrund befindet und das Betriebssystem entscheidet, dass es die Ressourcen (RAM, CPU usw.) benötigt. Ich muss in der Lage sein, dieses Verhalten während des Testens zu simulieren, damit ich sicherstellen kann, dass sich meine Anwendung korrekt verhält. Ich möchte dies auf automatisierte Weise tun können, damit ich testen kann, ob sich die Anwendung in diesem Fall korrekt verhält, was bedeutet, dass ich dies bei jeder Aktivität usw. testen muss.

Ich weiß, wie ich meinen Prozess beenden kann. Das ist nicht das Problem. Das Problem ist , dass , wenn ich meinen Prozess (mit DDMS, töten adb shell kill, Process.killProcess()usw.) Android nicht es die gleiche Art und Weise neu zu starten , dass es würde , wenn das Android OS es selbst getötet hatte.

Wenn das Android-Betriebssystem den Prozess abbricht (aufgrund von Ressourcenanforderungen), erstellt Android den Prozess neu, wenn der Benutzer zur Anwendung zurückkehrt, und erstellt dann die oberste Aktivität auf dem Aktivitätsstapel neu (Aufruf onCreate()).

Wenn ich den Prozess hingegen abbrich, geht Android davon aus, dass sich die Aktivität oben auf dem Aktivitätsstapel schlecht verhalten hat. Daher wird der Prozess automatisch neu erstellt und anschließend die oberste Aktivität aus dem Aktivitätsstapel entfernt und die darunter liegende Aktivität neu erstellt die oberste Aktivität (Aufruf von onCreate () `). Dies ist nicht das Verhalten, das ich will. Ich möchte das gleiche Verhalten wie wenn Android den Prozess abbricht.

Nur um es bildlich zu erklären, wenn mein Aktivitätsstapel so aussieht:

    ActivityA -> ActivityB -> ActivityC -> ActivityD

Wenn Android den Prozess abbricht und der Benutzer zur Anwendung zurückkehrt, erstellt Android den Prozess neu und erstellt ActivityD.

Wenn ich den Prozess abbreche, erstellt Android den Prozess neu und erstellt ActivityC.

David Wasser
quelle
4
Könnten Sie nicht einfach die Anzahl der Prozesse erstellen, die erforderlich sind, um Ihre im Hintergrund zu beenden?
Alex W
2
@Pang Ich denke du verpasst den Punkt. Ich weiß, wie ich feststellen kann, dass Android den Prozess beendet hat. Ich habe Code, der diese Bedingungen behandelt. Was ich tun möchte, ist, diesen Code richtig (und auf automatisierte Weise) zu testen . Dazu brauche ich eine Möglichkeit, Android zu provozieren, um meinen Prozess genauso zu beenden, wie es normalerweise unter Ressourcendruck der Fall wäre. Die verknüpfte Frage ist zwar interessant, bringt aber hier keinen Mehrwert.
David Wasser
@IgorGanapolsky Danke für die Links, aber eigentlich hat keiner dieser Links Lösungen für das Problem.
David Wasser

Antworten:

127

Der beste Weg, dies für mich zu testen, war Folgendes:

  • Öffnen Sie ActivityD in Ihrer Anwendung
  • Drücken Sie die Home-Taste
  • Drücken Sie Terminate Applicationin Logcat Fenster in Android Studio (dies wird die App Prozess töten, stellen Sie sicher , wählen Sie Ihr Gerät und Verfahren in Logcat Aufklappmenü oben)
  • Kehren Sie mit langem Drücken oder geöffneten Apps (je nach Gerät) zur Anwendung zurück.
  • Die Anwendung wird in neu erstelltem ActivityD gestartet (ActivityA, ActivityB, ActivityC sind tot und werden neu erstellt, wenn Sie zu ihnen zurückkehren).

Auf einigen Geräten können Sie auch über Anwendungen -> Ihr Startsymbol zur Anwendung (ActivityD) zurückkehren. Auf anderen Geräten wird stattdessen ActivityA gestartet.

Dies ist, was Android-Dokumente dazu sagen:

Normalerweise löscht das System in bestimmten Situationen eine Aufgabe (entfernt alle Aktivitäten vom Stapel über der Stammaktivität), wenn der Benutzer diese Aufgabe auf dem Startbildschirm erneut auswählt. Dies geschieht normalerweise, wenn der Benutzer die Aufgabe eine bestimmte Zeit lang nicht besucht hat, z. B. 30 Minuten.

Kennzeichen
quelle
2
Vielen Dank für Ihre Antwort, aber es ist für mich nicht nützlich, da ich dafür einen automatisierten Weg zum automatisierten Testen benötige.
David Wasser
1
Das war sehr hilfreich für mich.
John Roberts
6
Dies ist nicht automatisiert, aber es hat perfekt für meine Zwecke funktioniert. Es ist sehr wichtig, Schritt 2 nicht zu überspringen . Sie müssen die App in den Hintergrund senden, bevor Sie den Prozess in DDMS stoppen, damit dies funktioniert. Für diejenigen, die sich fragen, woher die Dokumentzitate stammen, ist es hier . Obwohl ich nicht sicher bin, ob sie tatsächlich mit dem Thema zusammenhängen, da es sich um das <activity>Tag im Manifest handelt.
Tony Chan
1
Genau das, was ich brauchte. Danke dir. Für diejenigen, die nicht wissen, dass sich DDMS in Eclipse befindet, gehen Sie zu Fenster -> Perspektive öffnen, und Sie sollten es dort finden.
Richard
4
Alternativ können Sie zu "Entwicklungsoptionen" gehen und das Hintergrundlimit auf "Keine Hintergrundprozesse" setzen. Jedes Mal, wenn Sie nach Hause drücken, wird der Prozess beendet.
Joao Gavazzi
56

Das scheint bei mir zu funktionieren:

adb shell am kill <package_name>

Dies unterscheidet sich adb shell killvon der vom OP erwähnten.

Beachten Sie, dass die Hilfe für den am killBefehl lautet:

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

Der Prozess wird also nicht abgebrochen, wenn er im Vordergrund steht. Dies scheint so zu funktionieren, wie es das OP wollte. Wenn ich von meiner App weg navigiere und sie dann ausführe adb shell am kill <package_name>, wird die App beendet (ich habe dies psauf dem Gerät bestätigt). Wenn ich dann zur App zurückkehre, bin ich wieder in der Aktivität, in der ich zuvor war - dh im Beispiel des OP wird der Prozess neu erstellt und erstellt ActivityD (anstelle von ActivityC, wie es die meisten anderen Tötungsmethoden auslösen).

Es tut mir leid, dass ich ein paar Jahre zu spät zum OP komme, aber hoffentlich finden andere dies nützlich.

HexAndBugs
quelle
Vielen Dank! das habe ich gesucht! Ich möchte angeben, dass sich dieser Befehl anders verhält als adb shell am force-stop. Der letzte entfernt auch alle anstehenden Inhalte, die mit Ihrer App zusammenhängen (wie Benachrichtigungen), während der erste dies nicht tut.
Bonnyz
Zeigt auf jeden, der den Quellcode des Betriebssystems untersucht, um festzustellen, welcher Code ausgeführt wird, wenn ein Prozess zum Zurückgewinnen von Speicher abgebrochen wird. Ich wette, es ist derselbe Code wie am kill.
AndroidGy
funktioniert nicht unter Android 7.1 Samsung J5. pszeigt meine App
Valgaal
17

Eine andere Methode, wahrscheinlich eine, die skriptfähig ist, da sie kein DDMS erfordert:

Einmalige Einrichtung: Gehen Sie zu Entwickleroptionen, wählen Sie Einstellung für Hintergrundprozesslimit, ändern Sie den Wert von 'Standardlimit' in 'Keine Hintergrundprozesse'.

Wenn Sie den Vorgang neu starten müssen, drücken Sie die Home-Taste. Der Prozess wird abgebrochen (Sie können dies in logcat / Android Monitor in Studio überprüfen - der Prozess wird mit [DEAD] markiert). Wechseln Sie dann mit dem Task-Umschalter zurück zur App.

Merk
quelle
2
Interessant. Ich denke, das wirkt sich nicht auf Foreground Services aus, oder?
IgorGanapolsky
Ich muss dies auf tatsächlichen Geräten tun, auf denen Android ab 2.3.3 ausgeführt wird, daher ist dies keine Hilfe.
David Wasser
13

Diese Frage ist alt, aber es gibt eine Antwort auf diese Frage, für die kein ADB, Android Studio usw. erforderlich ist. Die einzige Anforderung ist API 23 oder neuer.

Um einen App-Neustart nach Betriebssystem zu simulieren, gehen Sie zu den App-Einstellungen, während Ihre App ausgeführt wird, deaktivieren Sie eine Berechtigung (dann können Sie sie aktivieren) und geben Sie die App von den letzten Apps zurück. Wenn die Berechtigung deaktiviert ist, beendet das Betriebssystem die App, behält jedoch die gespeicherten Instanzzustände bei. Wenn der Benutzer die App zurückgibt, werden die App und die letzte Aktivität (mit gespeichertem Status) neu erstellt.

Die Methode "Keine Hintergrundprozesse" verursacht manchmal dasselbe Verhalten, aber nicht immer. Wenn in der App beispielsweise ein Hintergrunddienst ausgeführt wird, führt "Keine Hintergrundprozesse" nichts aus. Die App kann jedoch vom System einschließlich seiner Dienste beendet werden. Die Berechtigungsmethode funktioniert auch dann, wenn die App über einen Dienst verfügt.

Beispiel:

Unsere App hat zwei Aktivitäten. AktivitätA ist die Hauptaktivität, die vom Launcher aus gestartet wird. Aktivität B wird von Aktivität A gestartet. Ich werde nur die Methoden onCreate, onStart, onStop und onDestroy anzeigen. Android ruft onSaveInstanceState immer vor dem Aufruf von onStop auf, da eine Aktivität, die sich im Stoppzustand befindet, vom System beendet werden kann. [ https://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle]

Berechtigungsmethode:

<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

Ich möchte andere Methoden vergleichen, die in den anderen Antworten erwähnt werden.

Aktivitäten nicht behalten: Dies beendet die Anwendung nicht.

<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

Stop-Methode erzwingen: Speichert keine gespeicherten Instanzzustände

<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
quelle
~ " App kann vom System einschließlich seines Dienstes getötet werden ". Nicht Vordergrund Service ...
IgorGanapolsky
@ DavidWasser Lesen Sie die Spezifikation! developer.android.com/guide/components/services.html#Foreground Ein Vordergrunddienst ist ein Dienst, den der Benutzer aktiv kennt, und kein Kandidat für das System, das bei geringem Arbeitsspeicher beendet werden soll.
IgorGanapolsky
3
@IgorGanapolsky Die Dokumentation ist nett, besonders wenn sie vollständig und korrekt ist (was leider nicht der Fall ist), aber ich verlasse mich normalerweise mehr auf tatsächliche persönliche Beobachtungen. Ich habe einen Vordergrund Serviceoft getötet gesehen . Auch wenn das System nicht über genügend Speicher verfügt. Die meisten Gerätehersteller haben ihre eigenen "Optimierungen" und "Verbesserungen" für das Android-Betriebssystem geschrieben, um Batteriestrom zu sparen. Viele Geräte haben viel aggressivere "Killer" als Standard-Android.
David Wasser
@ DavidWasser Messebeobachtung. Haben Sie nach all den Jahren eine Lösung gefunden?
IgorGanapolsky
@IgorGanapolsky Nein. Ich habe keine Lösung für dieses Problem gefunden. Deshalb ist die Frage noch offen.
David Wasser
7

Ich bin sehr spät zur Party und einige vor mir gaben die gleiche richtige Antwort, aber um es für jeden zu vereinfachen, der nach mir kommt, drücken Sie einfach die Home-Taste und führen Sie diesen Befehl aus:

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

Die App verliert nicht den Status und meiner Erfahrung nach funktioniert dies genauso, wie das Betriebssystem die App im Hintergrund beendet hat. Dies funktioniert nur für Debug-Anwendungen

Hirschen
quelle
Ich bekomme'grep' is not recognized as an internal or external command, operable program or batch file.
Dale
Aber ich habe es getan, während ich in der Shell war run-as <package name> kill 7379, aber es hat mich zur vorherigen Aktivität gebracht, nicht zur Aktivität, bei der ich war, als ich den Home-Knopf gedrückt habe.
Dale
6

So machen Sie es in Android Studio.

  1. Lassen Sie Ihr Gerät im Debug-Modus an Ihren Computer anschließen.
  2. Öffnen Sie die App auf Ihrem Gerät und gehen Sie zu der Aktivität, die Sie testen möchten, und kehren Sie von den Toten zurück.
  3. Drücken Sie die Home-Taste auf Ihrem Gerät.
  4. Gehen Sie in Android Studio zu Android Monitor -> Monitore und klicken Sie auf das Symbol Anwendung beenden.
  5. Jetzt können Sie entweder über die letzten Apps zu Ihrer App zurückkehren oder durch Klicken auf das Startsymbol klicken. In meinen Tests war das Verhalten das gleiche.
dbar
quelle
2
Das ist keine Hilfe. Ich muss dies programmgesteuert innerhalb einer Testsuite tun. Danke trotzdem.
David Wasser
Auch diese Antwort ist so ziemlich die gleiche wie die Antwort von Mark.
David Wasser
Irgendeine Idee, wie man das über UIAutomator oder Espresso macht?
IgorGanapolsky
Ich kann nicht finden Android Monitor - Monitors. Muss etwas sein, das sie losgeworden sind. Ich bin auf v 3.2.1
Dale
1
@Dale Android Device Monitor war in Android Studio 3.1 veraltet und wurde aus Android Studio 3.2 entfernt.
Valgaal
5

Stellen Sie die Anwendung mit der HOME-Schaltfläche in den Hintergrund

Wählen Sie Ihren Prozess im "Logcat" -Modus in Android Studio aus und klicken Sie dann in der unteren linken Ecke auf "Anwendung beenden"

Schaltfläche zum Beenden

Starten Sie jetzt Ihre App vom Launcher auf einem Android-Gerät


EDIT: Laut Internet funktioniert auch folgendes:

 adb shell am kill [my-package-name]

BEARBEITEN aus der Zukunft: Es ist zu beachten, dass in Android Studio 4.0 eine Änderung vorgenommen wurde. Wenn Sie RunAS verwenden, Terminatewird a ausgegeben Force Stop.

Wenn Sie jedoch anschließend vom Launcher aus starten und dann versuchen, dies auf diese Weise zu simulieren, erhalten Sie die gewünschten Ergebnisse (geringes Speicherverhalten).

EpicPandaForce
quelle
Dies ist eine doppelte Antwort
Onik
@Onik Alle anderen haben eine Menge unnötiger Flusen wie ddms und was auch immer. Obwohl technisch ja, sagt stackoverflow.com/a/41975750/2413303 dasselbe. Vielleicht sollte ich Bilder hinzufügen.
EpicPandaForce
Das ist nicht hilfreich. Ich habe ein Testkabel und kann diese Aktionen nicht über das Testkabel ausführen. Außerdem ist das Verhalten nicht dasselbe wie das, was passiert, wenn Android den Prozess abbricht.
David Wasser
the behaviour is not the same as what happens when Android kills the processJa, das ist es
EpicPandaForce
Dieser Vorgang zeigt mir die vorherige Aktivität, nicht die Aktivität, wenn die Home-Taste gedrückt wird.
Dale
2

Sie können die nächsten Schritte ausführen, um das gesuchte Verhalten zu reproduzieren:

  1. Öffnen Sie Ihre App und navigieren Sie zu den wichtigsten Aktivitäten
  2. Verwenden Sie das Benachrichtigungsfeld, um zu einer anderen Vollbildanwendung zu navigieren (z. B. zu den Systemeinstellungen - in der rechten oberen Ecke).
  3. Beenden Sie Ihren Bewerbungsprozess
  4. Drücken Sie die Zurück-Taste
Igor Kostomin
quelle
1
Vielen Dank für Ihre Antwort, aber es ist für mich nicht nützlich, da ich dafür einen automatisierten Weg zum automatisierten Testen benötige.
David Wasser
Dies ist also die einzige Methode, die ich gefunden habe, um das Löschen des Speichers durch Android und das Beenden Ihrer App zu simulieren (meine API-Stufe ist 19, daher kann ich den Befehl send-trim-memory nicht verwenden). Andere Befehle wie adb shell am force-stop com.my.app.package oder kill reproduzieren nicht genau den gleichen Vorgang wie nach dem obigen Verfahren!
Mark Garcia
2

Wählen Sie in den Entwickleroptionen unter "Einstellungen" die Option "Aktivitäten nicht beibehalten" aus. Dadurch werden Aktivitäten zerstört, sobald Sie von ihnen weg navigieren.

Hinweis: Verwenden Sie dies gemäß einem hilfreichen Kommentar unten nur, wenn Sie sich nicht darum kümmern, dass statische Werte gelöscht werden.

MSpeed
quelle
Dies entspricht praktisch der Lösung, die bereits vor einem Jahr veröffentlicht und abgelehnt wurde. Der einzige Unterschied scheint die Anwendung zu sein, mit der es auf einem Emulator eingestellt wird, im Vergleich zu den neueren Telefonen, die es unterstützen.
Chris Stratton
1
Entschuldigung, wie Chris Stratton sagt, dies ist so ziemlich der gleiche Vorschlag wie die andere Antwort. Hier geht es nicht um Android-Finishing-Aktivitäten. Hier geht es darum, dass Android den gesamten Prozess beendet (was ziemlich regelmäßig und effektiv geschieht, insbesondere auf HTC-Geräten mit Android 4.x).
David Wasser
6
Dieser ist fast gut, aber er wird den Prozess nicht beenden, sondern nur die Aktivität zerstören. Was heißt das? Ihre Aktivität wird mit savedInstanceState geöffnet, aber alle statischen Variablen sind noch in Bearbeitung. Nach dem Prozessabbruch werden auch alle statischen Variablen gelöscht.
Mark
1

Drücken Sie die Home-Taste und stellen Sie die App zuerst in den Hintergrund. Stoppen oder beenden Sie dann den Prozess über DDMS oder ADB.

Monstieur
quelle
Vielen Dank für Ihre Antwort, aber es ist für mich nicht nützlich, da ich dafür einen automatisierten Weg zum automatisierten Testen benötige.
David Wasser
Android wird Ihren Prozess niemals beenden, wenn Ihre Aktivität derzeit im Vordergrund steht. Sie versuchen, einen Zustand zu testen, der niemals auftreten wird. Wenn sich Ihre Aktivität im Hintergrund befindet, wurde ihr Status bereits gespeichert, und es gibt keinen Unterschied zwischen dem manuellen Beenden und dem Beenden von Android bei geringem Arbeitsspeicher, dh der Vorgang wird nur abgebrochen. Es ist nichts Besonderes an einem Kill mit geringem Speicher. Wenn der Speicher wieder verfügbar ist, werden Ihre Sticky Services neu gestartet (außer in 4.4). Wenn Sie auf das Symbol oder die letzte Aufgabe tippen, werden der Stapel- und Aktivitätsstatus wiederhergestellt.
Monstieur
3
In Ihrem Beispiel wird auf Aktivität C zurückgegriffen, da Sie den Prozess abgebrochen haben, während Aktivität D auf dem Bildschirm sichtbar war (dies wird auch bei geringem Arbeitsspeicher niemals auftreten) und der Status von Aktivität C gespeichert wurde, da er sich im Hintergrund befindet. Ihr Prozess wird nur beendet, wenn er überhaupt nicht im Vordergrund steht, dh der Status von Aktivität D wäre gespeichert worden, als er in den Hintergrund trat, und wird somit auch dann wiederhergestellt, wenn Ihr Prozess beendet wird. Um Ihre Tests für jede Aktivität durchzuführen, MÜSSEN Sie die App zuerst in den Hintergrund senden, bevor Sie sie beenden.
Monstieur
Was hast du mit ~ "gemeint und die App zuerst in den Hintergrund gestellt "?
IgorGanapolsky
1

Sie können auch vom Terminal mit eine Verbindung zu Ihrem Gerät / Emulator herstellen adb shell, dann die PID Ihres Prozesses mit ps | grep <your_package_nameabrufen und ausführen kill -9 <pid>. Öffnen Sie dann Ihre minimierte App über die Auswahl der letzten Apps und die letzte Aktivität wird neu gestartet

qbasso
quelle
Ist das dasselbe wie Android, das einen Prozess unter Bedingungen mit wenig Arbeitsspeicher beendet? Ich denke, OP wollte das speziell ...
IgorGanapolsky
1
@IgorGanapolsky ist theoretisch, obwohl Sie das auf einem tatsächlichen Gerät nicht tun könnten, wenn es nicht gerootet ist.
Fran Marzoa
0

Die Wurzel Ihres Problems scheint zu sein, dass Sie Activityim Vordergrund stehen, wenn Sie den Prozess beenden.

Sie können dies beobachten, indem Sie in DDMS auf Stopp drücken, wenn dies Activitysichtbar ist (passiert genau das, was Sie beschreiben) und dies mit dem Drücken von Stopp nach dem Start und dem späteren Zurückkehren zur App vergleichen.

moveTaskToBack(true)Stellen Sie einfach sicher, dass Sie in Ihren Tests irgendwie.

MaciejGórski
quelle
0

Ich bin mir nicht sicher, ob dies die Antwort ist, nach der Sie suchen. Es ist eher ein logischer Gedanke.

Ich glaube nicht, dass Sie wirklich einen vollautomatischen Test durchführen können. Die einzige Möglichkeit, ihn zu simulieren, besteht darin, ihn neu zu erstellen. Die AKA hat so viele Aktivitäten, dass Android Ihre Anwendung beendet.

Meine Idee oder mein Vorschlag ist es also, eine weitere kleine App zu erstellen, die immer wieder neue Aktivitäten aufwirft, bis Android nicht mehr über genügend Speicher verfügt, und den Hintergrund im Hintergrund zu beenden.

Etwas in der Zeile:

Aktivität starten i -> Überprüfen Sie den laufenden Prozess, wenn die App in der Liste enthalten ist, erhöhen Sie i und starten Sie die Schleife neu, ohne die aktuelle Aktivität zu schließen. Andernfalls -> verringern Sie i und schließen Sie die aktuelle Aktivität, kehren Sie zur vorherigen zurück und überprüfen Sie erneut ...

Emil Borconi
quelle
0

Wenn der Bewerbungsprozess abbricht, durchläuft Android die Aktivitätsdatensätze (die Einträge stellen Aktivitäten im Verlaufsstapel dar) und entscheidet, welche im Verlauf gespeichert und welche aus dem Verlauf entfernt werden sollen.

Einer der wichtigsten Punkte ist das ActivityRecordFeld haveState, das von Android Framework-Ingenieuren als "Haben wir den letzten Aktivitätsstatus erhalten?" Beschrieben wird .

Standardmäßig geht Android davon aus , dass die Aktivität einen Status hat. Die Aktivität wird zustandslos, wenn die Anwendung dem Aktivitäts-Task-Manager-Dienst meldet , dass die Aktivität wieder aufgenommen wurde. Dies gilt so lange, bis die Anwendung dem Framework mitteilt, dass die Aktivität in den Status Gestoppt versetzt wurde. In einfachen Worten, der haveStateWert falsezwischen Aktivität onResume()wird aufgerufen und / onStop()oder onSaveInstanceState()aufgerufen, abhängig von der Anwendungszielversion.

Wenn ich den Prozess abbreche, erstellt Android den Prozess neu und erstellt ActivityC.

In diesem Fall hat ActivityD kein android:stateNotNeeded="true"Attribut im Anwendungsmanifest und wird derzeit im Vordergrund ausgeführt. Daher entfernt Android es aus dem Verlauf, da das System seinen letzten Status nicht erhalten hat.

Wie man simuliert, dass Android meinen Prozess beendet

Wie bereits mehrfach erwähnt, können Sie die Anwendung einfach in den Hintergrund verschieben, sodass die oberste Aktivität im Aktivitäts-Backstack ihren Status speichert. Anschließend können Sie den Anwendungsprozess über Android Debug Bridge, Android Studio oder mithilfe von beenden Hintergrundprozesse Limit-Eigenschaft in den Entwickleroptionen. Danach wird Ihre letzte Aktivität erfolgreich neu erstellt.

Trotzdem gibt es noch eine andere einfache Möglichkeit, das Todesszenario des Anwendungsprozesses zu testen. Wenn Sie alle oben beschriebenen Punkte kennen und wissen, dass der ActivityD- onStop()Rückruf erst nach der ActivityE- onResume()Methode aufgerufen wird, wenn Sie neue ActivityE über die aktuell ausgeführte ActivityD starten , können Sie den folgenden Trick ausführen.

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) {}
    }
}

Starten TerminatorActivitySie dann einfach, wenn Sie die Anwendung beenden möchten.

Am Ende gibt es ein leichtes Tool namens Venom , das das Testen des Todes Ihres Bewerbungsprozesses vereinfacht .

ivkil
quelle