[android] Quitter une application est-il mal vu?



Answers

Je voudrais juste ajouter une correction ici pour les futurs lecteurs de ce fil. Cette nuance particulière a échappé à ma compréhension pendant longtemps donc je veux m'assurer qu'aucun d'entre vous ne fasse les mêmes erreurs:

System.exit() ne tue pas votre application si vous avez plus d'une activité sur la pile. Ce qui se passe réellement, c'est que le processus est tué et redémarré immédiatement avec une activité de moins sur la pile. C'est également ce qui se produit lorsque votre application est supprimée par la boîte de dialogue Forcer la fermeture, ou même lorsque vous essayez de supprimer le processus de DDMS. C'est un fait qui est entièrement non documenté, à ma connaissance.

La réponse courte est, si vous voulez quitter votre application, vous devez garder une trace de toutes les activités dans votre pile et finish() TOUS quand l'utilisateur veut sortir (et non, il n'y a aucun moyen de parcourir la pile d'activité, vous devez donc gérer tout cela vous-même). Même cela ne tue pas réellement le processus ou les références pendantes que vous pourriez avoir. Il finit simplement les activités. En outre, je ne suis pas sûr que Process.killProcess(Process.myPid()) fonctionne mieux; Je ne l'ai pas testé.

Si, par contre, il est acceptable que des activités restent dans votre pile, il existe une autre méthode qui rend les choses super faciles pour vous: Activity.moveTaskToBack(true) mettra simplement en arrière-plan votre processus et affichera l'écran d'accueil.

La réponse longue implique une explication de la philosophie derrière ce comportement. La philosophie est née d'un certain nombre d'hypothèses:

  1. Tout d'abord, cela se produit uniquement lorsque votre application est au premier plan. Si c'est en arrière-plan, le processus se terminera très bien. Cependant, s'il est au premier plan, le système d'exploitation suppose que l'utilisateur veut continuer à faire ce qu'il / elle faisait. (Si vous essayez de tuer le processus de DDMS, vous devez d'abord frapper le bouton d'accueil, puis le tuer)
  2. Il suppose également que chaque activité est indépendante de toutes les autres activités. Ceci est souvent vrai, par exemple dans le cas où votre application lance l'activité du navigateur, qui est entièrement séparée et n'a pas été écrite par vous. L'activité du navigateur peut ou non être créée sur la même tâche, en fonction de ses attributs manifestes.
  3. Il suppose que chacune de vos activités est complètement autonome et peut être tué / restauré dans un délai d'un instant. (Je déteste cette hypothèse particulière, car mon application a de nombreuses activités qui reposent sur une grande quantité de données en cache, trop grandes pour être sérialisées efficacement pendant onSaveInstanceState , mais whaddya va faire?) Pour la plupart des applications Android bien écrites cela devrait être vrai , puisque vous ne savez jamais quand votre application va être tué en arrière-plan.
  4. Le facteur final n'est pas tant une hypothèse, mais plutôt une limitation de l'OS: tuer l'application explicitement est la même que l'application s'écrase, et aussi la même chose que Android tuant l'application pour récupérer la mémoire. Cela aboutit à notre coup de grâce: puisque Android ne peut pas dire si l'application a quitté ou s'est écrasé ou a été tué en arrière-plan, il suppose que l'utilisateur veut retourner là où ils l'avaient laissé, et ActivityManager redémarre le processus.

Quand vous y réfléchissez, c'est approprié pour la plate-forme. Tout d'abord, c'est exactement ce qui se passe quand le processus est tué en arrière-plan et que l'utilisateur y revient, il doit donc être redémarré là où il s'est arrêté. Deuxièmement, c'est ce qui se passe lorsque l'application se bloque et présente la redoutable boîte de dialogue Force Close.

