Notify Activity from Service

android service notify activity completed best way?

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

Notify activity from service

As Alex indicated, you can bind to the service and pass some sort of listener or callback to the service to use on events.

Or, you can use a broadcast Intent, perhaps using methods like setPackage() on the Intent to limit the scope of the broadcast.

Or, you can use createPendingResult() to create a PendingIntent that you pass as an Intent extra to the service -- the service can then use that PendingIntent to trigger onActivityResult() in your activity.

Or, you can use a ResultReceiver.

Or, you can use a Messenger.

(admittedly, I have not tried those latter two approaches, but I think they will work here)

How to display a notification from service when activity gets destroyed

Basically you should reconsider the time when your notification is shown. Since the onDestroy method of an activity may not be always called, I would prefer to use another point when to display your notification. You should be also aware of the new restrictions regarding background services since android 8 (API 26), if you do not explicitly mark them as a foreground service, then they might be killed by the OS while the app is in the background.

So, for your purpose it might be an option to use the method startForeground with a notification id and call it when your activity is going to the background (e.g. at onStop), then it will display the notification (which is the requirement for keeping the service in the foreground). If you decide to go back to your activity after some time, you may call stopForeground to stop the foreground mode and dismiss your notification.

How do i notify the activity on service completion?

First Create the Interface like MyLocationListener as following

public interface MyLocationListener {
public void locationChanged(double lat, double lon);
}

Now Update the GPS class as

public class GPS {
ArrayList<MyLocationListener> listeners = new ArrayList<MyLocationListener>();

public void addLocationListener(MyLocationListener listener) {
listeners.add(listener);
}
}

So Where you have changed the latitude or longitude just call the

notifyChangeLocation(lat, lon);

and this method has following code:

public void notifyChangeLocation(double lat, double lon) {
Iterator<MyLocationListener> itr = listeners.iterator();
while(itr.hasNext()) {
itr.next().locationChanged(lat, lon);
}
}

This is the first part, now the second thing is to add the listener in your activity, by Making an class MyServiceConnection which is like:

public class MyServiceConnection implements ServiceConnection, MyLocationListener {
//add the unimplemented methods
public void locationChanged(double lat, double lon) {
// do any extra setup that requires your Service
}
}
ServiceConnection mConnection = new MyServiceConnection();
Intent i=new Intent(getApplicationContext(), GPS.class);
bindService(i,mConnection,Context.BIND_AUTO_CREATE);

Now just register the listener
gps.addLocationListener(mConnection);

Sending data from activity to service UPDATED

To get the number of items, you need to establish a communication between the Activity and Service. For this, you need to implement the Messenger.

Messenger allows for the implementation of message-based communication across processes by help of Handlers.

Handler is a that allows you to send and process these messages.

Steps for implementing a Messenger:

  1. Service implements a Handler which receives the callbacks from the Activity

  2. The Handler then creates a Messenger object which further on creates an IBinder that the Service returns to the Activity.

  3. Activity then uses the IBinder to instantiate the Messenger, which the Activity uses to send messages to the Service.

  4. The Service receives the messages in the Handler created in the 1st step.

Lets now understand it with an example:

Create a Handler in the Service like this:

class ServiceHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
default:
super.handleMessage(msg);
}
}
}

Now, add the Messenger object along with onBind() method to the Service as mentioned in 2nd step above:

final Messenger messenger = new Messenger(new ServiceHandler());

@Override
public IBinder onBind(Intent intent) {
return messenger.getBinder();
}

In the Activity, we will create a ServiceConnection to fetch the iBinder from the Service to instantiate the Messenger object as mentioned in the 3rd step above.

Messenger messenger;
private ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder iBinder) {
messenger = new Messenger(iBinder);
}

public void onServiceDisconnected(ComponentName className) {
}
};

Bind the Service to the Activity by help of the ServiceConnection created above:

bindService(new Intent(this, MessengerService.class), serviceConnection,
Context.BIND_AUTO_CREATE);

To send messages to the Service from the Activity, use the send() method of the Messenger object.

If you want to receive messages from the Service in the Activity, you need to create a Messenger in the Activity along with a Handler and use the replyTo parameter of the Messenger to receive messages to the respective Handler.

Updated Answer:

To send Message via Messenger do this:

  1. Create a Bundle object.

  2. Put data into the Bundle Object.

  3. Add the bundle object to the Message object.

  4. Send Message object to Service by help of Messenger object.

Example:

Bundle bundle = new Bundle();
bundle.putFloat("key", 1.0f);
Message message = Message.obtain();
message.setData(bundle);
messenger.send(message);

For more info, visit the following link:

http://developer.android.com/guide/components/bound-services.html

How to call an activity from service with Notification Bar

I have solved, this open my application preserving the actual state and get the opened activity back form background to foregraund. Do the same think of app selecting from RECENTS !

Intent i = new Intent();
i.setAction(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
i.setComponent(new ComponentName(getApplicationContext().getPackageName(), MyAppClass.class.getName()));

MyAppClass is the 1st Activity your APK is launching.

Best regards

How to have Android Service communicate with Activity

There are three obvious ways to communicate with services:

  1. Using Intents
  2. Using AIDL
  3. Using the service object itself (as singleton)

In your case, I'd go with option 3. Make a static reference to the service it self and populate it in onCreate():

void onCreate(Intent i) {
sInstance = this;
}

Make a static function MyService getInstance(), which returns the static sInstance.

Then in Activity.onCreate() you start the service, asynchronously wait until the service is actually started (you could have your service notify your app it's ready by sending an intent to the activity.) and get its instance. When you have the instance, register your service listener object to you service and you are set. NOTE: when editing Views inside the Activity you should modify them in the UI thread, the service will probably run its own Thread, so you need to call Activity.runOnUiThread().

The last thing you need to do is to remove the reference to you listener object in Activity.onPause(), otherwise an instance of your activity context will leak, not good.

NOTE: This method is only useful when your application/Activity/task is the only process that will access your service. If this is not the case you have to use option 1. or 2.



Related Topics



Leave a reply



Submit