Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android service notify activity completed best way?

I created a service which syncs data from the web on a background thread and want to notify a list activity when the service has completed so it can update it's cursor? What would be the best way to do this? I'm thinking of sending a broadcast when the service is done but not sure if that's the best way to do it. I need to requery the cursor when the service has finished so I'm not sure if that will work well with broadcast receivers? I haven't done alot of android in awhile so thanks in advance.

like image 880
marchinram Avatar asked Jul 06 '11 06:07

marchinram


People also ask

How can a service notify an activity of an event happening?

Use a Handler in your service that registers a client when your ListActivity connects to the service; that is, in your onServiceConnected method in your ListActivity , send a Message to your service that enables you to keep track of connected clients.

How do I notify activity in Android?

Build and issue the notification: Create an Intent that starts the Activity . Set the Activity to start in a new, empty task by calling setFlags() with the flags FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_CLEAR_TASK . Create a PendingIntent by calling getActivity() .

How do you communicate with service and activity?

We already know that we can communicate with Service from activity just by using method startService() and passing Intent to the argument in the method, or either we can use bindService() to bind the service to the activity with argument Intent.

How can I make a service run continuously on Android?

1: You have to invoke the service's startForeground() method within 5 seconds after starting the service. To do this, you can call startForeground() in onCreate() method of service. public class AppService extends Service { .... @Override public void onCreate() { startForeground(9999, Notification()) } .... }


2 Answers

If you're already using the support library, you could just as easily fire a broadcast from the service using the LocalBroadcastManager back to your activity that would listen for the broadcast being sent.

Using LocalBroadcastManager ensures only your own application would ever receive the broadcast so you don't have to worry about leaking private data or opening up potential security holes.

Also see: how to use LocalBroadcastManager?

EDIT (09/2014):

A better way to do this would be to use an event bus framework like Otto (my favourite) or GreenRobot/EventBus to avoid coupling your components too tightly.

like image 143
Jay Sidri Avatar answered Sep 22 '22 00:09

Jay Sidri


Use a Handler in your service that registers a client when your ListActivity connects to the service; that is, in your onServiceConnected method in your ListActivity, send a Message to your service that enables you to keep track of connected clients. Then you can simply loop through these clients in your Service and send them a Message when something takes place in your Service that you want to notify your ListActivity about. For more information you can look at code in an on-going project of mine: my ListActivity and my Service stub.

In short, in your MainActivity, start and bind to your service with:

Intent i = new Intent(this, NetworkService.class);
startService(i);
bindService(i, networkServiceConnection, Context.BIND_AUTO_CREATE);

Define a messenger to respond to messages from the service like:

Messenger messenger = new Messenger(new IncomingHandler());

class IncomingHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case NetworkService.MSG_SOMETHING:
                // do something here
                break;
            default:
                super.handleMessage(msg);
        }
    }
}

And then write your service connection code like:

private ServiceConnection networkServiceConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className, IBinder service) {
        networkService = new Messenger(service);
        try {
            Message msg = Message.obtain(null, NetworkService.MSG_REGISTER_CLIENT);
            msg.replyTo = messenger;
            networkService.send(msg);
            log.debug("Connected to service");

        } catch (RemoteException e) {
            // Here, the service has crashed even before we were able to connect
        }
    }

Note that the replyTo is the messenger we just created.

In your NetworkService, keep track of connected clients with:

ArrayList<Messenger> clients = new ArrayList<Messenger>();

and create your handler like:

class IncomingHandler extends Handler {
       @Override
       public void handleMessage(Message msg) {
           switch (msg.what) {
               case MSG_REGISTER_CLIENT:
                   log.debug("Adding client: " + msg.replyTo);
                   clients.add(msg.replyTo);
                   break;
               default:
                   super.handleMessage(msg);
                   break;
           }
       }
   }

Then, when you want to send a message back to your MainActivity, just do something like the following:

for (int i = 0; i < clients.size(); i++) {
    try {
        clients.get(i).send(Message.obtain(null, MSG_SOMETHING));
    } catch (RemoteException e) {
        // If we get here, the client is dead, and we should remove it from the list
        log.debug("Removing client: " + clients.get(i));
        clients.remove(i);
    }
}
like image 24
zeitkunst Avatar answered Sep 23 '22 00:09

zeitkunst