Dites que je veux que mes utilisateurs puissent prendre une photo et la télécharger. Je lance l'activité Appareil photo depuis mon activité et je lui demande de renvoyer une image. La caméra est poussée sur le dessus de ma tâche actuelle (plutôt que d'être créée dans sa propre tâche). Si la caméra a une erreur et se bloque, cela devrait-il entraîner une panne totale de l'application? Du point de vue de l'utilisateur, seule la caméra a échoué, et ils devraient être retournés à leur activité précédente. Donc, il redémarre simplement le processus avec toutes les mêmes activités dans la pile, moins la caméra. Puisque vos Activités doivent être conçues de manière à pouvoir être tuées et restaurées à la dernière minute, cela ne devrait pas poser de problème. Malheureusement, toutes les applications ne peuvent pas être conçues de cette façon, c'est donc un problème pour beaucoup d'entre nous, peu importe ce que Romain Guy ou quelqu'un d'autre vous dit. Donc, nous devons utiliser des solutions de contournement.

Alors, mon dernier conseil:

  • N'essayez pas de tuer le processus. Appelez finish() sur toutes les activités ou appelez moveTaskToBack(true) .
  • Si votre processus se bloque ou est tué, et si, comme moi, vous avez besoin des données qui étaient en mémoire et qui sont maintenant perdues, vous devrez revenir à l'activité racine. Pour ce faire, vous devez appeler startActivity() avec un Intent qui contient l'indicateur Intent.FLAG_ACTIVITY_CLEAR_TOP .
  • Si vous voulez supprimer votre application de la perspective Eclipse DDMS, il vaut mieux ne pas être au premier plan, ou elle va redémarrer elle-même. Vous devez d'abord appuyer sur le bouton Accueil, puis arrêter le processus.
Question

En continuant dans ma tentative d'apprendre Android, je viens de lire ce qui suit :

Question: L'utilisateur a-t-il le choix de tuer l'application à moins de mettre une option de menu pour la tuer? Si aucune option n'existe, comment l'utilisateur met-il fin à l'application?

Réponse: (Romain Guy): L'utilisateur ne le fait pas, le système le gère automatiquement. C'est ce que le cycle de vie de l'activité (en particulier onPause / onStop / onDestroy) est destiné. Peu importe ce que vous faites, ne mettez pas un bouton d'application "Quitter" ou "Quitter". C'est inutile avec le modèle d'application d'Android. Cela est également contraire au fonctionnement des applications principales.

Hehe, pour chaque étape que je prends dans le monde Android, je rencontre une sorte de problème = (

Apparemment, vous ne pouvez pas quitter une application sous Android (mais le système Android peut très bien détruire totalement votre application dès qu'il en a envie). Qu'est-ce qui se passe avec ça? Je commence à penser qu'il est impossible d'écrire une application qui fonctionne comme une "application normale" - que l'utilisateur peut quitter l'application quand il / elle décide de le faire. Ce n'est pas quelque chose que l'on devrait faire confiance à l'OS.

L'application que j'essaie de créer n'est pas une application pour l'Android Market. Il ne s'agit pas d'une application «grand public» par le grand public, c'est une application métier qui va être utilisée dans un domaine très étroit.

J'étais vraiment impatient de développer pour la plate-forme Android, car il résout beaucoup de problèmes qui existent dans Windows Mobile et .NET. Cependant, la dernière semaine a été quelque peu une sortie pour moi ... J'espère que je ne dois pas abandonner Android, mais il ne semble pas très bon dès maintenant = (

Y a-t-il un moyen pour moi de vraiment quitter l'application?




The Linux kernel has a feature called Out-of-memory killer (as mentioned above, the policies are configurable at the userspace level as well as the kernel is not an optimal one, but by no means unnecessary).

And it is heavily used by Android:

Some userspace apps are available to assist with these kill apps, for example:




Vous pouvez quitter, soit en appuyant sur le bouton Retour, soit en appelant finish() dans votre Activity . Appelez simplement finish() partir d'un objet MenuItem si vous voulez le supprimer explicitement.

Romain ne dit pas que ça ne peut pas être fait, juste que c'est inutile: les utilisateurs n'ont pas besoin de quitter ou de sauvegarder leur travail ou autre, car le cycle de vie de l'application vous encourage à écrire des logiciels intelligents qui sauvegardent automatiquement restaure son état, peu importe ce qui se passe.




The Android application life cycle is designed for mobile phone users, not computer users.

The app life-cycle is the brutally simplistic paradigm required to turn a Linux server into a consumer appliance.

Android is Java over Linux, a real cross-platform server OS. That is how it spread so quickly. The app life-cycle encapsulates the underlying reality of the OS.

To mobile users, apps are just installed or not installed. There is no concept of running or exiting. In fact, app processes are meant to run until the OS releases them for their held resources.

Since this is , anyone reading this is a computer user and must turn off 90% of their knowledge to understand the mobile app lifecycle.




It took me longer to read this Q&A than to actually implement a semi-proper Android Application Lifecycle.

It's a GPS app that polls for points and sends the current location to a webservice every few seconds using a thread... This could be polling every 5 minutes in Ted's case for an update, then onStop can simply start the update activity Ted was soo concerned about if one was found (asynchronous Ted, don't code like a Windows programmer or your programs will run like Windows programs ... eww, it's not that hard).

I did some initial code in onCreate to set up things for the activity lifetime, including checkUpdate.start(); :

...

@Override
public void onStart() {
    super.onStart();
    isRemote = true;
    checkUpdate.resume();

    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, luh);
}

@Override
public void onPause() {
    isRemote = false;
    checkUpdate.suspend();
    locationManager.removeUpdates(luh);
    super.onStop();
}

This code may be completely wrong, but it works. This is one of my first Android applications.

Voilà, an application that doesn't consume CPU when it's in the background, yet is instantly ready to reopen because it is in RAM (although not holding RAM as is the Android lifecycle) ... an app is always ready, it's a phone, guys/gals. If an app was to use up all the RAM and couldn't be shut down by the OS then the thing might stop ringing =P That's why the OS needs to be able to close your app when it's in the background (if your application isn't a resource hog it won't be closed BTW), so let's just write better applications.




I think the point is that there is no need to quit the app unless you have buggy software. Android quits the app when the user is not using it and the device needs more memory. If you have an app that needs to run a service in the background, you will likely want a way to turn the service off.

For example, Google Listen continues to play podcast when the app is not visible. But there is always the pause button to turn the podcast off when the user is done with it. If I remember correctly, Listen, even puts a shortcut in the notification bar so you can always get to the pause button quickly. Another example is an app like a twitter app for instance which constantly polls a service on the internet. These types of apps should really allow the user to choose how often to poll the server, or whether even to poll in a background thread.

If you need to have code that runs on exit, you can override onPause(), onStop(), or onDestroy() as appropriate. http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle




Hmmmm...

I think that you just don't see the Android app the right way. You can do something almost like what you want easily:

  • Do the app activities save/restore state like it is encouraged in the developer livecycle documentation.

  • If some login is needed at the restore stage (no login/session information available) then do it.

  • Eventually add a button/menu/timeout in which case you will do a finish() without saving the login and other session info, making implicitly the end of app session: so if the app is started/brought to front again it will start a new session.

That way you don't really care if the app is really removed from memory or not.

If you really want to remove it from memory (this is discouraged, and BTW for what purpose?) you can kill it conditionally at the end of onDestroy() with java.lang.System.exit(0) (or perhaps restartPackage(..) ?). Of course do it only in the case where you want to "really end the app", because the onDestroy() is part of the normal lifecycle of activities and not an app end at all.




If you have 10,20 .. multiple Activities running and you want to finish all them and exit from system.

Create a static array in application class or constants class.

Constants

public class Constants {

public static ArrayList<Activity> activities = new ArrayList<Activity>();

}

MainActivity Ajouter la référence d'activité actuelle dans ce tableau

activity = MainActivity.this; Constants.activities.add(activity);

public class MainActivity extends Activity {

    private ImageView imageButton;
    private Activity activity;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        activity = MainActivity.this;
        Constants.activities.add(activity);

        imageButton = (ImageView) findViewById(R.id.camera);
        imageButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                // existing app.
                if (Constants.activities != null) {
                    for (int i = 0; i < Constants.activities.size(); i++) {
                        Activity s = Constants.activities.get(i);
                        s.finish();
                    }
                }
                //super.finish();
                finish();
                android.os.Process.killProcess(android.os.Process.myPid());
                System.exit(1);
            }
        });
    }
}



Ted, ce que vous essayez d'accomplir peut être fait, peut-être juste pas comment vous y pensez en ce moment.

