Comment «redémarrer» une application Android par programmation?

231

Tout d'abord, je sais qu'il ne faut pas vraiment tuer / redémarrer une application sur Android. Dans mon cas d'utilisation, je souhaite réinitialiser mon application en usine dans un cas spécifique où un serveur envoie des informations spécifiques au client.

L'utilisateur ne peut être connecté sur le serveur qu'avec UNE seule instance de l'application (c'est-à-dire que plusieurs appareils ne sont pas autorisés). Si une autre instance obtient ce verrou "connecté", toutes les autres instances de cet utilisateur doivent supprimer leurs données (réinitialisation d'usine), pour maintenir la cohérence.

Il est possible d'obtenir de force le verrou, car l'utilisateur pourrait supprimer l'application et la réinstaller, ce qui entraînerait un identifiant d'instance différent et l'utilisateur ne pourrait plus libérer le verrou. Par conséquent, il est possible d'obtenir de force le verrou.

En raison de cette possibilité de force, nous devons toujours vérifier dans un cas concret qu'il a le verrou. Cela se fait sur (presque) chaque requête au serveur. Le serveur peut envoyer un "identifiant de verrouillage incorrect". Si cela est détecté, l'application cliente doit tout supprimer.


C'était le cas d'utilisation.

J'ai un ActivityA qui démarre le Login ActivityL ou le ActivityB principal de l'application en fonction d'une valeur sharedPrefs. Après avoir démarré L ou B, il se ferme de sorte que seul L ou B fonctionne. Donc, dans le cas où l'utilisateur est déjà connecté, B s'exécute maintenant.

B commence C. C appelle startServicele IntentServiceD. Cela se traduit par cette pile:

(A)> B> C> D

À partir de la méthode onHandleIntent de D, un événement est envoyé à un ResultReceiver R.

R gère désormais cet événement en fournissant à l'utilisateur une boîte de dialogue où il peut choisir de réinitialiser l'application en usine (supprimer la base de données, sharedPrefs, etc.)

Après la réinitialisation d'usine, je veux redémarrer l'application (pour fermer toutes les activités) et redémarrer uniquement A qui lance ensuite la connexion ActivityL et se termine:

(A)> L

La méthode onClick de la boîte de dialogue ressemble à ceci:

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

Et c'est la MyAppclasse:

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

Le problème est que si j'utilise les FLAG_ACTIVITY_NEW_TASKactivités B et C sont toujours en cours d'exécution. Si je clique sur le bouton de retour sur la connexion, Activityje vois C, mais je veux revenir à l'écran d'accueil.

Si je ne règle pas, FLAG_ACTIVITY_NEW_TASKj'obtiens l'erreur:

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?

Je ne peux pas utiliser les activités Context, car le ServiceIntentD peut également être appelé à partir d'une tâche d'arrière-plan qui est lancée par le AlarmManager.

Alors, comment pourrais-je résoudre cela pour que la pile d'activités devienne (A)> L?

Coincé
la source

Réponses:

284

Vous pouvez utiliser PendingIntentpour configurer le lancement de votre activité de démarrage à l'avenir, puis fermer votre application

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
la source
5
Cela a parfaitement fonctionné pour moi! Je viens d'utiliser android.os.Process.killProcess (android.os.Process.myPid ()); sur System.exit ();
FDIM
29
Sur les appareils 4.3 et 4.4 (tout ce que j'ai testé), cela semble tuer l'activité actuelle, puis en lancer une nouvelle par-dessus l'ancienne. Je suis profond de 2 activités (principal -> prefs). Appuyer en arrière me ramène à l'ancienne application, un écran en arrière.
Mgamerz
5
Dans mon cas, System.exit (0) n'a pas fonctionné car une transaction était en cours de restauration. Au lieu de cela, j'ai utilisé activity.finish (); et cela fonctionne très bien.
unifier
6
@Qulin, Guys! Vous ne pouvez pas être sérieux! Cet exemple ressemble plus à une direction qu'à un exemple réel. Vous devez modifier cet extrait de code avec le nom de l'activité de départ, l'ID de l'intention et la mécanique de sortie quoi que vous en ayez. Ne copiez pas aveuglément, collez-le.
Oleg Koshkin
19
Cela ne fonctionne plus avec Android Q en raison de nouvelles restrictions aux activités d'arrière-plan developer.android.com/preview/privacy/…
Marco Righini
103

Vous pouvez simplement appeler:

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

Qui est utilisé dans la bibliothèque ProcessPhoenix


Comme alternative:

Voici une version un peu améliorée de la réponse @Oleg Koshkin.

Si vous voulez vraiment redémarrer votre activité, y compris l'arrêt du processus en cours, essayez de suivre le code. Placez-le dans une HelperClass ou là où vous en avez besoin.

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

Cela réinitialisera également les classes jni et toutes les instances statiques.

mikepenz
la source
1
Cette solution est agréable, mais elle retardera de quelques secondes le redémarrage de votre application, même si vous avez diminué les 100 millis. Cependant, cette bibliothèque ProcessPhoenix de Jack Wharton le fait mieux et rapidement, mais cela ne vaut pas la peine d'ajouter une bibliothèque uniquement pour cette fonction dans l'application.
blueware
@blueware J'ai mis à jour ma réponse et ajouté le code utilisé dans ProcessPhonix
mikepenz
@mikepenz, ce type "Ilya_Gazman" a fait beaucoup mieux et sans utiliser une telle bibliothèque.
blueware
3
@blueware - Sauf que la solution d'Ilya ne redémarrera pas le processus, donc les données statiques ou les bibliothèques NDK chargées ne seront pas correctement réinitialisées.
Ted Hopp,
Certains appareils Huawei et Samsung ont des restrictions AlarmManageret se comportent mal si vous utilisez cette solution. Une meilleure approche?
blueware
69

Jake Wharton a récemment publié sa bibliothèque ProcessPhoenix , qui le fait de manière fiable. Vous n'avez qu'à appeler:

ProcessPhoenix.triggerRebirth(context);

La bibliothèque terminera automatiquement l'activité d'appel, tuera le processus de demande et redémarrera ensuite l'activité d'application par défaut.

TBieniek
la source
Cela semble fonctionner, mais j'obtiens un plantage (qui est signalé). Pas sûr que ce soit idéal.
BK-
1
Je n'ai jamais eu de problème avec la bibliothèque, mais n'hésitez pas à signaler un bug sur github.com/JakeWharton/ProcessPhoenix/issues
TBieniek
Argh, je retire mon commentaire car je n'ai pas regardé le message assez près. Il me manquait un filtre d'intention sur mon activité de lancement par défaut. Il peut être utile de noter les filtres d'intention exacte requis.
BK-
1
C'est jusqu'à présent la meilleure solution.
yongsunCN
1
@Shambhu, vous devez ajouter la balise <category android:name="android.intent.category.DEFAULT" />à votre activité par défaut <intent-filter> dans le manifeste de l'application.
Muhammed Refaat
57

J'ai légèrement modifié la réponse Ilya_Gazman pour utiliser de nouvelles API (IntentCompat est déconseillé à partir de l'API 26). Runtime.getRuntime (). Exit (0) semble être meilleur que 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
la source
8
Directement à partir des documents : " L'appel System.exit(n) est effectivement équivalent à l'appel: Runtime.getRuntime().exit(n) ". En interne, System.exit()se retourne et appelle Runtime.getRuntime().exit(). Il n'y a rien de "meilleur" dans l'un ou l'autre (sauf si l'on se préoccupe de la quantité de frappe que l'on fait ou d'une couche supplémentaire d'appels de méthode).
Ted Hopp du
où et quand appeler la méthode ci-dessus?
Makvin
1
@Makvin vous décidez où l'appeler. Mon cas a redémarré l'application après un changement de langue.
android_dev
@TedHopp a commenté chaque réponse comme "pas bonne", avez-vous une solution possible? N'étant pas sarcastique, il faut vraiment recréer une application sans laisser de trace; des variables statiques aux instances de classe.
Farid
1
@FARID - Toutes les solutions qui impliquent d'appeler Runtime.getRuntime().exit(0)(ou System.exit(0)) fonctionneront probablement. Certains de mes " mauvais commentaires" sont des réponses (comme celle d' Ilya Gazman qui a depuis été modifiée pour incorporer un tel appel.
Ted Hopp
37

IntentCompat.makeRestartActivityTask

La nouvelle façon de procéder consiste à utiliser IntentCompat.makeRestartActivityTask

Créez une intention qui peut être utilisée pour relancer la tâche d'une application dans son état de base. Cela ressemble à makeMainActivity (ComponentName), mais définit également les indicateurs Intent.FLAG_ACTIVITY_NEW_TASK et 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
la source
6
Cela relance la tâche, mais il ne redémarre pas le processus, ni même l' Applicationobjet. Par conséquent, toutes les staticdonnées, données initialisées lors de la création des Applicationclasses, ou jni restent dans leur état actuel et ne sont pas réinitialisées.
Ted Hopp
2
@TedHopp Oh j'ai raté cette partie. J'ai ajouté System.exit (0); Mais je ne suis pas sûr à 100% que cela fonctionnera. Je le
testerai plus tard
1
La meilleure solution sans utiliser de bibliothèque open source pour le faire.
Levez la
4
Malheureusement, IntentCompat.makeRestartActivityTaskest désormais obsolète . Si vous inspectez le code source , c'est aussi simple que d'ajouter simplement des indicateurs Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK.
Paul Lammertsma
IntentCompat.makeRestartActivityTask supprimée
luckyhandler
28

Il y a un truc vraiment sympa. Mon problème était qu'une bibliothèque jni C ++ vraiment ancienne avait perdu des ressources. À un moment donné, il a cessé de fonctionner. L'utilisateur a tenté de quitter l'application et de la relancer - sans résultat, car terminer une activité n'est pas la même chose que terminer (ou tuer) le processus. (Soit dit en passant, l'utilisateur pourrait accéder à la liste des applications en cours d'exécution et l'arrêter à partir de là - cela fonctionnerait, mais les utilisateurs ne savent tout simplement pas comment mettre fin aux applications.)

Si vous souhaitez observer l'effet de cette fonctionnalité, ajoutez une staticvariable à votre activité et incrémentez-la chacune, par exemple, appuyez sur le bouton. Si vous quittez l'activité d'application, puis appelez à nouveau l'application, cette variable statique conservera sa valeur. (Si l'application était vraiment fermée, la variable se verrait attribuer la valeur initiale.)

(Et je dois expliquer pourquoi je ne voulais pas corriger le bogue à la place. La bibliothèque a été écrite il y a des décennies et des fuites de ressources depuis. La direction pense que cela a toujours fonctionné . Le coût de la fourniture d'un correctif au lieu d'une solution de contournement ... Je pense que vous avez l'idée.)

Maintenant, comment pourrais-je réinitialiser une bibliothèque partagée jni (aka dynamic, .so) à son état initial? J'ai choisi de redémarrer l'application en tant que nouveau processus.

L'astuce est que System.exit () ferme l'activité en cours et Android recrée l'application avec une activité de moins.

Le code est donc:

/** 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));
    }
}

L'activité appelante exécute simplement le code MagicAppRestart.doRestart(this);, l'activité appelante onPause()est exécutée, puis le processus est recréé. Et n'oubliez pas de mentionner cette activité dans AndroidManifest.xml

L'avantage de cette méthode est qu'il n'y a pas de retards.

UPD: cela fonctionnait dans Android 2.x, mais dans Android 4 quelque chose a changé.

18446744073709551615
la source
3
j'ai utilisé activity.startActivity (i); System.exit (0); genius solution
max4ever
5
Cette solution ferme l'application pour moi, mais elle ne redémarre pas. Au moins sur Android 4.3.
Kirill Rakhman
1
Sur Samsung Galaxy Mega Android 4.2.2, il provoque une boucle de redémarrage infinie. Donc, l'application ne redémarrera pas.
Gunhan
@Gunhan 1) que se passe-t-il si vous remplacez System.exit(0)par android.os.Process.killProcess(android.os.Process.myPid());? 2) une boucle infinie signifie très probablement qu'ils ne suppriment pas l'activité la plus élevée lorsqu'ils redémarrent une application. En principe, vous pouvez ajouter une variable booléenne statique, la définir sur true avant d'appeler l'activité de redémarrage et après le redémarrage, elle sera fausse. Ainsi, l'activité peut savoir si le redémarrage a déjà eu lieu (et si cela s'est produit, il suffit de terminer () ). OTOH, votre rapport signifie que l'astuce ne fonctionne pas de manière identique sur tous les appareils.
18446744073709551615
@Gunham Si vous démarrez la même activité qui est à l'origine du redémarrage, alors ce sera une boucle infinie sur n'importe quel appareil.
Lukas Hanacek
23

Ma solution ne redémarre pas le processus / l'application. Il permet uniquement à l'application de "redémarrer" l'activité à domicile (et de rejeter toutes les autres activités). Cela ressemble à un redémarrage pour les utilisateurs, mais le processus est le même. Je pense que dans certains cas, les gens veulent obtenir cet effet, alors je laisse juste ici FYI.

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

Ok, j'ai refactorisé mon application et je ne terminerai pas A automatiquement. Je laisse cette course toujours et la termine tout au long de l' onActivityResultévénement. De cette façon, je peux utiliser les drapeaux FLAG_ACTIVITY_CLEAR_TOP+ FLAG_ACTIVITY_NEW_TASKpour obtenir ce que je veux:

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

et dans le 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);
}

Merci quand même!

Coincé
la source
23
Cela ne redémarrera pas l'application, seulement recréera les classes. Ainsi, toutes les variables statiques au sein des classes conserveront les valeurs des exécutions précédentes.
Brian White
14
Intent i = getBaseContext().getPackageManager().getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
Nirav Ranpara
la source
24
Cela ne redémarrera pas l'application, seulement recréera les classes. Ainsi, toutes les variables statiques dans les classes conserveront les valeurs des exécutions précédentes.
Brian White
14

Le seul code qui n'a pas déclenché «Votre application s'est fermée de façon inattendue» est le suivant. C'est également du code non obsolète qui ne nécessite pas de bibliothèque externe. Il ne nécessite pas non plus de minuterie.

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
la source
8

J'ai constaté que cela fonctionne sur l'API 29 et versions ultérieures - dans le but de tuer et de redémarrer l'application comme si l'utilisateur l'avait lancée alors qu'elle n'était pas en cours d'exécution.

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.
}

Cela a été fait lorsque l'activité du lanceur dans l'application a ceci:

<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>

J'ai vu des commentaires affirmant qu'une catégorie de DEFAUT est nécessaire, mais je n'ai pas trouvé que c'était le cas. J'ai confirmé que l'objet Application dans mon application est recréé, donc je crois que le processus a vraiment été tué et redémarré.

Le seul but pour lequel j'utilise ceci est de redémarrer l'application après que l'utilisateur a activé ou désactivé les rapports de plantage pour Firebase Crashlytics. Selon leurs documents, l'application doit être redémarrée (processus tué et recréé) pour que cette modification prenne effet.

Mark Peters
la source
7

La meilleure façon de redémarrer complètement une application est de la relancer, pas seulement de passer à une activité avec FLAG_ACTIVITY_CLEAR_TOPet FLAG_ACTIVITY_NEW_TASK. Donc ma solution est de le faire depuis votre application ou même depuis une autre application, la seule condition est de connaître le nom du package de l'application (exemple: ' 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);
}

Exemple de redémarrage d'utilisation ou de lancement de appA à partir de appB :

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

Vous pouvez vérifier si l'application est en cours d'exécution:

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

Remarque : je sais que cette réponse est un peu hors sujet, mais elle peut être très utile pour quelqu'un.

Choletski
la source
5

Ma meilleure façon de redémarrer l'application est d'utiliser finishAffinity();
Depuis, finishAffinity();ne peut être utilisé que sur les versions JELLY BEAN, donc nous pouvons utiliser ActivityCompat.finishAffinity(YourCurrentActivity.this);pour les versions inférieures.

Ensuite, utilisez Intentpour lancer la première activité, de sorte que le code ressemblera à ceci:

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

J'espère que ça aide.

Hussein ND
la source
1
Cela met fin à toutes les activités de la tâche en cours, mais ne redémarre pas le processus, ni même recrée l'objet Application. Par conséquent, toutes les données statiques, les données initialisées lors de la création de l'application ou par les classes jni, restent dans leur état actuel et ne sont pas réinitialisées.
Ted Hopp
3

Essayez d'utiliser FLAG_ACTIVITY_CLEAR_TASK

Pedro Loureiro
la source
hm en développement pour 2.1: Intent.FLAG_ACTIVITY_CLEAR_TASK ne peut pas être résolu
Bloqué le
Désolé - Depuis: API Level 11 developer.android.com/reference/android/content/…
Pedro Loureiro
3

Voici un exemple pour redémarrer votre application de manière générique à l'aide du PackageManager:

Intent i = getBaseContext().getPackageManager()
             .getLaunchIntentForPackage( getBaseContext().getPackageName() );
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
Alireza Ghanbarinia
la source
Cela relance la tâche, mais il ne redémarre pas le processus, ni même l' Applicationobjet. Par conséquent, les données statiques, les données initialisées lors de la création des Applicationclasses ou jni restent dans leur état actuel et ne sont pas réinitialisées.
Ted Hopp
3

essaye ça:

Intent intent = getPackageManager().getLaunchIntentForPackage(getPackageName());
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
veeson
la source
1
Comme pour toutes les autres réponses ici suggérant déjà la même chose, cela ne redémarrera pas l'application, seulement recréera les classes. Ainsi, toutes les données statiques du processus ne seront pas réinitialisées.
Ted Hopp
2

Démarrez directement l'écran initial avec FLAG_ACTIVITY_CLEAR_TASKet FLAG_ACTIVITY_NEW_TASK.

Yijun Li
la source
2

J'ai dû ajouter un gestionnaire pour retarder la sortie:

 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
la source
2

Utilisation:

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

Cela fonctionne à partir du niveau 16 (4.1) de l'API, je crois.

Peter Mortensen
la source
1

Vous pouvez utiliser la startInstrumentationméthode de Activity. Vous devez implémenter vide Instrumentationet pointé dans le manifeste. Après cela, vous pouvez appeler cette méthode pour redémarrer votre application. Comme ça:

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

J'obtiens le nom de classe d'Instrumentation dynamiquement mais vous pouvez le coder en dur. Certains aiment ça:

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

Appelez startInstrumentationpour recharger votre application. Lisez la description de cette méthode. Mais il peut être dangereux de se comporter comme une application de mise à mort.

Enyby
la source
1

L'application sur laquelle je travaille doit donner à l'utilisateur la possibilité de choisir les fragments à afficher (les fragments sont modifiés dynamiquement au moment de l'exécution). La meilleure solution pour moi était de redémarrer complètement l'application.

J'ai donc essayé de nombreuses solutions et aucune d'entre elles n'a fonctionné pour moi, mais ceci:

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

En espérant que cela va aider quelqu'un d'autre!

hzitoun
la source
0

essaye ça:

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
la source
-1

Avec la bibliothèque Process Phoenix . L'activité que vous souhaitez relancer s'appelle "A".

Saveur Java

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

Saveur de kotlin

// kotlin
fun restart() {
    ProcessPhoenix.triggerRebirth(context)
}
Raymond Chenon
la source
Cela a le malheureux résultat de déconnecter votre débogueur.
DrSatan1
-3

Vous pouvez redémarrer votre activité actuelle comme ceci:

Fragment:

activity?.recreate()

Activité:

recreate()

la source
3
Ce n'est pas du tout ce que OP veut faire.
Ted Hopp