I\'m writing my first Android application and trying to get my head around communication between services and activities. I have a Service that will run in the background an
Create a callback
public interface MyCallBack{
public void getResult(String result);
}
Activity side:
Implement the interface in the Activity
Provide the implementation for the method
Bind the Activity to Service
Register and Unregister Callback when the Service gets bound and unbound with Activity.
public class YourActivity extends AppCompatActivity implements MyCallBack{
private Intent notifyMeIntent;
private GPSService gpsService;
private boolean bound = false;
@Override
public void onCreate(Bundle sis){
// activity code ...
startGPSService();
}
@Override
public void getResult(String result){
// show in textView textView.setText(result);
}
@Override
protected void onStart()
{
super.onStart();
bindService();
}
@Override
protected void onStop() {
super.onStop();
unbindService();
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
GPSService.GPSBinder binder = (GPSService.GPSBinder) service;
gpsService= binder.getService();
bound = true;
gpsService.registerCallBack(YourActivity.this); // register
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
bound = false;
}
};
private void bindService() {
bindService(notifyMeIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
private void unbindService(){
if (bound) {
gpsService.registerCallBack(null); // unregister
unbindService(serviceConnection);
bound = false;
}
}
// Call this method somewhere to start Your GPSService
private void startGPSService(){
notifyMeIntent = new Intent(this, GPSService.class);
startService(myIntent );
}
}
Service Side:
Initialize callback
Invoke the callback method whenever needed
public class GPSService extends Service{
private MyCallBack myCallback;
private IBinder serviceBinder = new GPSBinder();
public void registerCallBack(MyCallBack myCallback){
this.myCallback= myCallback;
}
public class GPSBinder extends Binder{
public GPSService getService(){
return GPSService.this;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent){
return serviceBinder;
}
}
There are three obvious ways to communicate with services:
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.
The other method that's not mentioned in the other comments is to bind to the service from the activity using bindService() and get an instance of the service in the ServiceConnection callback. As described here http://developer.android.com/guide/components/bound-services.html
As mentioned by Madhur, you can use a bus for communication.
In case of using a Bus you have some options:
Otto event Bus library (deprecated in favor of RxJava)
http://square.github.io/otto/
Green Robot’s EventBus
http://greenrobot.org/eventbus/
NYBus (RxBus, implemented using RxJava. very similar to the EventBus)
https://github.com/MindorksOpenSource/NYBus
I am surprised that no one has given reference to Otto event Bus library
http://square.github.io/otto/
I have been using this in my android apps and it works seamlessly.
To follow up on @MrSnowflake answer with a code example.
This is the XABBER now open source Application class. The Application
class is centralising and coordinating Listeners
and ManagerInterfaces and more. Managers of all sorts are dynamically loaded. Activity´s
started in the Xabber will report in what type of Listener
they are. And when a Service
start it report in to the Application
class as started. Now to send a message to an Activity
all you have to do is make your Activity
become a listener
of what type you need. In the OnStart()
OnPause()
register/unreg. The Service
can ask the Application
class for just that listener
it need to speak to and if it's there then the Activity is ready to receive.
Going through the Application
class you'll see there's a loot more going on then this.