Schließen Sie die Anwendung und starten Sie den Startbildschirm unter Android

76

Ich habe zwei verschiedene Aktivitäten. Der erste startet den zweiten. In der zweiten Aktivität rufe ich System.exit(0)auf, um das Schließen der Anwendung zu erzwingen. Die erste Aktivität wird jedoch automatisch angezeigt, anstatt dass die Anwendung zum Startbildschirm zurückkehrt. Wie kann ich dies vermeiden und die Anwendung dazu bringen, zum Startbildschirm zurückzukehren?

Arutha
quelle
Da der Stapel mehr als eine Aktivität enthält, wird er von System.exit (?) Neustart. (Ich denke)
Yousha Aleayoub

Antworten:

45

Sie sollten wirklich darüber nachdenken, die Anwendung nicht zu beenden. So funktionieren Android-Apps normalerweise nicht.

Romain Guy
quelle
2
Da gibt es keinen Ausgang in einer Android App. Gibt es eine Möglichkeit, alle Aktivitäten einer App zu durchlaufen, sodass ich bei jedem Aufruf Finish () aufrufe, dh alle gestarteten Aktivitäten beende?
Arutha
2
Warum müssen Sie das tun? Befinden sich die Aktivitäten in einem unzulässigen Zustand, weil Sie sich abgemeldet haben oder in einem anderen Zustand? Sie können dies innerhalb onResumeund dann in finishder Aktivität überprüfen .
James
2
Das Problem als Benutzer und Entwickler ist, dass die automatische Speicherbereinigung in Android nicht so gut funktioniert. Es gibt so viele "schlecht benommene" Apps, dass mein Telefon nicht mehr genügend Speicher hat und wenn es fast leer ist, beginnt die Benutzeroberfläche zu stottern. Dies ist auf einer relativ hohen Spezifikation (für diese Zeit) HTC Desire. Ich denke, deshalb stellen ich und andere manchmal diese Frage.
Richard Le Mesurier
1
@Richard: Wäre es nicht besser, alle Aktivitäten zu stoppen, wenn onPause in Ihrer Anwendung aufgerufen wird? Die einzige Möglichkeit, eine Anwendung zu verlangsamen, besteht darin, dass AsyncTasks usw. noch ausgeführt werden, wenn Sie angehalten werden, wenn dies nicht erforderlich ist. Zum Beispiel sollten Spiele ihre Hauptschleife nach onPause verlassen. (Und ein früher Ausstieg aus der Schleife zählt nicht.)
idbrii
2
@pydave: Ich stimme dir zu. Aber es scheint eine Menge Debatten über diese Art von Thema zu geben, und ich habe einige "reale" Entwickler- und Benutzererfahrungen geteilt. Tatsache ist, dass mein Telefon im Moment merklich langsamer wird, wenn der verfügbare Speicher abnimmt. Es scheint, dass ich sozusagen "im Hintergrund" Apps habe, die diesen Speicher belegen. Wenn ich diese Apps töte, habe ich die Erfahrung gemacht, dass mein Gerät schneller wird. Was mich denken lässt, dass es schön wäre, wenn entweder 1) Entwickler Code schreiben könnten, um einen Prozess vollständig zu beenden und seinen Speicher freizugeben, oder 2) der Android GC ein bisschen besser lief als derzeit. ymmv
Richard Le Mesurier
88

Kurze Antwort: Rufen moveTaskToBack(true)Sie anActivity statt System.exit(). Dadurch wird Ihre Anwendung ausgeblendet, bis der Benutzer sie erneut verwenden möchte.

Die längere Antwort beginnt mit einer anderen Frage: Warum möchten Sie Ihre Anwendung beenden?

Das Android-Betriebssystem übernimmt die Speicherverwaltung und -prozesse usw. Mein Rat ist also, dass Android sich nur darum kümmert. Wenn der Benutzer Ihre Anwendung verlassen möchte, kann er die Home-Taste drücken, und Ihre Anwendung wird effektiv ausgeblendet. Wenn das Telefon später mehr Speicher benötigt, beendet das Betriebssystem Ihre Anwendung.

