Wie starte ich eine Android-App programmgesteuert neu?

231

Erstens weiß ich, dass man eine Anwendung auf Android nicht wirklich beenden sollte. In meinem Anwendungsfall möchte ich meine Anwendung in einem bestimmten Fall auf die Werkseinstellungen zurücksetzen, in dem ein Server bestimmte Informationen an den Client sendet.

Der Benutzer kann nur mit EINER Instanz der Anwendung am Server angemeldet sein (dh mehrere Geräte sind nicht zulässig). Wenn eine andere Instanz diese "angemeldete" Sperre erhält, müssen alle anderen Instanzen dieses Benutzers ihre Daten löschen (auf die Werkseinstellungen zurücksetzen), um die Konsistenz aufrechtzuerhalten.

Es ist möglich, die Sperre zwangsweise zu erhalten, da der Benutzer die App möglicherweise löschen und neu installieren kann, was zu einer anderen Instanz-ID führen würde und der Benutzer die Sperre nicht mehr aufheben kann. Daher ist es möglich, das Schloss gewaltsam zu bekommen.

Aufgrund dieser Kraftmöglichkeit müssen wir immer in einer konkreten Instanz überprüfen, ob sie das Schloss hat. Dies geschieht bei (fast) jeder Anfrage an den Server. Der Server sendet möglicherweise eine "falsche Sperr-ID". Wenn dies erkannt wird, muss die Clientanwendung alles löschen.


Das war der Anwendungsfall.

Ich habe ein ActivityA, das das Login ActivityL oder das Haupt- ActivityB der App abhängig von einem sharedPrefs-Wert startet. Nach dem Start von L oder B schließt es sich so, dass nur L oder B läuft. Für den Fall, dass der Benutzer bereits angemeldet ist, wird B jetzt ausgeführt.

B startet C. C fordert startServicedas IntentServiceD. Das ergibt diesen Stapel:

(A)> B> C> D.

Von der onHandleIntent-Methode von D wird ein Ereignis an einen ResultReceiver R gesendet .

R behandelt dieses Ereignis jetzt, indem es dem Benutzer einen Dialog zur Verfügung stellt, in dem er die Anwendung auf die Werkseinstellungen zurücksetzen kann (Löschen der Datenbank, sharedPrefs usw.).

Nach dem Zurücksetzen auf die Werkseinstellungen möchte ich die Anwendung neu starten (um alle Aktivitäten zu schließen) und erst wieder A starten, das dann das Login ActivityL startet und sich selbst beendet:

(A)> L.

Die onClick-Methode des Dialogs sieht folgendermaßen aus:

@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);
}

Und das ist die MyAppKlasse:

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() {
        // ...
    }
}

Das Problem ist, wenn ich FLAG_ACTIVITY_NEW_TASKdie Aktivitäten B und C verwende, laufen sie noch. Wenn ich beim Anmelden auf die Schaltfläche "Zurück" drücke, wird ActivityC angezeigt, ich möchte jedoch zum Startbildschirm zurückkehren.

Wenn ich das nicht einstelle, FLAG_ACTIVITY_NEW_TASKerhalte ich den Fehler:

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?

Ich kann die Aktivitäten nicht verwenden Context, da das ServiceIntentD möglicherweise auch von einer Hintergrundaufgabe aufgerufen wird, die von der gestartet wird AlarmManager.

Wie könnte ich das lösen, damit der Aktivitätsstapel (A)> L wird?

Stecken
quelle

Antworten:

284

Sie können PendingIntentdamit den Start Ihrer Startaktivität in der Zukunft einrichten und dann Ihre Anwendung schließen

