简体   繁体   中英

Communicate between service and activity

I have a class in a service

MyClass m = new MyClass();

and inside my class I check if I have permission to overlay the view; if so, it's ok, otherwise I must start an activity

if (Settings.canDrawOverlays(mContext)) {
    // draw over app
} else {
    // start the activity
    Intent i  = new Intent(context,Calls.class);
    context.startActivity(i);
}

When I start the activity I have a problem communicating between the class and the activity. I know how to use the interface but how can I register it in activity.

Some time I want to pass an object or data from the class to the activity or from the activity to the class... how can I do that?

I saw many examples in Stack Overflow about how to communicate between service and activity; they suggest to start the class from the activity but this does not work in my app because my class must be running all the time.

Perhaps you could use an event bus like mechanism where you can send or receive events through out your app, Though there are several libraries out there, I would recommend using Otto library for android.

Usage is pretty simple just register in your activity onCreate

Bus bus = new Bus();
bus.register(this);

For sending events

// example data to post
public class TestData {
    public String message;
}

// post this data
bus.post(new TestData().message="Hello from the activity");

And subscribe to events like this

@Subscribe public void getMessage(TestData data)  {
    // TODO: React to the event somehow!
}

More info here

If you want to implement a communication pattern between a Service and an Activity , you should use a LocalBroadcastManager .

It will turn handy because, in case your Service is still on but your Activity has been destroyed (very common situation), then the 'messagging' between the two will simply have no effect (no NPE or whatsoever will be thrown).

Step 1

Create a BroadcastReceiver in your Activity and define an ID / Filter

this.localBroadcastReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        // Do what you have to do here if you receive data from the Service / Background Task
    }
}

public static final IntentFilter SIGNAL_FILTER = new IntentFilter("com.you.yourapp.MY_SIGNAL")

Step 2

In your Activity register the broadcast in onResume() and unregister it in onPause() .

@Override
protected void onResume() {
    // Listen if a Service send me some data
    LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(this.localBroadcastReceiver, SIGNAL_FILTER);
}

@Override
protected void onPause() {
    // I'm going to the background / or being destroyed: no need to listen to anything anymore...
    LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(this.localBroadcastReceiver);
}

Your Activity is now ready to receive data from any other component in your Application .

If it's in the background, then there is no need to update the UI : in fact the Activity will not respond if in the background.

In the same way, if it's being garbage collected, the Receiver will be unregistered and the Activity will just not respond to anything.

If the Activity is resumed / restarted, onResume() will be triggered and the Receiver will be registered again.

Step 3

All you need to do right now, is send data from the Service .

Simply call

final Intent intent = new Intent();
intent.setAction(SomeActivity.SIGNAL_FILTER);
// put your data in intent
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);

and your Activity will accordingly respond to the signal.


It's surprising how few people know about the LocalBroadcastManager and instead use some self-implemented callback / singleton pattern, which increases complexity and non-readability.

This pattern is built-in in Android , so you don't need external libraries. As for security, this ensures that your signals stay internal to your application: no data can therefore be read by other apps.

I similarly answered to another question here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM