3

How can I tell that my application has been put in the background (i.e. none of my app's activities are visible anymore)? I need to determine this so that I can release resources shared among several of my activities (graphics, sound clips and a socket connection).

I've thought about keeping a global counter that's incremented in the activities' onStart() method, and decremented in onStop(). If the counter reaches zero, then all activities have been stopped and my app is running in the background. However I'm not sure if this is going to be 100% reliable. Also, I can't help but think that there must be a better way of doing this.

Haakon
  • 295
  • 1
  • 12
  • 2
    possible duplicate of http://stackoverflow.com/questions/3136187/how-to-detect-if-any-of-my-activity-is-front-most-and-visible-to-user – Pentium10 Jul 13 '10 at 11:57

5 Answers5

2

You shouldn't need to know this, but to answer you:

in your main activity:

public boolean inBackground;

@Override
public void onPause()
{
     inBackground=true;
     super.onPause();
}

@Override
public void onResume()
{
     inBackground=false;
     super.onResume();
}
Ray Britton
  • 8,257
  • 3
  • 23
  • 32
0

You could use a global counter assuming it is kept in persistent storage. Always keep in mind the system is free to unload and reload activities from device RAM based on pressure from other apps so instance variables of activities are probably not a good choice to house that data.

I think the Android way of handling a scenario like yours would be to manage your connection state in a service and use persistent storage to monitor application state.

ktingle
  • 374
  • 2
  • 9
  • Using a service for this seems a bit heavyweight. Also, it's not just a connection that needs to be released, there's also other resources shared among my activities such as graphics and sound clips that I'd like to release when my app goes in the background (I'll edit this in to my question). Of course the counter wouldn't be kept in an Activity instance variable. It would probably live in the custom Application class I have in my app, which of course will persist for the entire lifetime of my app. – Haakon Jul 13 '10 at 11:59
0

If you need this functionality maybe your architecture is not well designed. Each activity must be in some way "standalone" so when it's stopped release any data associate with it. If you need to store some persistant data between activities use sql or some other data storage and if you need some shared resources between activities put them in service. Try to isolate any coupling between activities.

Mojo Risin
  • 8,136
  • 5
  • 45
  • 58
  • It's not necessary problem with architecture. Image that you wish to have Interstitial Ads whenever the application is coming from background. Then it's not a matter of persisting resources, but finding what happened with the lifecycle of the app. – luben Nov 28 '13 at 09:40
0

I haven't tried this myself yet, but I think the following would work.

  • Create your own custom Activity class that extends Activity (as suggested in this SO question).
  • Ensure all your activites extend your custom Activity class.
  • @Override the onStop() method (as per the Activity life cycle docs).
  • Have onStop() call the utility method below (code based on Droid-Fu project) to figure out if your app is now in the background.

My worry is there could be some timing windows when your last activity closes before its new activity (also i your app) launches, but hopefully that is avoidable.

public static boolean isApplicationInBackground(Context context) 
{
    ActivityManager am = 
      (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

    List<RunningTaskInfo> tasks = am.getRunningTasks(1);

    if (!tasks.isEmpty()) 
    {
        ComponentName topActivity = tasks.get(0).topActivity;

        if (!topActivity.getPackageName().equals(context.getPackageName())) 
        {
            return true;
        }
    }

    return false;
}

Let us know how you get on as I might need to implement this feature too!

Update: I've done some quick testing of this code.

It seems to work fine when pressing the home key to exit the application, as the running task changes to ComponentInfo{com.motorola.blur.home/com.motorola.blur.home.HomeActivity} on my device. However, the code doesn't detect the app as in the background when using the back button to exit the application (it still thinks my app is running).

This scenario can be detected by overriding onDestroy() in your top level activities, and checking isFinished() to confirm that the app is getting destroyed (rather than the activity being recreated, e.g. for an orientation change).

Community
  • 1
  • 1
Dan J
  • 25,433
  • 17
  • 100
  • 173