In my previous tutorials I have been talking about Services in Android, showcasing basic functions of a service. This tutorial also shows Android service class, but it revolves around a specific feature of this class i.e binding of service to an activity. It also briefly explains the features associated with Android bind service type. Although if you are not clear on what android bind services are, here’s a brief explanation. A bound service is a type of service which can bind with one or more application components like activities and return the results back to them.
As I explained in my previous tutorials that in Android services are used for long running operations, presumably never ending operations. Here in this Bound Service Example In Android tutorial I would also show a never ending service. But talking about services here, I would like to say that service is an Android component which should be used only when you don’t have a requirement to display something on user interface. Most of the times, services are used for long running network operations. If you want to explore more on services have a look at some of my tutorials listed below:
While working with Android services, there comes a situation where we would want the service to communicate with an activity. To accomplish this task one has to bind a service to an activity, this type of service is called an android bound service. After a service is bound to an activity one can return the results back to the calling activity. Here in this tutorial I would start a timer service which would keep counting a timer from the start of service. Then I will bind this service to the same activity, which would make this a bound service. Why I started a service and then bind it? will answer this later in the tutorial. For now lets start with some code:
In the above piece of code you can see that I have defined the service and an activity in the manifest. Moving on lets define the service which will be bound to an activity.
package com.truiton.boundservice; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.os.SystemClock; import android.util.Log; import android.widget.Chronometer; public class BoundService extends Service < private static String LOG_TAG = "BoundService"; private IBinder mBinder = new MyBinder(); private Chronometer mChronometer; @Override public void onCreate() < super.onCreate(); Log.v(LOG_TAG, "in onCreate"); mChronometer = new Chronometer(this); mChronometer.setBase(SystemClock.elapsedRealtime()); mChronometer.start(); >@Override public IBinder onBind(Intent intent) < Log.v(LOG_TAG, "in onBind"); return mBinder; >@Override public void onRebind(Intent intent) < Log.v(LOG_TAG, "in onRebind"); super.onRebind(intent); >@Override public boolean onUnbind(Intent intent) < Log.v(LOG_TAG, "in onUnbind"); return true; >@Override public void onDestroy() < super.onDestroy(); Log.v(LOG_TAG, "in onDestroy"); mChronometer.stop(); >public String getTimestamp() < long elapsedMillis = SystemClock.elapsedRealtime() - mChronometer.getBase(); int hours = (int) (elapsedMillis / 3600000); int minutes = (int) (elapsedMillis - hours * 3600000) / 60000; int seconds = (int) (elapsedMillis - hours * 3600000 - minutes * 60000) / 1000; int millis = (int) (elapsedMillis - hours * 3600000 - minutes * 60000 - seconds * 1000); return hours + ":" + minutes + ":" + seconds + ":" + millis; >public class MyBinder extends Binder < BoundService getService() < return BoundService.this; >> >
Ok the above BoundService class is the main service class which will bound to an activity. Now since this is a bound service tutorial, in the above class I have tried to create a never ending timer service, as it should be in a real world scenario. If you closely observe the above stated code, you would see that this timer service runs a Chronometer, and returns time-stamp through a public method. Since this method is a public method of BoundService class it may be accessed only through an object of this class. In-comes the Android Bind Service concepts.
To do this I have created a MyBinder class which inherits Binder class which in-turn implements IBinder interface. This class has a method which returns the object of this BoundService class. Though this object any android application component would be able to access public methods of this class.
Now before defining the class which will bind this Android service, lets make a layout for activity:
Next have a look at the MainActivity which will bind the BoundService class:
package com.truiton.boundservice; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import com.truiton.boundservice.BoundService.MyBinder; public class MainActivity extends AppCompatActivity < BoundService mBoundService; boolean mServiceBound = false; @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final TextView timestampText = (TextView) findViewById(R.id.timestamp_text); Button printTimestampButton = (Button) findViewById(R.id.print_timestamp); Button stopServiceButon = (Button) findViewById(R.id.stop_service); printTimestampButton.setOnClickListener(new OnClickListener() < @Override public void onClick(View v) < if (mServiceBound) < timestampText.setText(mBoundService.getTimestamp()); >> >); stopServiceButon.setOnClickListener(new OnClickListener() < @Override public void onClick(View v) < if (mServiceBound) < unbindService(mServiceConnection); mServiceBound = false; >Intent intent = new Intent(MainActivity.this, BoundService.class); stopService(intent); > >); > @Override protected void onStart() < super.onStart(); Intent intent = new Intent(this, BoundService.class); startService(intent); bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); >@Override protected void onStop() < super.onStop(); if (mServiceBound) < unbindService(mServiceConnection); mServiceBound = false; >> private ServiceConnection mServiceConnection = new ServiceConnection() < @Override public void onServiceDisconnected(ComponentName name) < mServiceBound = false; >@Override public void onServiceConnected(ComponentName name, IBinder service) < MyBinder myBinder = (MyBinder) service; mBoundService = myBinder.getService(); mServiceBound = true; >>; >
All of this should give an output like this :
Above MainActivity class is the class which starts the BoundService class and then later on binds to it. Whenever a service is started or bound, first onCreate() method is called, then the onStartCommand() or onBind() method is called according to the situation. But here in this Bound Service Example In Android tutorial first the onStartCommand() method is called then the onBind() method is called. Although if you closely observe I have not implemented the onStartCommand() method, hence its default implementation will be called.
I left off a point above referring to, why I started a service and then created a binding for it. The answer lies in the official documentation that if we bind a service without starting it, the bound service would exist only while the binding application component is active. In other words if a service is not started, only bound to an activity then it will exist till the activity exists. In most cases and in this case too we need a service to remain active even when the activity is not present, hence the service is started first then its bound to an activity. Same is stated in the documentation for Context.BIND_AUTO_CREATE the flag used for binding the service.
Coming back to our MainActivity , here you can see that ServiceConnection class is used to establish or bind a connection to the service, through which an object of class is returned. Now whenever an operation on service is to be performed this object reference is used. Like in this Bound Service Example In Android tutorial mBoundService.getTimestamp() method is used to get the time-stamp from the service.
Okay this method in the Android bound service implementation is sort of special, as it can control the life-cycle of a service. This method may seem harmless but can do a great amount of damage to your code if not used properly. In regular flow this method is called when the bound application component like an activity unbinds the service by calling unbindService() method.
Android Service onUnbind method can alter the flow for Android bound service on the basis of its return value, it can either be true or false .
Although if you were reading this Bound Service Example In Android thoroughly you might have got this point till now. That service’s onBind method would be called only once in both the cases of onUnbind method. So choose wisely according to specs. To view full source code, please have at the link below:
Another important thing that I observed while exploring was that, if a service is bound to an application component, it cannot be stopped until unbind is called from that component. If a service has multiple bindings then all the bindings have to be removed, only then your service may stop. Hope this helped.
Born in New Delhi, India. A software engineer by profession, an android enthusiast and an evangelist. My motive here is to create a group of skilled developers, who can develop something new and good. Reason being programming is my passion, and also it feels good to make a device do something you want. In a very short span of time professionally I have worked with many tech firms. As of now too, I am employed as a senior engineer in a leading tech company. In total I may have worked on more than 20 projects professionally, and whenever I get spare time I share my thoughts here at Truiton.