Background Service.
Background Service in android is a service which performs an operation that isn't directly noticed by the user.
Examples :
- Downloading a file in background from a server.
- Playing songs in background in a music player app.
- Displaying the status of Connection to the server for a chat messaging app.
Implementation of Background Service.
Build a new Android project .
Open up
activity_main.xml
.Now , we're going to add 2 buttons , which is startService and stopService .
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.codingblocks_projects.stoned_coder.ForegroundServices.MainActivity">
<Button android:id="@+id/btnStartService"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="Start Service" />
<Button android:id="@+id/btnStopService"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="Start Service" />
</LinearLayout>
- create a
customview.xml
in which we're going to create some custom views for our notification panel .
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/notification"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@+id/llPlayControls"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:id="@+id/notification_text_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:singleLine="true"
android:text="Song Title"
android:textColor="#787878"
android:textStyle="bold" />
<TextView
android:id="@+id/notification_text_artist"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:singleLine="true"
android:text="artist"
android:textColor="#787878" />
</LinearLayout>
<LinearLayout
android:id="@+id/llPlayControls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:orientation="horizontal">
<ImageView
android:id="@+id/notification_button_prev"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@android:drawable/ic_media_previous" />
<ImageView
android:id="@+id/notification_button_play"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@android:drawable/ic_media_play" />
<ImageView
android:id="@+id/notification_button_skip"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@android:drawable/ic_media_next" />
<ImageView
android:id="@+id/notification_button_close"
android:layout_width="48dp"
android:layout_height="48dp"
android:src="@android:drawable/ic_menu_close_clear_cancel" />
</LinearLayout>
</RelativeLayout>```
* Now in the ```MainActivity.java``` file inside ``onCreate`` , we'll be geting refrence fo the buttons and defining 2 intents , one for start and the other being stop .
```java
startButton=(Button)findViewById(R.id.btnStartService);
stopButton =(Button)findViewById(R.id.btnStopService);
startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent startIntent = new Intent(MainActivity.this, ForegroundService.class);
startIntent.setAction(Constants.ACTION.STARTFOREGROUND_ACTION);
startService(startIntent);
}
});
stopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent stopIntent = new Intent(MainActivity.this, ForegroundService.class);
stopIntent.setAction(Constants.ACTION.STOPFOREGROUND_ACTION);
startService(stopIntent);
}
});
We'll create a new class and name that as Constants.java
- This class will contain 2 interfaces one for
Actions
and other forServiceID
public class Constants {
public interface ACTION {
public static String MAIN_ACTION = "com.stonedcoder.alertdialog.action.main";
public static String STARTFOREGROUND_ACTION = "com.stonedcoder.alertdialog.action.startforeground";
public static String STOPFOREGROUND_ACTION = "com.stonedcoder.alertdialog.action.stopforeground";
}
public interface NOTIFICATION_ID {
public static int FOREGROUND_SERVICE = 101;
}
}
- Now we'll create another class and name that
ForegroundService
which holds the logic for custom notification views and service .
class ForegroundService extends Service {
private static final String LOG_TAG = "ForegroundService";
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) {
Toast.makeText(this,"Start Service",Toast.LENGTH_SHORT).show();
Log.i(LOG_TAG, "Received Start Foreground Intent ");
Intent notificationIntent = new Intent(this, MainActivity.class);
notificationIntent.setAction(Constants.ACTION.MAIN_ACTION);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
notificationIntent, 0);
RemoteViews notificationView = new RemoteViews(this.getPackageName(),R.layout.customviews);
// And now, building and attaching the Play button.
Intent buttonPlayIntent = new Intent(this, NotificationPlayButtonHandler.class);
buttonPlayIntent.putExtra("action", "togglePause");
PendingIntent buttonPlayPendingIntent = pendingIntent.getBroadcast(this, 0, buttonPlayIntent, 0);
notificationView.setOnClickPendingIntent(R.id.notification_button_play, buttonPlayPendingIntent);
// And now, building and attaching the Skip button.
Intent buttonSkipIntent = new Intent(this, NotificationSkipButtonHandler.class);
buttonSkipIntent.putExtra("action", "skip");
PendingIntent buttonSkipPendingIntent = pendingIntent.getBroadcast(this, 0, buttonSkipIntent, 0);
notificationView.setOnClickPendingIntent(R.id.notification_button_skip, buttonSkipPendingIntent);
// And now, building and attaching the Skip button.
Intent buttonPrevIntent = new Intent(this, NotificationPrevButtonHandler.class);
buttonPrevIntent.putExtra("action", "prev");
PendingIntent buttonPrevPendingIntent = pendingIntent.getBroadcast(this, 0, buttonPrevIntent, 0);
notificationView.setOnClickPendingIntent(R.id.notification_button_prev, buttonPrevPendingIntent);
// And now, building and attaching the Close button.
Intent buttonCloseIntent = new Intent(this, NotificationCloseButtonHandler.class);
buttonCloseIntent.putExtra("action", "close");
PendingIntent buttonClosePendingIntent = pendingIntent.getBroadcast(this, 0, buttonCloseIntent, 0);
notificationView.setOnClickPendingIntent(R.id.notification_button_close, buttonClosePendingIntent);
Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("nkDroid Music Player")
.setTicker("nkDroid Music Player")
.setContentText("nkDroid Music")
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(
Bitmap.createScaledBitmap(icon, 128, 128, false))
.setContent(notificationView)
.setOngoing(true).build();
startForeground(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE,
notification);
}
else if (intent.getAction().equals(Constants.ACTION.STOPFOREGROUND_ACTION)) {
Toast.makeText(this,"Stop Service",Toast.LENGTH_SHORT).show();
Log.i(LOG_TAG, "Received Stop Foreground Intent");
stopForeground(true);
stopSelf();
}
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(LOG_TAG, "In onDestroy");
}
@Override
public IBinder onBind(Intent intent) {
// Used only in case of bound services.
return null;
}
/**
* Called when user clicks the "play/pause" button on the on-going system Notification.
*/
public static class NotificationPlayButtonHandler extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Play Clicked",Toast.LENGTH_SHORT).show();
}
}
/**
* Called when user clicks the "skip" button on the on-going system Notification.
*/
public static class NotificationSkipButtonHandler extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Next Clicked",Toast.LENGTH_SHORT).show();
}
}
/**
* Called when user clicks the "previous" button on the on-going system Notification.
*/
public static class NotificationPrevButtonHandler extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Previous Clicked",Toast.LENGTH_SHORT).show();
}
}
/**
* Called when user clicks the "close" button on the on-going system Notification.
*/
public static class NotificationCloseButtonHandler extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Close Clicked",Toast.LENGTH_SHORT).show();
}
}
}
- Now open up
AndroidManifest.xml
and add recivers and service to the manifest .
<receiver android:name=".ForegroundService$NotificationCloseButtonHandler" />
<receiver android:name=".ForegroundService$NotificationPlayButtonHandler" />
<receiver android:name=".ForegroundService$NotificationPrevButtonHandler" />
<receiver android:name=".ForegroundService$NotificationSkipButtonHandler" />
<service android:name=".ForegroundService" />````