7

Over the past months I have been developing a versatile real-time game engine, and I have learned a lot, but I still feel very naive when it comes to the application life cycle. Specifically, I am trying to implement an Activity which can be shuffled in to the background by the user, then properly resumed.

My current architecture is as such: I have a an XML menu launcher activity which can create a real-time Game activity using intent. Relevant data in this Game activity is referenced through static data structures and variables. The Game activity creates worker threads in the onSurfaceCreate() callback of my SurfaceView object.

When a user presses the back button, the activity is destroyed, and they are sent back to the XML menu in the launcher activity. Fine, good for now. When the user presses the home button, the Activity is sent to the background. OK, great. My problems arise when the user tries to find their way back in the Game activity once is has been sent to the background. When the user touches the launcher icon, the Game is destroyed and the menu is re-launched. Also, when the user resumes the game through the task manager, the onSurfaceCreate() callback fires and the worker threads are started, but the game is frozen.

So, I have two questions. First, how do I resume my activity through the launcher icon, instead of re-launching the game? Second, when I resume my activity, what actions are necessary to restart my worker threads while persisting the game data?

Thanks!

EDIT: By request, I am including some code below. My onSurfaceCreate is a little bit complicated, it sends a message to another thread, which then implements the callback. I have verified that this implementation function fires when the Game activity is resumed.

protected void surfaceCreate()
{
    Log.e(TAG, "surfaceCreate");

    Thread gameThread = createGameThread();
    gameThread.start();
}


protected final void onResume()
{
    super.onResume();

    resume();
}

protected final void onPause()
{
    super.onPause();

    pause();
}

These cryptic pause() and resume() methods simply set a boolean variable which prevents some game logic from being executed, they do nothing to hinder the worker threads, which should continue looping.

EDIT: Thanks Mohammad, for solving my first (although smaller) problem. It turns out that the launcher icon behaves differently when not connected by USB to the IDE. The second problem remains unresolved.

EDIT: All working! The second problem turned out to be an issue unique to my code, I apologize for that. I hope that this question can still be useful for those dealing with the launcher and IDEs.

4

1 回答 1

5

There are multiple possible problems/solutions listed in this post. This includes misunderstanding of activity lifecycle and launchMode settings.

First, how do I resume my activity through the launcher icon, instead of re-launching the game?

You are most likely missing definition for your onResume() and onPause() methods. Examples are here:

http://developer.android.com/training/basics/activity-lifecycle/pausing.html

Straight from the API:

onPause() Called as part of the activity lifecycle when an activity is going into the background, but has not (yet) been killed.

onResume() Called after onRestoreInstanceState(Bundle), onRestart(), or onPause(), for your activity to start interacting with the user.

When coding an Android application, you have to understand and follow this flow:

Check the Android Activity Lifecycle out:

http://developer.android.com/reference/android/app/Activity.html

One theory on your issue may be is that you're most likely going to onStop() (by hitting the home button) and the Android OS is looking for your onRestart(), but can't find it hence freezing/restarting.

Second, when I resume my activity, what actions are necessary to restart my worker threads while persisting the game data?

Careful how you use the word restart. You want to pause and resume the application (not restart). Save data in onPause() (use a database or any other save feature you'd like). Load data in onResume(). Although, the activity should resume as normal if you just fill up these methods.

Now, if you want to save state for when you restart the application, you should save states in onStop() and/or onDestroy(). You should load states in onStart(). In order to save states, you can check this out:

https://stackoverflow.com/a/151940/2498729

For those using Eclipse (or any other IDE to run/test your application):

From what have you described you probably have overridden android:launchMode in AndroidManifest.xml or if you are testing by "run as" from Eclipse try exiting the application after installing and auto-starting. Then start again from the emulator and test the Home button behavior. I suppose this is because Android does not put Activities on the OS stack when started from Eclipse and then the Home button behavior is not as usual. If this does not solve your problem, try reading http://developer.android.com/guide/topics/fundamentals.html#lmodes.

I had launchMode set in my StartupActivity. THen I removed that (it was set to "singleTask", it behaves like I want it; the app is "resumed" to the Activity I expect, ie not StartupActivity but MainActivity.

Source:

https://stackoverflow.com/a/1619461/2498729

http://developer.android.com/guide/topics/manifest/activity-element.html

According to this:

https://stackoverflow.com/a/3002890/2498729

You should change your andoird:launchMode to "Standard" (or "default").

Standard: A > B > HOME > B  (what you want)
SingleTask: A > B > HOME > A (what you don't want)
于 2013-08-07T19:07:19.613 回答