Intent mStartActivity = new Intent(context, StartActivity.class);
int mPendingIntentId = 123456;
PendingIntent mPendingIntent = PendingIntent.getActivity(context, mPendingIntentId,    mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager mgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
System.exit(0);
Oleg Koshkin
quelle
5
Das hat bei mir perfekt funktioniert! Ich habe gerade android.os.Process.killProcess (android.os.Process.myPid ()) verwendet. über System.exit ();
FDIM
29
Auf 4.3- und 4.4-Geräten (alles, was ich getestet habe) scheint dies die aktuelle Aktivität zu beenden und dann eine neue über die alte zu starten. Ich bin 2 Aktivitäten tief (main -> prefs). Durch Zurückdrücken komme ich zur alten App, einen Bildschirm zurück.
Mgamerz
5
In meinem Fall funktionierte System.exit (0) nicht, da eine Transaktion zurückgesetzt wurde. Stattdessen habe ich activity.finish () verwendet. und es funktioniert gut.
Vereinige
6
@ Qulin, Leute! Sie können nicht ernst sein! Dieses Beispiel ist eher eine Richtung als ein Beispiel aus dem wirklichen Leben. Sie müssen dieses Snippet mit dem Namen der Startaktivität, der Intent-ID und der Exit-Mechanik ändern, mit was auch immer Sie arbeiten. Kopieren Sie es nicht blind und fügen Sie es ein.
Oleg Koshkin
19
Dies funktioniert nicht mehr mit Android Q aufgrund neuer Einschränkungen für Hintergrundaktivitäten developer.android.com/preview/privacy/…
Marco Righini
103

Sie können einfach anrufen:

public static void triggerRebirth(Context context, Intent nextIntent) {
    Intent intent = new Intent(context, YourClass.class);
    intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
    intent.putExtra(KEY_RESTART_INTENT, nextIntent);
    context.startActivity(intent);
    if (context instanceof Activity) {
      ((Activity) context).finish();
    }

    Runtime.getRuntime().exit(0);
}

Welches in der ProcessPhoenix- Bibliothek verwendet wird


Als Alternative:

Hier ist eine etwas verbesserte Version der Antwort von @Oleg Koshkin.

Wenn Sie Ihre Aktivität wirklich neu starten möchten, einschließlich eines Abbruchs des aktuellen Prozesses, versuchen Sie, den folgenden Code zu verwenden. Legen Sie es in eine HelperClass oder wo Sie es brauchen.

public static void doRestart(Context c) {
        try {
            //check if the context is given
            if (c != null) {
                //fetch the packagemanager so we can get the default launch activity 
                // (you can replace this intent with any other activity if you want
                PackageManager pm = c.getPackageManager();
                //check if we got the PackageManager
                if (pm != null) {
                    //create the intent with the default start activity for your application
                    Intent mStartActivity = pm.getLaunchIntentForPackage(
                            c.getPackageName()
                    );
                    if (mStartActivity != null) {
                        mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        //create a pending intent so the application is restarted after System.exit(0) was called. 
                        // We use an AlarmManager to call this intent in 100ms
                        int mPendingIntentId = 223344;
                        PendingIntent mPendingIntent = PendingIntent
                                .getActivity(c, mPendingIntentId, mStartActivity,
                                        PendingIntent.FLAG_CANCEL_CURRENT);
                        AlarmManager mgr = (AlarmManager) c.getSystemService(Context.ALARM_SERVICE);
                        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
                        //kill the application
                        System.exit(0);
                    } else {
                        Log.e(TAG, "Was not able to restart application, mStartActivity null");
                    }
                } else {
                    Log.e(TAG, "Was not able to restart application, PM null");
                }
            } else {
                Log.e(TAG, "Was not able to restart application, Context null");
            }
        } catch (Exception ex) {
            Log.e(TAG, "Was not able to restart application");
        }
    }

Dadurch werden auch jni-Klassen und alle statischen Instanzen neu initialisiert.

mikepenz
quelle
1
Diese Lösung ist nett, verzögert sich jedoch um einige Sekunden, bis Ihre Anwendung neu gestartet wird, selbst wenn Sie die 100 Millis verringert haben. Diese Bibliothek ProcessPhoenix von Jack Wharton macht es jedoch besser und schneller, aber es lohnt sich nicht, nur für diese Funktion innerhalb der App eine Bibliothek hinzuzufügen.
Blueware
@ Blueware Ich habe meine Antwort aktualisiert und den Code hinzugefügt, der in ProcessPhonix verwendet wird
Mikepenz
@mikepenz, dieser Typ "Ilya_Gazman" hat es viel besser gemacht und ohne eine solche Bibliothek zu benutzen.
Blueware
3
@blueware - Außer, dass die Lösung von Ilya den Prozess nicht neu startet, sodass statische Daten oder geladene NDK-Bibliotheken nicht korrekt neu initialisiert werden.
Ted Hopp
Einige Geräte von Huawei und Samsung unterliegen Einschränkungen AlarmManager und verhalten sich schlecht, wenn sie diese Lösung verwenden. Gibt es einen besseren Ansatz?
Blueware
69

Jake Wharton hat kürzlich seine ProcessPhoenix- Bibliothek veröffentlicht, die dies auf zuverlässige Weise tut. Sie müssen grundsätzlich nur anrufen:

ProcessPhoenix.triggerRebirth(context);

Die Bibliothek beendet automatisch die aufrufende Aktivität, beendet den Anwendungsprozess und startet anschließend die Standardanwendungsaktivität neu.

TBieniek
quelle
Dies scheint zu funktionieren, aber ich bekomme einen Absturz (der gemeldet wird). Ich bin mir nicht sicher, ob das ideal ist.
BK
1
Ich hatte nie Probleme mit der Bibliothek, kann aber einen Fehler unter github.com/JakeWharton/ProcessPhoenix/issues
TBieniek vom
Argh, ich ziehe meinen Kommentar zurück, da ich die Nachricht nicht genau genug angesehen habe. Bei meiner Standardstartaktivität fehlte ein Absichtsfilter. Es kann sinnvoll sein, die genauen erforderlichen Absichtsfilter zu notieren.
BK
1
Dies ist bisher die beste Lösung.
YongsunCN
1
@Shambhu Sie müssen das Tag <category android:name="android.intent.category.DEFAULT" />zu Ihrer Standardaktivität <intent-filter> im App-Manifest hinzufügen .
Muhammed Refaat
57

Ich habe die Antwort von Ilya_Gazman leicht geändert, um neue APIs zu verwenden (IntentCompat ist ab API 26 veraltet). Runtime.getRuntime (). Exit (0) scheint besser zu sein als System.exit (0).

 public static void triggerRebirth(Context context) {
    PackageManager packageManager = context.getPackageManager();
    Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName());
    ComponentName componentName = intent.getComponent();
    Intent mainIntent = Intent.makeRestartActivityTask(componentName);
    context.startActivity(mainIntent);
    Runtime.getRuntime().exit(0);
}
android_dev
quelle
8
Direkt aus den Dokumenten : " Der Anruf System.exit(n) entspricht effektiv dem Anruf: Runtime.getRuntime().exit(n) ". Intern System.exit()dreht sich nur um und ruft an Runtime.getRuntime().exit(). Es gibt nichts "Besseres" an dem einen oder anderen (es sei denn, man ist besorgt darüber, wie viel man tippt oder über eine zusätzliche Ebene von Methodenaufrufen).
Ted Hopp
wo und wann obige Methode aufrufen?
Makvin
1
@ Makvin Sie entscheiden, wo Sie es nennen. Mein Fall war ein Neustart der App nach einem Sprachwechsel.
android_dev
@ TedHopp hat jede Antwort als "nicht gut" kommentiert. Haben Sie eine praktikable Lösung? Da Sie nicht sarkastisch sind, müssen Sie eine Anwendung wirklich ohne Spuren neu erstellen. von statischen Variablen zu Klasseninstanzen.
Farid
1
@FARID - Alle Lösungen, die das Aufrufen Runtime.getRuntime().exit(0)(oder System.exit(0)) beinhalten, werden wahrscheinlich funktionieren. Einige meiner "nicht guten" Kommentare sind für Antworten (wie der von Ilya Gazman , die seitdem bearbeitet wurden, um einen solchen Aufruf aufzunehmen)
Ted Hopp
37

IntentCompat.makeRestartActivityTask

Die neue Methode ist die Verwendung von IntentCompat.makeRestartActivityTask

Erstellen Sie eine Absicht, mit der die Aufgabe einer Anwendung im Basiszustand neu gestartet werden kann. Dies ähnelt makeMainActivity (ComponentName), setzt jedoch auch die Flags Intent.FLAG_ACTIVITY_NEW_TASK und FLAG_ACTIVITY_CLEAR_TASK.

PackageManager packageManager = context.getPackageManager();
Intent intent = packageManager.getLaunchIntentForPackage(context.getPackageName());
ComponentName componentName = intent.getComponent();
Intent mainIntent = IntentCompat.makeRestartActivityTask(componentName);
context.startActivity(mainIntent);
System.exit(0);
Ilya Gazman
quelle
6
Dadurch wird die Aufgabe neu gestartet, der Prozess oder sogar das ApplicationObjekt werden jedoch nicht neu gestartet . Daher bleiben alle staticDaten, Daten, die während der Erstellung der Applicationoder jni-Klassen initialisiert wurden , in ihrem aktuellen Zustand und werden nicht neu initialisiert.
Ted Hopp
2
@ TedHopp Oh, ich habe diesen Teil verpasst. Ich habe System.exit (0) hinzugefügt. Aber ich bin nicht zu 100% sicher, dass es funktionieren wird. Ich werde es später am
Ilya Gazman
1
Die beste Lösung ohne Open Source-Bibliothek. Hände hoch und danke für diese Antwort, +1
Blueware
4
Leider IntentCompat.makeRestartActivityTaskist jetzt veraltet . Wenn Sie den Quellcode überprüfen , müssen Sie lediglich die Flags hinzufügen Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK.
Paul Lammertsma
IntentCompat.makeRestartActivityTask entfernt
Luckyhandler
28