Solange Sie angemessen auf Lebenszyklusereignisse reagieren , müssen sich weder Sie noch der Benutzer darum kümmern, ob Ihre Anwendung noch ausgeführt wird oder nicht.

Wenn Sie also Ihren Anwendungsaufruf ausblenden moveTaskToBack()und Android entscheiden lassen möchten , wann er beendet werden soll.

Dave Webb
quelle
4
Weitere Informationen zu Daves Argument finden Sie unter stackoverflow.com/questions/2033914/…
CommonsWare
Es gibt legitime Verwendungszwecke für das Beenden einer Anwendung. Ich mache beispielsweise eine Closed Beta und muss meine App schließen, wenn ein Benutzer nicht über das entsprechende Kennwort verfügt.
Matt Lyons
4
@Matt: Warum stoppen Sie den Benutzer nicht einfach am Passwortbildschirm? Wenn sie diesen Punkt nicht überschreiten können, warum müssen Sie dann das Herunterfahren der App erzwingen?
idbrii
Ein Sonderfall wäre, wenn der Benutzer die Zurück-Taste drückt, um die App zu beenden. Der Standardhandler onKeyUp () für diesen Vorgang führt in dieser Situation ein finish () aus. Ich habe jedoch die Erfahrung gemacht, dass finish () den Speicher nicht immer angemessen bereinigt, während System.exit (0) dies tut. In dieser speziellen Situation, in der sich der Benutzer im Wesentlichen von Ihrer App verabschiedet hat und implizit gesagt hat, dass er keinen Status beibehalten möchte, habe ich festgestellt, dass das Aufrufen von System.exit (0) die Reinigung viel besser macht oben.
Carl
53

Der einfachste Weg, dies zu erreichen, ist unten angegeben (ohne die native Speicherverwaltung von Android zu beeinträchtigen. Es ist kein Prozessabbruch erforderlich).

  1. Starten Sie eine Aktivität mit dieser Absicht:

    Intent intent = new Intent(this, FinActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    startActivity(intent);
    finish();
    
  2. FinActivity.classRufen Sie in der Zielaktivität finish () in auf onCreate.

Erklärte Schritte:

  1. Sie erstellen eine Absicht, die alle anderen Aktivitäten löscht (FLAG_ACTIVITY_CLEAR_TOP)und die aktuelle Aktivität löscht .

  2. Die Aktivität zerstört sich selbst. Eine Alternative besteht darin, dass Sie in finActivity einen Begrüßungsbildschirm erstellen können. Dies ist optional.

jordi
quelle
3
Willst du nicht die startActivity () vor dem finish ()?
Jemand irgendwo
FinActivitymuss deine RootActivity sein, oder? Wenn Sie dieses Flag verwenden, wird Ihr System neu gestartet, FinActivity.classwie in der Dokumentation developer.android.com/reference/android/content/… angegeben. Ich habe in meiner Antwort unten ein Beispiel angegeben, um dies zu beheben.
Darpan
Arbeiten wie ein Zauber :)
Radhey
Dadurch werden die Aktivitäten und Dienste beendet, aber im Debugger werden weiterhin Threads im Hintergrund angezeigt, und meine App wird weiterhin angezeigt, wenn Sie die Multitasking-Schaltfläche drücken.
Stephen M-auf Streik-
20

Android verfügt über einen Mechanismus zum sicheren Schließen einer Anwendung gemäß der Dokumentation. In der letzten Aktivität, die beendet wird (normalerweise die Hauptaktivität, die beim Start der Anwendung zum ersten Mal ausgeführt wurde), setzen Sie einfach ein paar Zeilen in die onDestroy () -Methode. Der Aufruf von System.runFinalizersOnExit (true) stellt sicher, dass alle Objekte finalisiert und beim Beenden der Anwendung Müll gesammelt werden. Zum Beispiel:

public void onDestroy() {
    super.onDestroy();

    /*
     * Notify the system to finalize and collect all objects of the
     * application on exit so that the process running the application can
     * be killed by the system without causing issues. NOTE: If this is set
     * to true then the process will not be killed until all of its threads
     * have closed.
     */
    System.runFinalizersOnExit(true);

    /*
     * Force the system to close the application down completely instead of
     * retaining it in the background. The process that runs the application
     * will be killed. The application will be completely created as a new
     * application in a new process if the user starts the application
     * again.
     */
    System.exit(0);
}

Schließlich benachrichtigt Android eine Anwendung nicht über das Ereignis HOME- Taste, sodass Sie die Anwendung nicht schließen können, wenn die HOME- Taste gedrückt wird. Android reserviert das HOME- Schlüsselereignis für sich, sodass ein Entwickler Benutzer nicht daran hindern kann, ihre Anwendung zu verlassen.

Danny Remington - OMS
quelle
4
Im AOSP-Quellcode ist diese Methode jetzt veraltet: @deprecated Diese Methode ist unsicher.
Artem Russakovskii
9

Sie können im Tag für die erste Aktivität auch noHistory = "true" angeben oder die erste Aktivität beenden, sobald Sie die zweite starten (wie David sagte).

AFAIK, "Schließen erzwingen" beendet den Prozess, der die JVM hostet, in der Ihre Anwendung ausgeführt wird, und System.exit () beendet die JVM, in der Ihre Anwendungsinstanz ausgeführt wird. Beide sind abrupte Abbrüche und für den normalen Anwendungsfluss nicht ratsam.

Ebenso wenig ist es ratsam, Ausnahmen zu erfassen, um Logikflüsse abzudecken, die ein Programm möglicherweise durchführt.

Samuh
quelle
Es gibt keine Möglichkeit, eine Anwendung ordnungsgemäß zu schließen, und alle Aktivitäten sind noch offen.
Arutha
2
Nein, es gibt in Android nicht wirklich ein "Anwendungs" -Konzept. Ihre Apps sind eine Sammlung von Aktivitäten. Wenn Sie nach Abschluss der zweiten Aktivität nicht zu Ihrer ersten Aktivität zurückkehren möchten, sollten Sie das noHistoryAttribut wie erwähnt verwenden.
Christopher Orr
Es geht mehr um Aktivitäten und Aufgaben ... developer.android.com/guide/topics/fundamentals.html#acttask
Samuh
9

Ich benutze diese Methode, um die Aktivitäten zu schließen!

public static void closeAllBelowActivities(Activity current) {
    boolean flag = true;
    Activity below = current.getParent();
    if (below == null)
        return;
    System.out.println("Below Parent: " + below.getClass());
    while (flag) {
        Activity temp = below;
        try {
            below = temp.getParent();
            temp.finish();
        } catch (Exception e) {
            flag = false;
        }
    }
}
Amsurana
quelle
8

Wenn Sie die zweite Aktivität starten, wird finish()die erste sofort ausgeführt:

startActivity(new Intent(...));
finish();
David Hedlund
quelle
1
Ich möchte die erste Aktivität nicht systematisch beenden, nur wenn ich System.exit (0) aufrufe. Es ist eine normale Funktion? Wie funktioniert die Schaltfläche zum Schließen erzwingen im Anwendungsmanager?
Arutha
1
Oh. Ich habe deine Frage dann falsch verstanden, sorry. So sieht der Standard-Lebenszyklus einer Android-App nicht aus. Die FC-Schaltfläche verwendet etwas Ähnliches, android.os.Process.killProcess(android.os.Process.myPid());das normalerweise nicht zum Beenden Ihrer Apps dient. Aber Sie könnten das verwenden, oder Sie könnten in Betracht ziehen , etwas zu untersuchen startActivityForResultund zu finishActivityerstellen, bei dem die erste Aktivität nur endet, wenn die zweite mit einem bestimmten Antwortcode endet.
David Hedlund
6

android.os.Process.killProcess(android.os.Process.myPid()); funktioniert gut, aber es wird empfohlen, dass sich die Android-Plattform um die Speicherverwaltung kümmert :-)

Arnab
quelle
4

Sie können System.exit () nicht ausführen, es ist nicht sicher.