Je vous suggère de lire sur les activités et services. Cessez d'utiliser le terme "app" et commencez à vous référer aux composants, c'est-à-dire Activité, Service. Je pense que vous avez juste besoin d'en savoir plus sur la plate-forme Android; C'est un changement d'état d'esprit d'une application PC standard. Le fait qu'aucun de vos posts n'ait eu le mot "Activité" (en l'absence d'une citation FAQ, c'est-à-dire pas vos mots) en eux me dit que vous devez en lire plus.




There is a (relatively) simple design which will allow you to get around the "exit" conundrum. Make your app have a "base" state (activity) which is just a blank screen. On the first onCreate of the activity, you can launch another activity that your app's main functionality is in. The "exit" can then be accomplished by finish()ing this second activity and going back to the base of just a blank screen. The OS can keep this blank screen in memory for as long as it wants...

In essence, because you cannot exit out to OS, you simply transform into a self-created nothingness.




I would consider reading "Android Wireless Application Development" published by Addison-Wesley. I am just finishing it up and it is VERY thorough.

It appears that you have some fundamental misunderstandings of the Android platform. I too was a little frustrated at first with the application life-cycle of Android apps, but after coming to a greater understanding, I have come to really enjoy this approach. This book will answer all of your questions and much more. It really is the best resource I have found for new Android developers.

Also, I think you need to let go of a line-for-line port of the existing app. In order to port your application to the Android platform, some of the application design is going to change. The application-lifecycle used is necessary as mobile devices have very limited resources relative to desktop systems and allows Android devices to run several applications in an orderly and resource-aware fashion. Do some more in depth study of the platform, and I think you will realize that what you are wanting to do is entirely feasible. Bonne chance.

By the way, I am no way affiliated with Addison-Wesley or any person or organization associated with this book. After re-reading my post I feel that I came off a little fanboyish. I just really, really enjoyed it and found it extremely helpful. :)




Almost 99% of the time there is no need for an Android application to take over its own life cycle. Most of the time it comes down to better planning or smarter design of the application. For example, rather build an internal service (not exported) to handle downloads, etc., or design actions and tasks around user workflow.

But that being said, where there is a will there is a way. Android provides - through the android.os.Process class, a much better API than Java to control the underlying process. And unlike Java it does not treat the developer like a moron by hiding it all behind a simple java.lang.System.exit() call.

So how do you ask your application to commit suicide in Android? Well, the trick is simple:

Create your own Android application class by inheriting from the standard android.app.Application class (remember to declare it in the AndroidManifest.xml file).

Override the onCreate() method, and store the process ID which started your application:

this.pid = android.os.Process.myPid(); // Save for later use.

Now to kill your application, provide a kill() method:

android.os.Process.sendSignal(pid, android.os.Process.SIGNAL_KILL);

Now whenever you need your app to commit suicide just type cast the application context, and call your kill method!

((MySuicidalApp) context.getApplicationContext()).kill()

Just remember that due to the process management policies in Android, specifically related to services, Android may just opt to restart your service (see You should not use task killers on Android ).




You apparently have found the answer you want in the finish() command. This will not remove your app from memory, but Android will do so whenever it needs the resources, so it doesn't make any difference that you won't be doing that explicitly.

I would only add that in order to attain the full effect that an application exit would typically have, you would want to reset the app's state to whatever its state is normally at the time it is first run after a boot of the device, just prior to calling finish() on all of your activities. That way, if the user selects your app again, it will appear to have been run "fresh," without any state left over from the point prior to the simulated "exit."

If there are some special actions that should only occur on "exit," such as saving the user's work or whatever, you can also perform them prior to the re-initialization part of the above routine.

This approach allows you to accomplish your goal of having an "exit" command without violating Android's philosophy of leaving the management of OS resources, including the closing of apps, in the hands of the operating system.

Personally, I would not use this approach, because Android users expect an app to preserve its continuity when they revisit it, and so they are not used to the modality of "exiting" an app. I would instead support a "clear" function that a user can invoke to reset the app to some default initial state, without the necessity of "leaving" it in the process.