Es gibt einen wirklich schönen Trick. Mein Problem war, dass in einer wirklich alten C ++ jni-Bibliothek Ressourcen verloren gingen. Irgendwann funktionierte es nicht mehr. Der Benutzer hat versucht, die App zu beenden und erneut zu starten - ohne Ergebnis, da das Beenden einer Aktivität nicht mit dem Beenden (oder Beenden) des Prozesses identisch ist. (Übrigens könnte der Benutzer zur Liste der ausgeführten Anwendungen gehen und sie von dort aus stoppen - dies würde funktionieren, aber die Benutzer wissen einfach nicht, wie sie Anwendungen beenden sollen.)

Wenn Sie den Effekt dieser Funktion beobachten möchten, fügen Sie a hinzu static Ihrer Aktivität Variable hinzu und erhöhen Sie sie beispielsweise durch Drücken einer Taste. Wenn Sie die Anwendungsaktivität beenden und die Anwendung dann erneut aufrufen, behält diese statische Variable ihren Wert. (Wenn die Anwendung wirklich beendet wurde, wird der Variablen der Anfangswert zugewiesen.)

(Und ich muss kommentieren, warum ich den Fehler nicht stattdessen beheben wollte . Die Bibliothek wurde vor Jahrzehnten geschrieben und hat seitdem Ressourcen verloren. Das Management glaubt, dass es immer funktioniert hat . Die Kosten für die Bereitstellung eines Fixes anstelle einer Problemumgehung ... Ich denke, du kommst auf die Idee.)

Wie kann ich nun eine gemeinsam genutzte jni-Bibliothek (auch bekannt als dynamic, .so) auf den Ausgangszustand zurücksetzen? Ich habe mich entschieden, die Anwendung als neuen Prozess neu zu starten.

Der Trick besteht darin, dass System.exit () die aktuelle Aktivität schließt und Android die Anwendung mit einer Aktivität weniger neu erstellt.

Der Code lautet also:

/** This activity shows nothing; instead, it restarts the android process */
public class MagicAppRestart extends Activity {
    // Do not forget to add it to AndroidManifest.xml
    // <activity android:name="your.package.name.MagicAppRestart"/>
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        System.exit(0);
    }
    public static void doRestart(Activity anyActivity) {
        anyActivity.startActivity(new Intent(anyActivity.getApplicationContext(), MagicAppRestart.class));
    }
}

Die aufrufende Aktivität führt nur den Code aus MagicAppRestart.doRestart(this);, die aufrufende Aktivität onPause()wird ausgeführt und dann wird der Prozess neu erstellt. Und vergessen Sie nicht, diese Aktivität in AndroidManifest.xml zu erwähnen

Der Vorteil dieser Methode ist, dass es keine Verzögerungen gibt.

UPD: Es hat in Android 2.x funktioniert, aber in Android 4 hat sich etwas geändert.