Sie können dies tun: Process.killProcess (Process.myPid ());

Cytown
quelle
Sie benötigen die richtige Berechtigung - <Verwendungsberechtigung android: name = "android.permission.KILL_BACKGROUND_PROCESSES" />
Kevin Parker
Funktioniert für meine App, die als Gerätebesitzer ausgeführt wird. Es waren keine neuen Berechtigungen erforderlich. Verlässt noch die Multitasking-Ansicht.
Stephen M-auf Streik-
4

Ich benutze das:

1) Die übergeordnete Aktivität ruft die sekundäre Aktivität mit der Methode "startActivityForResult" auf.

2) In der sekundären Aktivität, wenn geschlossen wird:

int exitCode = 1; // Select the number you want
setResult(exitCode);
finish();

3) Überschreiben Sie in der übergeordneten Aktivität die Methode "onActivityResult":

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    int exitCode = 1;
    if(resultCode == exitCode) {
        super.setResult(exitCode); // use this if you have more than 2 activities
        finish();
    }
}

Das funktioniert gut für mich.

Molda
quelle
4

Verwenden Sie die finishMethode. Es ist die einfachere und einfachere Methode.

this.finish();
Nikhil
quelle
2

Beachten Sie, dass bei der Arbeit mit Anwendungen, die dauerhafte Socket-Verbindungen verwenden, die finish()Methode die Verbindung nicht freigibt. Unter normalen Umständen finish()ist dies die beste Option. Wenn Sie jedoch unbedingt eine App beenden und alle verwendeten Ressourcen freigeben müssen, verwenden Sie sie killProcess. Ich hatte keine Probleme damit.

PJ420
quelle
2

Starten Sie die zweite Aktivität mit startActivityForResult und geben Sie in der zweiten Aktivität einen Wert zurück, der einmal in der onActivityResult-Methode der ersten Aktivität die Hauptanwendung schließt. Ich denke, das ist der richtige Weg, wie Android es macht.

Dayerman
quelle
2

Sie liegen falsch. Es gibt eine Möglichkeit, eine Anwendung zu beenden. In einer Klasse mit Super Class Application verwenden wir beispielsweise ein Feld killApp. Wenn wir den Begrüßungsbildschirm (erste Aktivität) in starten onResume(), setzen wir einen Parameter für false für field killApp. In jeder Aktivität, die wir haben, wenn onResume()sie am Ende aufgerufen wird, nennen wir so etwas:

if(AppClass.killApp())
    finish();

Jede Aktivität, die auf den Bildschirm kommt, muss aufgerufen werden onResume(). Wenn es aufgerufen wird, müssen wir überprüfen, ob unser Feld killAppwahr ist. Wenn dies zutrifft, werden aktuelle Aktivitäten aufgerufen finish(). Um die vollständige Aktion aufzurufen, verwenden wir die nächste Konstruktion. Zum Beispiel in der Aktion für eine Schaltfläche:

AppClass.setkillApplication(true);
   finish();
   return;
Peter
quelle
Das Android-System beendet die Aktivität gemäß der Dokumentation nicht in Zuständen wie onStart (), onRestart () und onResume (). Ihr Vorschlag ist absolut falsch!
Anonim
2

Versuche Folgendes. Für mich geht das.

ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1); 
ComponentName componentInfo = taskInfo.get(0).topActivity;
am.restartPackage(componentInfo.getPackageName());
Sikandar
quelle
2

Angenommen, Sie haben einen Aktivitätsstapel wie A> B> C> D> E. Sie befinden sich in Aktivität D und möchten Ihre App schließen. Das wirst du tun -

In Aktivität, von wo aus Sie schließen möchten (Aktivität D) -

Intent intent = new Intent(D.this,A.class);
intent.putExtra("exit", "exit");
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP| Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);

In Ihrer RootActivity (dh Ihrer Basisaktivität, hier Aktivität A) -

@Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (intent.hasExtra("exit")) {
            setIntent(intent);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (getIntent() != null) {
            if (("exit").equalsIgnoreCase(getIntent().getStringExtra(("exit")))) {
                onBackPressed();
            }
        }
    }

