Free Android app covering all aspects of addiction, including prevention and treatment

Binding to a Service: A Tutorial

  • Written by  101_apps

Bound Services. A way to interact with the Service

andoid bound services tutorial icon

Our tutorial app uses a Service to play a sound clip.

We start a Service when the app starts. The Service will run as long as the app is alive.

We need to bind to the Service to start and stop playing a sound clip. We can leave the clip playing in the Service while it is running. It will continue to play even if the activity is paused or destroyed.

Service notification

A notification displays while the Service runs. It's only cancelled when the Service is destroyed

Clicking the notification starts the activity and displays the control buttons.

Bound Service Tutorial screenshot

The app has one activity. It displays the control buttons

Clicking the buttons calls on the two methods in the service to start and stop playing the sound clip.

Bound Service Tutorial diagram

The Service starts when the app starts. The activity binds to the Service in onStart and unbinds in onStop. When the activity is destroyed, it unbinds from the Service but the Service continues to run until we stop it

Here’s looking at the main activity

If you want some background information on bound Services, have alook at, Bound Services: What you should know!

Starting the app, starts the MainActivity activity.

It displays two buttons:

  • Start Play – starts playing the sound clip
  • Stop Play – stops playing the sound clip

Getting off the ground: onCreate

The activity’s onCreate method is only called once when the activity is being created for the first time. It is an ideal place to start the Service.

Here’s the code for starting the Service:

Bound Service startService

We start the Service in the activity’s onCreate() method

Note the following:

  • intent – we use an intent to specify which Service to start. It has two parameters:
    • the context
    • the Service that we want to start
  • startService – this starts the Service specified in the intent if it is not running. It continues to run if it is already running
  • sendNotification – we send an ongoing notification so that the user is aware that a Service is running. The notification is only cancelled when the Service is killed

Here a button there a button: The buttons

There are two buttons. They will only work when the activity is bound to the Service. Here’s the code for the Start Play button:

Bound Service startButton

Pressing the Start Play button accesses the Service’s startPlay() method to start playing the sound clip

Note the following:

  • startButton – our button object
  • findViewById – we get the button view identified in the layout file by its id
  • setOnClickListener – we set a listener to listen for when the button is clicked
  • onClick – the code contained in this method is executed when the button is clicked
  • isBound – a boolean set to true when the activity binds to the Service and false when it unbinds
  • serviceReference – this is an instance of our Service that we are binding to. It enables us to access the public methods in the Service, the start and stop play methods
  • startPlay – a public method in the Service that starts playing the sound clip

The code for the Stop Play button is the same, except for calling the stopPlay() method to stop playing the sound clip.

The great communicator: The interface

We need an interface if we want to bind to the Service. We pass it as a parameter when we call bindService().

Once we have bound to the Service, the interface gives us a Service object that we can use to access the public methods in the Service.

Here’s the code for the interface:

Bound Service interface

We need a ServiceConnection object to be able to bind to the Service. Once bound, onServiceConnected returns an IBinder interface for communicating with the Service

Note the following:

  • myConnection – our interface object that monitors the connection with the Service
  • onServiceConnected – this gives us our interface once we have connected to the Service
  • serviceReference – the Service object that we can use to access the public methods in the Service
  • isBound – we set it to true as we are now connected to the Service
  • onServiceDisconnected – this is called when the connection is unexpectedly broken because the Service’s process has crashed. Only significant if the Service is running in a separate process (ours is running in the same process as our activity)

Hello and goodbye: Binding and unbinding

Our Service is a started Service. It runs until we stop it. We play the sound in this Service using a media player. We must be bound to the Service to access the media player.

We use these two methods to bind to and unbind from the Service:

Bound Service bind and unbind

We use these methods for binding to and unbinding from the Service. Binding to the Service gives us access to the Service’s public methods

Note the following:

  • unbindService – disconnects from the Service. The Service is now allowed to die. We pass the connection interface as the parameter
  • bindIntent – the intent that specifies the Service that we want to bind to. It receives two parameters:
    • the context
    • the Service that we want to bind to
  • bindService – this connects us to the Service if it’s running. It starts the Service if it’s not. It returns true if the binding was successful and false if not. It receives three parameters:
    • the intent specifying which Service to bind to
    • our interface object that monitors the connection with the Service
    • the options flag for how we should bind. We use BIND_AUTO_CREATE which indicates that we want to bind to an existing Service or create one if none exists

Stops and starts: onStart and onStop

We only want to interact with the Service while our activity is visible, so we bind to the Service in onStart and unbind in onStop.

Here’s the code:

Bound Service activity onStart onStop

It’s good practice to unbind from a Service when you are not interacting with it

Note the following:

  • onStart – called after onCreate and after onRestart. The activity is now either showing for the first time or restarting from the stopped state
  • doBindToService – we bind to the Service. We can now interact with the Service
  • onStop – the activity is no longer visible
  • doUnBindService – we unbind from the Service as there is no point in remaining bound to it if the activity is not visible

Pause for thought: Override the Back press button

By default, if you press the Back button it finishes the activity. onDestroy is called and the Service is killed. This is not what we want.

We want the activity to pause so we override the onBackPressed method. Here’s the code:

Bound Service onBackPressed

Override onBackPressed to pause the activity