The one exception would be when the user has hit the back button a sufficient number of times to cause the app to close. In that situation, there is no expectation on the user's part that state will have been saved (and if there is unsaved state in the app, then you, as the developer, should have code handling the back button that detects that unsaved data, and prompts the user to save it to SharedPreferences or to a file, or to some other non-volatile medium).

Regarding system.exit(0):

If you do decide to use system.exit(0) to close your app with rude finality (eg, as a result of a final back button press), then I would warn you that although for me this "works," and in some cases has been the only way I've been able to close an app without any trace of it remaining, there is one minor glitch that occurs in Jelly Bean when you use this approach.

Specifically, if you use the Recent Apps list to open your app, and then use the back button to close the app (with that close implemented via system.exit(0)), the Recent Apps list will become visible again, as it will never have been closed. If you then tap on your app's entry in that list to run it a second time from the same, already-open, Recent Apps list, there will be no response.

I suspect that the cause of this is that the Recent Apps list is holding on to a reference to your app that has become non-functional due to your having closed the app using system.exit(0). A more civilized closing of your app using finish() might have informed the OS in a manner that would have allowed it to refresh its Recent Apps list, but system.exit(0) apparently does not do this.

This is not a huge problem in and of itself, as very few people will open an app from Recent Apps, then exit it, and then immediately open it again from the same open Recent Apps list. And if they tap the home button and then re-open the Recent Apps list, your app's entry will be there, and it will be fully functional. But I think that it shows that the use of system.exit(0) can interfere with proper communication between your app and the OS, and this suggests that there may be other, more serious, possibly subtle, consequences of using this approach.




For closing an app at any point use FLAG_ACTIVITY_CLEAR_TOP flag in Intent and then system.exit();

Or there is similar way, but without system.exit() when you want to exit call this method:

public void exit() {
    startActivity(new Intent(this, HomeActivity.class).
    setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK).putExtra(EXIT_FLAG, true));
}

In your HomeActivity.onCreate() add following code

protected void onCreate(Bundle savedInstanceState) {
    if (getIntent().getBooleanExtra(EXIT_FLAG, false)) {
        if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
            finish();
        }
    }
......................

This will work without breaking the Android life-cycle.




Arrêtez de penser à votre application en tant qu'application monolithique. C'est un ensemble d'écrans d'interface utilisateur que l'utilisateur peut interagir avec votre «application», et les «fonctions» fournies via les services Android.

Ne pas savoir ce que votre application mystérieuse "fait" n'est pas vraiment important. Supposons qu'il s'introduit dans un intranet d'entreprise super sécurisé, effectue une surveillance ou une interaction et reste connecté jusqu'à ce que l'utilisateur «quitte l'application». Parce que votre service informatique le commande, les utilisateurs doivent être très conscients du moment où ils sont entrés ou sortis de l'intranet. D'où votre état d'esprit qu'il est important pour les utilisateurs de "quitter".

C'est simple. Créez un service qui met une notification en cours dans la barre de notification en disant "Je suis dans l'intranet ou je cours". Avoir ce service effectuer toutes les fonctionnalités dont vous avez besoin pour votre application. Avoir des activités qui lient à ce service pour permettre à vos utilisateurs d'accéder aux bits de l'interface utilisateur dont ils ont besoin pour interagir avec votre «application». Et avoir un menu Android -> Quitter (ou se déconnecter, ou autre) bouton qui dit au service de quitter, puis ferme l'activité elle-même.

C'est, à toutes fins utiles exactement ce que vous dites que vous voulez. Fait de la manière Android. Regardez Google Talk ou Google Maps Navigation pour des exemples de cette "sortie" est la mentalité possible. La seule différence est que le fait d'appuyer sur le bouton de retour hors de votre activité peut laisser votre processus UNIX à l'affût au cas où l'utilisateur voudrait faire revivre votre application. Ce n'est vraiment pas différent d'un système d'exploitation moderne qui met en cache les fichiers récemment accédés en mémoire. Après avoir quitté votre programme Windows, les ressources les plus probables dont il a besoin sont toujours en mémoire, attendant d'être remplacées par d'autres ressources car elles sont chargées maintenant qu'elles ne sont plus nécessaires. Android est la même chose.

Je ne vois vraiment pas ton problème.




Related



Tags

android android