onNewIntent wird verwendet, da bei einer aktiven Aktivität die erste Absicht angezeigt wird, mit der sie gestartet wurde. Nicht der Neue. Für mehr Details - Dokumentation

Darpan
quelle
1

Es ist eigentlich ganz einfach.

Ich speichere dazu ein Flag in einer statischen Variablen, die allen zur Verfügung steht. Wenn ich dann beende, setze ich dieses Flag und alle meine Aktivitäten überprüfen dieses Flag onResume. Wenn das Flag gesetzt ist, stelle ich das ausSystem.exit für diese Aktivität aus.

Auf diese Weise suchen alle Aktivitäten nach dem Flag und werden ordnungsgemäß geschlossen, wenn das Flag gesetzt ist.

Mikeghtmare
quelle
1

Folgendes habe ich getan, um die Anwendung zu schließen: In meiner Anwendung habe ich eine Basisaktivitätsklasse und ein statisches Flag namens "applicationShutDown" hinzugefügt. Wenn ich die Anwendung schließen muss, setze ich sie auf true.

In der Basisaktivität onCreate und onResume teste ich nach dem Aufruf der Superaufrufe dieses Flag. Wenn "applicationShutDown" wahr ist, rufe ich "finish" für die aktuelle Aktivität auf.

Das hat bei mir funktioniert:

protected void onResume() {
    super.onResume();
    if(BaseActivity.shutDownApp)
    {
        finish();
        return;

    }}
user1942887
quelle
0

Führen Sie die zweite Aktivität mit der Startaktivität für das Ergebnis aus:

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);

//This line is important
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

startActivityForResult(intent, REQUEST_CODE);

Fügen Sie diese Funktion zur ersten Aktivität hinzu:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(rquestCode == REQUEST_CODE)
        if(resultCode == RESULT_CANCELED)
            finish();
}

Und fügen Sie dies der zweiten Aktivität hinzu:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event)  {
    if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {

        Log.i(TAG, "Back key pressed");
        setResult(RESULT_CANCELED);
        finish();
        return true;
    }
    return super.onKeyDown(keyCode, event);
}
Piojo
quelle
0

Es wird nicht empfohlen, aber Sie können es trotzdem verwenden. Verwenden Sie diese Lösung besser, wenn Sie die App beenden müssen.

Meiner Meinung nach besteht die beste Lösung darin, jede Aktivität in Ihrer App wie unten beschrieben zu beenden.

Schritt 1. Pflegen Sie eine statische Variable in der Hauptaktivität. Sagen,

public static boolean isQuit = false;

Schritt 2. Setzen Sie diese Variable beim Klicken auf das Ereignis einer Schaltfläche auf true.

mainactivity.isQuit = true;
finish();

Schritt 3. Führen Sie in jeder Aktivität Ihrer Anwendung die folgende onrestartMethode aus.

@Override
protected void onRestart() {
    // TODO Auto-generated method stub
    super.onRestart();
    if(mainactivity.isQuit)
        finish();
}
Shankar Agarwal
quelle
0

Ich habe ein ähnliches Problem gelöst: MainActivity startet BrowserActivity und ich muss die App schließen, wenn der Benutzer in BrowserActivity auf Zurück drückt - um nicht in MainActivity zurückzukehren. Also, in MainActivity:

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "sm500_Rmt.MainActivity";
    private boolean m_IsBrowserStarted = false;

und dann in OnResume:

    @Override
protected void onResume() {
    super.onResume();
    if(m_IsBrowserStarted) {
        Log.w(TAG, "onResume, but it's return from browser, just exit!");
        finish();
        return;
    }
    Log.w(TAG, "onResume");

... dann weiter mit OnResume. Und wenn Sie BrowserActivity starten:

    Intent intent = new Intent(this, BrowserActivity.class);
    intent.putExtra(getString(R.string.IPAddr), ip);
    startActivity(intent);
    m_IsBrowserStarted = true;

Und es sieht so aus, als ob es gut funktioniert! :-)

Sergey Skosyrev
quelle