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
Service
and update theActivity
. How do I check if theActivity
is 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.