In this class, we'll be learning about:
Source code available on Github.
Service
is an application component that runs in the background without needing to interact with the user. Activity
) can start a service and it will continue to run in the background even if the user switches to another application. A service can have two forms-
State | Service callback | Description |
---|---|---|
Started | onStartCommand() | A service is “started” when an application component (such as an activity) starts it by calling startService() . Once started, a service can run in the background indefinitely, even if the component that started it is destroyed. |
Bound | onBind() | A service is “bound” when an application component binds to it by calling bindService() . A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC). |
To create a service, you must create a subclass of Service (or one of its existing subclasses). The most important callback methods you should override are:
Lifecycle Callback | Description |
---|---|
onCreate() | The system calls this method when the service is first created, to perform one-time setup procedures (before it calls either onStartCommand() or onBind() ). If the service is already running, this method is not called. |
onStartCommand() | The system calls this method when another component, such as an activity, requests that the service be started, by calling startService(). If you implement this, it is your responsibility to stop the service when its work is done, by calling stopSelf() or stopService(). |
onBind() | The system calls this method when another component wants to bind with the service (such as to perform RPC), by calling bindService(). |
onDestroy() | The system calls this method when the service is no longer used and is being destroyed. |
Quick look into what we're going to build next.
We'll build an application similar to other Music Players which we can use to play music even when our application is in background or we have exited from our app. We'll use Service
and Notification
for this purpose.
Let's begin with creating an Android Application Project (with Minimum API Level = 16). I've named it PlayMusic.
Now, we have to create a service which will play this audio file even if our application goes into background. So, as mentioned before, we'll need implement lifecycle methods - (1) onCreate()
, (2) onStartCommand()
, (3) onDestroy()
. And, yes, we'll be binding the service in our app, so we'll implement onBind()
as well.
Service
. I named it PlayMusicService.public class PlayMusicService extends Service { // An interface object used by clients to communicate with the service. private final IBinder mBinder = new MyBinder(); @Override public void onCreate() { Toast.makeText(this, "Service Created", Toast.LENGTH_SHORT).show(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show(); return Service.START_STICKY; // Service will be explicitly started and stopped as needed. } @Override public IBinder onBind(Intent i) { Toast.makeText(this, "Binding Service", Toast.LENGTH_SHORT).show(); return mBinder; } public class MyBinder extends Binder { PlayMusicService getService() { return PlayMusicService.this; } } public void onDestroy() { Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show(); } }
Activity
, we also have to register any Service
used in the app in AndroidManifest.xml of the project. Add <service>
as the sibling of <activity>
tag (i.e. as a child of <application>
tag).<application> <!-- Existing activities --> <activity>....</activity> <!-- Add your service as in the line below --> <service android:name="com.example.playmusic.PlayMusicService" /> </application>
ServiceConnection
object in the MainActivity
class. ServiceConnection
is an interface for monitoring the state of an application service. The methods of this class are called from the main thread of application's process.private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder binder) { Toast.makeText(MainActivity.this, "Connected to the service", Toast.LENGTH_SHORT) .show(); } public void onServiceDisconnected(ComponentName className) { Toast.makeText(MainActivity.this, "Disconnected from the service", Toast.LENGTH_SHORT) .show(); } };
private boolean mIsBound = false; public void onButtonClick(View v) { switch (v.getId()) { case R.id.button_start: doBindService(); startService(new Intent(MainActivity.this, PlayMusicService.class)); break; case R.id.button_stop: doUnbindService(); stopService(new Intent(MainActivity.this, PlayMusicService.class)); break; default: } } void doUnbindService() { if (mIsBound) { unbindService(mConnection); mIsBound = false; Toast.makeText(this, "Unbinding Service", Toast.LENGTH_SHORT).show(); } } void doBindService() { mIsBound = true; bindService(new Intent(this, PlayMusicService.class), mConnection, Context.BIND_AUTO_CREATE); }
Our intention is to play a music file on press of 'Start' button, and stop it on press of 'Stop' button.
raw
inside res
folder. And, copy the downloaded audio file to res/raw
folder.MediaPlayer
object./* Create a MediaPlayer object as the member variable of PlayMusicService class */ MediaPlayer mPlayer; /* ----------- Add this in onCreate() method -----------------------*/ mPlayer = MediaPlayer.create(this, R.raw.song); // Set the Player to play the downloaded audio file mPlayer.setLooping(false); // Disable auto-repeat /* ----------- Add this in onStartCommand() method -----------------------*/ mPlayer.start(); // Start playing music /* ----------- Add this in onDestroy() method -----------------------*/ mPlayer.stop(); // Stop playing music
Notifications
are persistent messages at the top of the device, commonly known as the 'Status bar' (sometimes also referred to as the 'Notification bar').
Notifications collapsed appear something like below:
And, when expanded, they look something like:
Notification
, we can use Notification.Builder
. And, we have to use NotificationManager
to display a notification. The code snippet below shows how to create a notification. You can add this method to PlayMusicService
class.private NotificationManager mNotificationMgr; private void createNotification() { // Prepare intent which is triggered if the notification is clicked. Intent intent = new Intent(this, MainActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0 /* requestCode */, intent, Notification.FLAG_ONGOING_EVENT); // Build notification Notification notification = new Notification.Builder(this) .setContentTitle("PlayMusicService") .setContentText("Tap to go to application & stop the service.") .setSmallIcon(R.drawable.ic_launcher) .setContentIntent(contentIntent) .setAutoCancel(true) .build(); notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT; // Display the notification mNotificationMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); mNotificationMgr.notify(R.string.hello_world, notification); }
onStartCommand()
should look something like below in the end:@Override public int onStartCommand(Intent intent, int flags, int startId) { // Display notification in the notification bar createNotification(); // Start playing music mPlayer.start(); Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show(); return Service.START_STICKY; // Service will be explicitly started and stopped as needed. }
NotificationManager
. Hence, onDestroy()
of PlayMusicService
should end up with something similar like below:public void onDestroy() { // Remove notification from the Notification bar. mNotificationMgr.cancel(R.string.hello_world); // Stop playing music mPlayer.stop(); Toast.makeText(this, "Service Destroyed", Toast.LENGTH_SHORT).show(); }