6

I've already been looking for solutions about my problem for much time, but The Android documentation is not so clear and web solutions don't work completely.

I'm developing a game in which the main Activity (where the game takes place) can call another simple Activity and than return back. It would work like this:

  1. If the user clicks the Home button and then returns to the game, the activity must be stopped and then resumed without pass the onDestroy (otherwise it would lose the game state)
  2. The same function when the main Activity calls the other Activity and then returns to the game.
  3. When the user presses the exit button the game must exit at all

For the first two points I tried this to be sure that one and only one main Activity is created and called: android:launchMode="singleTask" or android:launchMode="singleTop" but unluckily the first works for the first problem and the second for the second one, not for both!

I think the problem is: with singleTop the main Activity isn't actually on the top of the stack when the second activity calls it (to be clear, I don't understand what should be the situation in which I call an activity that is already on the top of the stack!). Conversely, the singleTask ensures that the Activity is unique in its stack, but after the users click the Home button and returns to the Application the other Task is called, am I right?

Anyway, is this a smart solution or I should save the state of my game in the onStop/onPause and then resume that in the onResume?

For the third point I tried to add the android:noHistory="true" to every Activity, then when the user clicks the exit button I call a new Activity which do nothing but the finish() method on the onCreate, this Activity is called with intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK); and its launchMode is singleInstance, but it doesn't work, it simply returns always in the main Activity.

j0k
  • 22,600
  • 28
  • 79
  • 90
mordicchio
  • 135
  • 4
  • 12

1 Answers1

3

You definitely don't want to mess with the launchMode. That isn't the way to solve this problem and will just cause you more problems.

Android can (and will) kill your process whenever it wants to (but especially if your application is in the background). Because of this, you need to save the state of your game in onPause(), because that is the only opportunity that you are guaranteed to have.

Anyway, if you save the game in onPause() the standard behaviour will cover your first 2 points.

For your 3rd point, there are a few options:

  1. You can start all activities with startActivityForResult() see my answer here
  2. When you want to "exit", you can just go back to your root activity (the one that starts your application) and tell it that you want to exit.

Like this:

Intent intent = new Intent(this, MyRootActivity.class); // this is the starting activity for your application
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); // tells Android to finish all other activities in the stack
intent.addExtra("exit", "true"); // this tells your root activity that you want to exit
startActivity(intent);

Now, in your MyRootActivity you want to add this code to onCreate():

Intent intent = getIntent();
if (intent.hasExtra("exit")) {
    // User wants to exit
    finish();
}
Community
  • 1
  • 1
David Wasser
  • 93,459
  • 16
  • 209
  • 274
  • Thank for the answer. For the first two points I solved using android:launchMode="singleTask" and deleting the android:noHistory="true" (I think this was the real problem). Saving the state on the onPause() could be an option, but how can I save the UI appearance of the Activity? About the third point... this was exactly the solution I used but didn't work because there is the main Activity on the other Task. I solved calling the finish() on the root activity, and then checking in the onResume() of the main Activity if a flag "exit" is setted, in this case I call immediately finish(). – mordicchio Oct 23 '12 at 20:52
  • You don't need to use `launchMode="singleTask"`. The standard launch mode will do what you want. If it doesn't, then you are doing something else wrong. Your whole application should run in one task, not in multiple tasks. There's no reason for that. – David Wasser Oct 24 '12 at 11:54
  • 1
    I agree, but it is not my fault, the problem are the crazy chooses of Google! I want that the main Activity is always one and only one (and must not be destoyed unless rare cases of low memory) and this activity could not be on the top of the stack. So the classic launchMode create multiple instances of my activity, the singleTop resume the activity only if it is on the top, but I don't understand how it could be on the top if I'm calling that from another activity! – mordicchio Oct 24 '12 at 14:29
  • If you are getting multiple instances of your main activity, then you are doing something wrong. Explain where you are getting multiple instances and how you are starting the activity in these cases. – David Wasser Oct 24 '12 at 15:03
  • 1
    You should save state in onSaveInstanceState not in onPause – Greg Ennis Sep 05 '13 at 22:56