Note the following:

  • moveTaskToBack – this moves the activity to the back of the stack, effectively pausing it

Day of execution: onDestroy

onDestroy is called when the device changes orientation and when the activity finishes.

We don’t want to do anything if the activity is destroyed when the device’s orientation changes. However, we want to stop the Service if the activity is being destroyed for good.

Here’s the code:

Bound Service onDestroy

onDestroy is where you can release resources for use elsewhere. We stop the Service here if the activity is being destroyed for good. Nothing happens if it’s destroyed during an orientation change

Note the following:

  • isFinishing – returns true if the activity is finishing. It’s not called when the activity is destroyed because of an orientation change. It is called when we dismiss the activity. We want to stop the Service when the activity is destroyed and won’t be brought back to life
  • intentStopService – our intent that we’ll use to stop the Service. It has two parameters:
    • the context
    • the Service that we want to stop
  • stopService – stops the Service identified by the intent passed as a parameter. If there are still bound connections (that used BIND_AUTO_CREATE when binding) then the Service will not stop until these have been unbound
  • returns true if the identified Service has been stopped else false

Given notice: The notification

We send an ongoing notification when the Service starts. This lets the user know that the Service is running. The notification is cancelled when the Service stops.

Here’s the code:

Bound Service notification

Build the notification that we send when the Service is started

Note the following:

Have a look at You can master notifications. It’s easy! Part 1: Some stuff you should know and You can master notifications. It’s easy! Part 2: Tutorials for more on notifications.

  • we use the compatibility library class to build the notification so that we can support Android 1.6 and up
  • setOngoing – we want the notification to be ongoing so that the user is aware that the Service is running. It is only cancelled when the Service is killed
  • startIntent – our intent specifies the main activity as the activity that we want to start when the notification is clicked

The one that serves: The Service

We’re creating a started Service which runs indefinitely. We also create a separate thread in the Service in which we play a sound clip. We have to stop the Service when we’re finished with it.

We bind to the Service to stop and start playing the sound clip.

We’re running the Service in the same process as our app so we can implement our own Binder class. Our Binder class returns an instance of our Service. We can then use this in our activity to access to the public methods in our Service.

For more on Services, you may want to have a look at these articles and tutorials:

Remember to register the Service in the app’s AndroidManifest.xml file.

In the beginning: onCreate

onCreate is called when the Service is being created.

Bound Service onCreate

Create and start the background thread in onCreate. It’s good practice to free the main thread by using a separate thread to do the heavy work

Note the following:

  • backgroundThread – we create a thread that will do the work in the background, off the main thread
  • playMusic – uses a MediaPlayer to play a sound clip (the sound clip loops so it plays continuously)
  • start – starts the thread (which sets up the media player but does not start playing the sound clip)

For more on threads, you may be interested in this tutorial, Using Threads Tutorial.

We’ve started, now what? onStartCommand

Bound Service onStartCommand

The onStartCommand is called when we call startService in our activity

Note the following:

  • onStartCommand is only called when we call startService in the activity. Its parameters are:
    • intent – the intent passed in the startService call
    • flags –indicates how the Service was started
    • startId – a unique id representing this start request
  • START_STICKY – ensures that onStartCommand is called if the Service needs to restart after being killed by the system
  • onStartCommand would not be called if we were only using a bound Service

Making the connection: onBind

The activity requests to bind to the Service by calling bindService, passing a ServiceConnection and an intent as parameters. The system then calls onBind, passing it the intent. onBind returns the IBinder interface.

Here’s the code:

Bound Service onBind

When we request to bind to the Service, onBind returns an IBinder interface which the activity can use to communicate with the Service

Note the following:

  • returns an instance of an IBinder, an interface that enables the activity to communicate with the Service. This same IBinder is given to all clients that bind to the Service. We would return null if we were not wanting to bind to the Service

Make it your own: Extending the Binder class

Our Service is in the same process as the client so we use the IBinder interface. We get it by extending the Binder class. Our activity receives the Binder which enables it to access the public methods in the Service.

This is the preferred technique if the Service is just a background worker for the app.

Bound Service Binder

We get an instance of our Service by extending the Binder class. We can use this in the activity to access the Service’s public methods

Note the following:

  • MyLocalBinder extends the Binder class and returns an instance of our Service, BoundService

Out in the public: The public methods

There are two public methods that we include in our Service. We can access them from our activity via the IBinder interface.

Here are the methods:

Bound Service public methods

The Service’s public methods which we can access from the activity by using the Binder interface

Note the following:

  • startPlay – we call this from the activity to start playing the sound clip
  • stopPlay – we call this from our activity to stop (actually pause) the player

The Terminator: onDestroy

onDestroy is called when the Service is no longer used and is about to be destroyed. This is where we release the resources used by the media player and stop the thread.

Bound Service onDestroy

The Service is no longer used and is about to be destroyed. Stop the thread and release the resources used by the media player

Note the following:

  • release – we release any resources used by the media player
  • interrupt – we interrupt the thread to stop it
  • we get an instance of the notification manager and then cancel the notification

I hope that you have found this tutorial helpful.

This tutorial was created using Android Studio. You can download the project files here Download icon

Are you using Eclipse or another IDE? Here's how you can use this project's Android Studio files.