By background, I mean none of the application\'s activities are currently visible to the user?
In my opinion, many answers introduce a heavy load of code and bring lots of complexity and non-readability.
When people ask on SO how to communicate between a Service and a Activity, I usually advice to use the LocalBroadcastManager.
Why?
Well, by quoting the docs:
You know that the data you are broadcasting won't leave your app, so don't need to worry about leaking private data.
It is not possible for other applications to send these broadcasts to your app, so you don't need to worry about having security holes they can exploit.
It is more efficient than sending a global broadcast through the system.
Not in the the docs:
Activity, Application, ...Description
So, you want to check if any of the Activity is currently in the foreground. You usually do that in a Service, or your Application class.
This means, your Activity objects become the sender of a signal (I'm on / I'm off). Your Service, on the other hand, becomes the Receiver.
There are two moments in which your Activity tells you if it's going in the foreground or in the background (yes only two... not 6).
When the Activity goes into the foreground, the onResume() method is triggered (also called after onCreate()).
When the Activity goes in the back, onPause() is called.
These are the moments in which your Activity should send the signal to your Service to describe its state.
In case of multiple Activity's, remember the an Activity goes into the background first, then another one comes into the foreground.
So the situation would be:*
Activity1 -- send --> Signal:OFF
Activity2 -- send --> Signal:ON
The Service / Application will simply keep listening for those signals and act accordingly.
Code (TLDR)
Your Service must implement a BroadcastReceiver in order to listen for signals.
this.localBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// received data if Activity is on / off
}
}
public static final IntentFilter SIGNAL_FILTER = new IntentFilter("com.you.yourapp.MY_SIGNAL")
Register the Receiver in Service::onCreate()
@Override
protected void onCreate() {
LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(this.localBroadcastReceiver, SIGNAL_FILTER);
}
Un-register it in Service::onDestroy()
@Override
protected void onDestroy() {
// I'm dead, no need to listen to anything anymore.
LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(this.localBroadcastReceiver);
}
Now your Activity's must communicated their state.
In Activity::onResume()
Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER); // put ON boolean in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
In Activity::onPause()
Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER); // put OFF boolean in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
A very, very common situation
Developer: I want to send data from my
Serviceand update theActivity. How do I check if theActivityis in the foreground?
There is usually no need to check if the Activity is in the foreground or not. Just send the data via LocalBroadcastManager from your Service. If the Activity is on, then it will respond and act.
For this very common situation, the Service becomes the sender, and the Activity implements the BroadcastReceiver.
So, create a Receiver in your Activity. Register it in onResume() and un-register it in onPause(). There is no need to use the other life-cycle methods.
Define the Receiver behavior in onReceive() (update ListView, do this, do that, ...).
This way the Activity will listen only if it's in the foreground and nothing will happen if it's in the back or is destroyed.
In case of multiple Activity's, whichever Activity is on will respond (if they also implement the Receiver).
If all are in the background, nobody will respond and the signal will simply get lost.
Send the data from the Service via Intent (see code above) by specifying the signal ID.