18446744073709551615
quelle
3
Ich habe activity.startActivity (i) verwendet. System.exit (0); geniale Lösung
max4ever
5
Diese Lösung schließt die App für mich, startet aber nicht neu. Zumindest unter Android 4.3.
Kirill Rakhman
1
Auf Samsung Galaxy Mega Android 4.2.2 Es verursacht eine unendliche Schleife des Neustarts. Die App wird also nicht erneut gestartet.
Gunhan
@Gunhan 1) , was passiert , wenn Sie ersetzen System.exit(0)durch android.os.Process.killProcess(android.os.Process.myPid());? 2) Eine Endlosschleife bedeutet höchstwahrscheinlich, dass sie beim Neustart einer App nicht die oberste Aktivität entfernen. Im Prinzip können Sie eine statische boolesche Variable hinzufügen, diese vor dem Aufrufen der Neustartaktivität auf true setzen und nach dem Neustart ist sie false. Auf diese Weise kann die Aktivität herausfinden, ob der Neustart bereits stattgefunden hat oder nicht (und wenn dies geschehen ist, beenden Sie einfach () ). OTOH, Ihr Bericht bedeutet, dass der Trick nicht auf allen Geräten identisch funktioniert.
18446744073709551615
@Gunham Wenn Sie dieselbe Aktivität starten, die den Neustart verursacht, ist dies auf jedem Gerät eine Endlosschleife.
Lukas Hanacek
23

Meine Lösung startet den Prozess / die Anwendung nicht neu. Die App kann nur die Heimaktivität "neu starten" (und alle anderen Aktivitäten schließen). Für Benutzer sieht es nach einem Neustart aus, aber der Vorgang ist der gleiche. Ich denke, in einigen Fällen wollen die Leute diesen Effekt erzielen, also lasse ich ihn einfach hier, zu Ihrer Information.

public void restart(){
    Intent intent = new Intent(this, YourHomeActivity.class);
    this.startActivity(intent);
    this.finishAffinity();
}
yongsunCN
quelle
15

Ok, ich habe meine App überarbeitet und werde A nicht automatisch beenden. Ich lasse das immer laufen und beende es durch die onActivityResultVeranstaltung. Auf diese Weise kann ich die FLAG_ACTIVITY_CLEAR_TOP+ FLAG_ACTIVITY_NEW_TASKFlags verwenden, um das zu bekommen, was ich will:

public class A extends Activity {

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        finish();
    }

    protected void onResume() {
        super.onResume();
        // ...
        if (loggedIn) {
            startActivityForResult(new Intent(this, MainActivity.class), 0);
        } else {
            startActivityForResult(new Intent(this, LoginActivity.class), 0);
        }
    }
}

und in der ResultReceiver

@Override
public void onClick(DialogInterface dialog, int which) {
    MyApp.factoryReset();
    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);
}

Danke trotzdem!

Stecken
quelle
23
Dadurch wird die Anwendung nicht neu gestartet, sondern nur die Klassen neu erstellt. Daher behalten alle statischen Variablen innerhalb der Klassen Werte aus früheren Läufen bei.
Brian White
14
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
Nirav Ranpara
quelle
24
Dadurch wird die Anwendung nicht neu gestartet, sondern nur die Klassen neu erstellt. Daher behalten alle statischen Variablen innerhalb der Klassen Werte aus früheren Läufen bei.
Brian White
14

Der einzige Code, der nicht "Ihre App wurde unerwartet geschlossen" ausgelöst hat, lautet wie folgt. Es ist auch nicht veralteter Code, für den keine externe Bibliothek erforderlich ist. Es ist auch kein Timer erforderlich.

public static void triggerRebirth(Context context, Class myClass) {
    Intent intent = new Intent(context, myClass);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    context.startActivity(intent);
    Runtime.getRuntime().exit(0);
}
Haskell McRavin
quelle
8

Ich habe festgestellt, dass dies unter API 29 und höher funktioniert - zum Beenden und Neustarten der App, als hätte der Benutzer sie gestartet, als sie nicht ausgeführt wurde.

public void restartApplication(final @NonNull Activity activity) {
   // Systems at 29/Q and later don't allow relaunch, but System.exit(0) on
   // all supported systems will relaunch ... but by killing the process, then
   // restarting the process with the back stack intact. We must make sure that
   // the launch activity is the only thing in the back stack before exiting.
   final PackageManager pm = activity.getPackageManager();
   final Intent intent = pm.getLaunchIntentForPackage(activity.getPackageName());
   activity.finishAffinity(); // Finishes all activities.
   activity.startActivity(intent);    // Start the launch activity
   System.exit(0);    // System finishes and automatically relaunches us.
}

Dies geschah, wenn die Launcher-Aktivität in der App Folgendes aufweist:

<intent-filter>
    <action android:name="android.intent.action.VIEW"/>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

Ich habe Kommentare gesehen, in denen behauptet wurde, dass eine Kategorie von DEFAULT erforderlich ist, aber ich habe nicht festgestellt, dass dies der Fall ist. Ich habe bestätigt, dass das Anwendungsobjekt in meiner App neu erstellt wurde, daher glaube ich, dass der Prozess tatsächlich beendet und neu gestartet wurde.

Der einzige Zweck, für den ich dies verwende, besteht darin, die App neu zu starten, nachdem der Benutzer die Absturzberichterstattung für Firebase Crashlytics aktiviert oder deaktiviert hat. Gemäß ihren Dokumenten muss die App neu gestartet (Prozess abgebrochen und neu erstellt) werden, damit diese Änderung wirksam wird.

Mark Peters
quelle
7

Der beste Weg, eine App vollständig neu zu starten, besteht darin, sie neu zu starten und nicht nur mit FLAG_ACTIVITY_CLEAR_TOPund zu einer Aktivität zu springen FLAG_ACTIVITY_NEW_TASK. Meine Lösung besteht also darin, dies von Ihrer App oder sogar von einer anderen App aus zu tun. Die einzige Bedingung besteht darin, den Namen des App-Pakets zu kennen (Beispiel: ' com.example.myProject ').

 public static void forceRunApp(Context context, String packageApp){
    Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(packageApp);
    launchIntent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(launchIntent);
}

Beispiel für den Neustart oder den Start von AppA über AppB :

forceRunApp(mContext, "com.example.myProject.appA");

Sie können überprüfen, ob die App ausgeführt wird:

 public static boolean isAppRunning(Context context, String packageApp){
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<ActivityManager.RunningAppProcessInfo> procInfos = activityManager.getRunningAppProcesses();
    for (int i = 0; i < procInfos.size(); i++) {
        if (procInfos.get(i).processName.equals(packageApp)) {
           return true;
        }
    }
    return false;
}

Hinweis : Ich weiß, dass diese Antwort etwas unangebracht ist, aber für jemanden sehr hilfreich sein kann.

Choletski
quelle
5

Mein bester Weg, um die Anwendung neu zu starten, ist die Verwendung von finishAffinity();
Da, finishAffinity();kann nur in JELLY BEAN-Versionen verwendet werden, sodass wir verwenden könnenActivityCompat.finishAffinity(YourCurrentActivity.this); für niedrigere Versionen verwenden können.

Verwenden Sie dann Intent, um die erste Aktivität zu starten, damit der Code folgendermaßen aussieht:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
    finishAffinity();
    Intent intent = new Intent(getApplicationContext(), YourFirstActivity.class);
    startActivity(intent);
} else {
    ActivityCompat.finishAffinity(YourCurrentActivity.this);
    Intent intent = new Intent(getApplicationContext(), YourFirstActivity.class);
    startActivity(intent);
}

Ich hoffe es hilft.

Hussein ND
quelle
1
Dadurch werden alle Aktivitäten in der aktuellen Aufgabe beendet, der Prozess wird jedoch nicht neu gestartet oder das Anwendungsobjekt neu erstellt. Daher bleiben statische Daten, Daten, die während der Erstellung der Anwendung oder von jni-Klassen initialisiert wurden, in ihrem aktuellen Zustand und werden nicht neu initialisiert.
Ted Hopp
3

Versuchen Sie es mit FLAG_ACTIVITY_CLEAR_TASK

Pedro Loureiro
quelle
hm Entwicklung für 2.1: Intent.FLAG_ACTIVITY_CLEAR_TASK kann nicht gelöst werden
Stuck
Entschuldigung - Seit: API Level 11 developer.android.com/reference/android/content/…
Pedro Loureiro
3

Hier ist ein Beispiel, um Ihre App mithilfe des PackageManager generisch neu zu starten:

Intent i = getBaseContext().getPackageManager()
             .getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
Alireza Ghanbarinia
quelle
Dadurch wird die Aufgabe neu gestartet, der Prozess oder sogar das ApplicationObjekt werden jedoch nicht neu gestartet . Daher Applicationbleiben statische Daten, Daten, die während der Erstellung der oder jni-Klassen initialisiert wurden , in ihrem aktuellen Zustand und werden nicht neu initialisiert.
Ted Hopp
3

Versuche dies:

Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
veeson
quelle
1
Wie bei jeder anderen Antwort, die hier bereits dasselbe vorschlägt, wird die Anwendung nicht neu gestartet, sondern nur die Klassen neu erstellt. Daher werden statische Daten innerhalb des Prozesses nicht zurückgesetzt.
Ted Hopp
2

Starten Sie den Einstiegsbildschirm direkt mit FLAG_ACTIVITY_CLEAR_TASKund FLAG_ACTIVITY_NEW_TASK.

Yijun Li
quelle
2

Ich musste einen Handler hinzufügen, um den Exit zu verzögern:

 mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 200, mPendingIntent);
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                Runtime.getRuntime().exit(0);
            }
        }, 100);
Andy7229082
quelle
2

Verwenden:

navigateUpTo(new Intent(this, MainActivity.class));

Ich glaube, es funktioniert ab API-Level 16 (4.1).

Peter Mortensen
quelle
1

Sie können die startInstrumentationMethode von verwenden Activity. Sie müssen das Gerät leer Instrumentationund im Manifest zeigen. Danach können Sie diese Methode aufrufen, um Ihre App neu zu starten. So was:

try {           
    InstrumentationInfo info = getPackageManager().queryInstrumentation(getPackageName(), 0).get(0);
    ComponentName component = new ComponentName(this, Class.forName(info.name));
    startInstrumentation(component, null, null);
} catch (Throwable e) {             
    new RuntimeException("Failed restart with Instrumentation", e);
}

Ich erhalte den Namen der Instrumentierungsklasse dynamisch, aber Sie können ihn fest codieren. Etwas wie das:

try {           
    startInstrumentation(new ComponentName(this, RebootInstrumentation.class), null, null); 
} catch (Throwable e) {             
    new RuntimeException("Failed restart with Instrumentation", e);
}

Rufen Sie startInstrumentationmake make reload Ihrer App auf. Lesen Sie die Beschreibung dieser Methode. Aber es kann nicht sicher sein, wenn man sich wie eine Kill-App verhält.

Enyby
quelle
1

Die Anwendung, an der ich arbeite, muss dem Benutzer die Möglichkeit geben, auszuwählen, welche Fragmente angezeigt werden sollen (Fragmente werden zur Laufzeit dynamisch geändert). Die beste Lösung für mich war ein vollständiger Neustart die Anwendung .

Also habe ich viele Lösungen ausprobiert und keine davon hat für mich funktioniert, aber dies:

final Intent mStartActivity = new Intent(SettingsActivity.this, Splash.class);
final int mPendingIntentId = 123456;
final PendingIntent mPendingIntent = PendingIntent.getActivity(SettingsActivity.this, mPendingIntentId, mStartActivity,
                    PendingIntent.FLAG_CANCEL_CURRENT);
final AlarmManager mgr = (AlarmManager) SettingsActivity.this.getSystemService(Context.ALARM_SERVICE);
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
this.finishAffinity(); //notice here
Runtime.getRuntime().exit(0); //notice here

Ich hoffe, das hilft jemand anderem!

hzitoun
quelle
0

Versuche dies:

private void restartApp() {
    Intent intent = new Intent(getApplicationContext(), YourStarterActivity.class);
    int mPendingIntentId = MAGICAL_NUMBER;
    PendingIntent mPendingIntent = PendingIntent.getActivity(getApplicationContext(), mPendingIntentId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager mgr = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
    mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, mPendingIntent);
    System.exit(0);
}
Muhammad Mubeen
quelle
-1

Mit der Process Phoenix-Bibliothek . Die Aktivität, die Sie neu starten möchten, heißt "A".

Java-Geschmack

// Java
public void restart(){
    ProcessPhoenix.triggerRebirth(context);
}

Kotlin Geschmack

// kotlin
fun restart() {
    ProcessPhoenix.triggerRebirth(context)
}
Raymond Chenon
quelle
Dies hat das unglückliche Ergebnis, dass Ihr Debugger die Verbindung trennt.
DrSatan1
-3

Sie können Ihre aktuelle Aktivität folgendermaßen neu starten:

Fragment :

activity?.recreate()

Aktivität:

recreate()

quelle
3
Dies ist überhaupt nicht das, was OP tun möchte.
Ted Hopp