Android Foreground Service Example Tutorial

Please follow and like us:

android foreground service example tutorial

In Android Foreground Service Example Tutorial we will see a very simple implementation of android foreground service. For long running operations we don’t need user interface hence we can use service for that. But what happen when you need some UI for your long running operations?  The first solution that comes in my mind is Android Foreground Service. This kind of service comes under the category of started service, as its not bound to any component and neither it returns any result back.

Download: Android Foreground Service Example

 

What is Android Foreground Service ?

A Service is an application component that can perform long-running operations in the background and does not provide a user interface.

A Foreground Service in android is a background service which keeps running even after the parent application is closed. And useful when you need user interface while performing long running operations.

Android Foreground Service 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 chat server for a chat messenger app.

When we started service it will keep running even after app is closed. It doesn’t need any user interface to complete it. But for better user experience we can show some user interface to indicate some long running operation is going on. we can make sticky android custom notification view with buttons for interacting with long running operations. for this kind of operations Android Foreground Service is the best suitable approach.

add start &stop buttons in activity_main.xml layout file

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="16dp" tools:context="${relativePackage}.${activityClass}" >

    <Button android:id="@+id/button1" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="Start Foreground Service" />

    <Button android:id="@+id/button2" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="Stop Foreground Service" />

</LinearLayout>

Create custom notification view in notification.xml layout file

<?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:padding="10dp" android:orientation="vertical" >

        <TextView android:textColor="#787878" android:id="@+id/notification_text_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" android:text="Song Title" android:textStyle="bold" android:ellipsize="end" android:lines="1" />

        <TextView android:textColor="#787878" android:id="@+id/notification_text_artist" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="artist name" android:lines="1" android:ellipsize="end" android:singleLine="true" />

    </LinearLayout>


    <LinearLayout android:id="@+id/llPlayControls" android:layout_alignParentRight="true" android:layout_width="wrap_content" android:layout_height="wrap_content" 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>

MainActivity.java file for start and stop service

package com.nkdroid.android.foreground.service.example;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    private Button startButton,stopButton;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startButton= (Button)findViewById(R.id.button1);
        stopButton = (Button)findViewById(R.id.button2);

        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);
            }
        });


    }
}

Constants.java file

package com.nkdroid.android.foreground.service.example;

public class Constants {
    public interface ACTION {
        public static String MAIN_ACTION = "com.nkdroid.alertdialog.action.main";
        public static String STARTFOREGROUND_ACTION = "com.nkdroid.alertdialog.action.startforeground";
        public static String STOPFOREGROUND_ACTION = "com.nkdroid.alertdialog.action.stopforeground";
    }

    public interface NOTIFICATION_ID {
        public static int FOREGROUND_SERVICE = 101;
    }
}

ForegroundService.java file include service and custom notification view logic

package com.nkdroid.android.foreground.service.example;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;

public 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.notification);

            // 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();

        }
    }

}

Androidmainifest.xml file for Android Foreground Service Example

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.nkdroid.android.foreground.service.example" >

    <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" >
        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name=".ForegroundService$NotificationCloseButtonHandler" />
        <receiver android:name=".ForegroundService$NotificationPlayButtonHandler" />
        <receiver android:name=".ForegroundService$NotificationPrevButtonHandler" />
        <receiver android:name=".ForegroundService$NotificationSkipButtonHandler" />

        <service android:name=".ForegroundService" />


    </application>

</manifest>

Download: Android Foreground Service Example

Android Foreground Service Example Start/Stop Service Example

 

android foreground service example

Android Foreground Service Example Custom Notification View with Buttons

android foreground service example custom notification view

nirav kalola