25

I would like to launch an intent when any of my activity is visible, otherwise I will put it up as a notification, and will be fired by the user.

To decide this, I need to know if any of my activity is front-most, how do I that?

Pentium10
  • 204,586
  • 122
  • 423
  • 502

5 Answers5

10

I don't know that there's a method to get the currently displayed activity, but you could do something combining the Activity Lifecycle and a flag.

For the flag, if you've extended the Application class, that's probably a decent place to store it. For extending the application class, the top answer to this question has info. (d).

So probably keep track of the current active activity (or a flag that the activity is visible) in onResume/onPause or onStart/onStop depending on exactly what behavior you want.

Since you have multiple activities, you'll need a centroid place for storing the flag, which is why the Application makes sense. You can get the custom Application object by casting the application context (e.g. ((MyApplication)getApplicationContext()).isMyActivityActive).

You could extend Activity as well to help keep this code clean and contained.


If you're using a service you could bind to the service in every activity in the onStart/onStop (or onResume/onPause). If bound, you're visible.

Community
  • 1
  • 1
mbafford
  • 2,266
  • 1
  • 20
  • 25
  • 1
    It is not true in all cases. For instance, when you acquire a wake lock PROXIMITY_SCREEN_OFF_WAKE_LOCK, to mimic the behavior of a call mode, when screen turns off or on as user put the phone near to his ear, it is desired behavior when you write for example a voip application. But as user put the phone near his head and the screen blocks, then the onPause is called, and in the opposite onResume. The problem is, you don't know why it is called, so you don't know if you should pause your application or not. So there are possible some other events, that may cause call to onPause or onResume. – Krzysztof Cichocki Aug 26 '15 at 08:47
4

You can ask for the running tasks from ActivityManager:

ActivityManager activityManager = (ActivityManager)getContext()
                .getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> runningTasks = activityManager.getRunningTasks(Integer.MAX_VALUE));

From API docs:

Return a list of the tasks that are currently running, with the most recent being first and older ones after in order.

So the first item on the list is the frontmost activity.

Zds
  • 4,311
  • 2
  • 24
  • 28
  • 14
    Also from the API docs: Note: this method is only intended for debugging and presenting task management user interfaces. This should never be used for core logic in an application, such as deciding between different behaviors based on the information found here. Such uses are not supported, and will likely break in the future. For example, if multiple applications can be actively running at the same time, assumptions made about the meaning of the data here for purposes of control flow will be incorrect. – Edward Dale Jul 23 '12 at 09:11
2

onResume() called && onPause() not called = visible.
Have a public static Activity currentlyVisible; in your Application subclass that will be updated by your activities (set to the instance in onResume() and nulled in onPause()). Or invent a less ugly variant of a registry.

yanchenko
  • 56,576
  • 33
  • 147
  • 165
  • 5
    You should not hold references to the activity object like that... see http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html. – cristis Jun 29 '10 at 06:51
  • Generally speaking - yes. Unless you null references manually before it's too late. – yanchenko Jun 29 '10 at 10:53
  • Because Activity.isResumed or Activity.isStarted would have been too easy... :-) – GenesisST Jun 12 '13 at 16:41
2

You could use onWindowFocusChanged(boolean hasFocus) place this in a superclass of your activities to launch the intent if it has focus.

Grant
  • 258
  • 2
  • 8
  • This is nice, but you'd need custom dialogs, as a dialog will cause onWindowFocusChanged(bool) to tell you the activity isn't visible, according to the documentation. Therefore it doesn't sound like a good solution in this case. You care about application being foreground more than being visible. – Justin Feb 06 '15 at 15:50
0

Instead of using Activity manager there is a simple trick which you can do through code. If you observe the activity cycle closely, the flow between two activities and foreground to background is as follows. Suppose A and B are two activities.

When transition from A to B: 1. onPause() of A is called 2. onResume() of B is called 3. onStop() of A is called when B is fully resumed

When app goes into background: 1. onPause() of A is called 2. onStop() of A is called

You can detect your background event by simply putting a flag in activity.

Make an abstract activity and extend it from your other activities, so that you wont have to copy paste the code for all other activities wherever you need background event.

In abstract activity create flag isAppInBackground.

In onCreate() method: isAppInBackground = false;

In onPause() method: isAppInBackground = false;

In onStop() method: isAppInBackground = true;

You just to need to check in your onResume() if isAppInBackground is true. n after you check your flag then again set isAppInBackground = false

For transition between two activities since onSTop() of first will always called after second actvity resumes, flag will never be true and when app is in background, onStop() of activity will be called immediately after onPause and hence the flag will be true when you open the app later on.

Ankita
  • 313
  • 1
  • 8