In my previous question: How to keep and access data in BroadcastReceiver? I've got excellent answers, but here I focus on this.
There is BroadcastReceiver and there is Service. I would like to send some data from the receiver to service and get the data back. The party which initiates the transfer is receiver, not the service.
For the sake of the simplicity, let's say that receiver waits for SCREEN_ON and then asks service "is this a birthday of the user", and server returns true or false.
If I am not mistaken I should attach my data that goes to Service to the Intent, and call startService
, but how to get data back?
You can't really do this the way you've described. @CommonsWare is correct, your chosen architecture is flawed.
BroadcastReceiver
s are short-lived. Therefore they cannot make any asynchronous calls and they cannot perform any tasks that take a "significant amount of time". Your BroadcastReceiver
gets triggered by a certain event and if you need to do any significant amount of work due to that event you will need to delegate that work to a Service
.
Normally (for example: within an Activity
), if you wanted to request information from a Service
you could either bind to the Service
and make a synchronous call to the service to request the data you want OR you could call the service asynchronously (ie: send an Intent
to it) and then listen for the returned result (using a BroadcastReceiver
). Neither of these methods works from a BroadcastReceiver
because a BroadcastReceiver
cannot bind to a Service
and it cannot make asynchronous calls.
EDIT: Copied relevant information from the Android documentation for reference here
Receiver Lifecycle
A BroadcastReceiver
object is only valid for the duration of the call
to onReceive(Context, Intent)
. Once your code returns from this
function, the system considers the object to be finished and no longer
active.
This has important repercussions to what you can do in an
onReceive(Context, Intent)
implementation: anything that requires
asynchronous operation is not available, because you will need to
return from the function to handle the asynchronous operation, but at
that point the BroadcastReceiver
is no longer active and thus the
system is free to kill its process before the asynchronous operation
completes.
In particular, you may not show a dialog or bind to a service from
within a BroadcastReceiver
. For the former, you should instead use the
NotificationManager
API. For the latter, you can use
Context.startService()
to send a command to the service.
Use a session!
Save the data in a session:
@Override
public void onReceive(Context context, Intent intent)
{
SessionManager session = new SessionManager(context);
// get user data from session
HashMap<String, Object> user = session.getUserDetails();
// name
m_userId = (int)user.get(SessionManager.KEY_ID);
m_context = context;
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "");
wl.acquire();
// Put here YOUR code.
//Toast.makeText(context, "Alarm !!!!!!!!!!", Toast.LENGTH_LONG).show(); // For example
wl.release();
}