How to send and get data between Service and Broad

2019-09-08 09:03发布

问题:

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?

回答1:

You can't really do this the way you've described. @CommonsWare is correct, your chosen architecture is flawed.

BroadcastReceivers 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.



回答2:

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();
}