The following two tabs change content below.
Hi, I have written and developed this site to share my experience and ideas with other colleagues. I also started to prepare interview questions and answers for job seekers. I hope it will help you a lot.

Today I am going to share details about service in android and what types of services we can create/use into our application. Basically service is an Android application component that can perform long-running operations in the background, and it does not provide a user interface. Another application component can start a service, and it continues to run in the background even if the user switches to another application.

There are three main types of service is available
1. Started
2. Bound
3. Scheduled

All types services code you can download from here ServiceApplication

So in the below section we are going to describe each type with example one by one. So first lets start with Started type

Started: A service is started when an application component (such as an activity) calls startService(). After it’s started, a service can run in the background indefinitely, even if the component that started it is destroyed. Usually, a started service performs a single operation and does not return a result to the caller. For example, it can download or upload a file over the network. When the operation is complete, the service should stop itself.

Note: If you are starting the service using startService() then its your responsibility to stop service using stopService() or stopSelf() once your operation has been completed.

1. Creating the MyService class by extending the android.app.Service

/**
 * @author Khushvinders
 */

public class MyService extends Service {
    static String TAG = MyService.class.getName();
    public MyService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "--Service started--");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "--Service onStartCommand ---"+ intent.getStringExtra("empid"));
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
       // return null so that no one can bind with this service
        return  null;
    }

}

In MyService.java first onCreate() will be called and then onStartCommand(). If you notice under onBind() I have return the null so that other component or application cannot bind with this service.

If we are trying to start same service two or more times in that case new service instance will not be get created (If that service instance is already exist) and onStartCommand() method will get called where we can get the Intent object and do the appropriate operation.

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.d(TAG, "--Service onStartCommand ---"+ intent.getStringExtra("empid"));
    return super.onStartCommand(intent, flags, startId);
}

2. In next creating a StartedActivity from this will start MyService.java like below

/**
 * @author Khushvinders 
 */
public class StartedActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent one = new Intent(this, MyService.class);
        one.putExtra("empid", "101");
        startService(one);


        Intent two = new Intent(this, MyService.class);
        two.putExtra("empid", "102");
        startService(two);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopService(new Intent(this, MyService.class));
    }
}



3. Make sure you given all component’s entry in Manifest file like

<service
    android:name=".started.MyService"
    android:enabled="true"
    android:exported="true" />

<activity android:name=".started.StartedActivity"></activity>

In the StartedActivity.java I have tried to start service two times with different Intent object. In this case MyService’s onCreate() will call one time and onStartCommand() will call two time.

started

4. In the last point I am giving reminder to stop the service (Once your task has been completed) using  stopService() or stopSelf() . If trying to stop outside the service then call stopService() function with Intent (with service name). if trying to stop from service itself then call stopSelf().

@Override
protected void onDestroy() {
    super.onDestroy();
    stopService(new Intent(this, MyService.class));
}

Note: If you have some heavy task or long running operation then always create separate thread inside the service to avoid ANR( Application not responding) message. Or best way to use IntentService rather then new thread like below section.

IntentService: This is also coming under “Started” service. This is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.

/**
 * @author Khushvinders
 */

public class MyService extends IntentService {
    static String TAG = MyService.class.getName();

    public MyService(){
        super(TAG);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "--Service started--");
    }

   //WILL UNCOMMENT THIS METHOD WHEN WE WILL USE NORMAL SERVICE BECAUSE THIS WILL WORK ON MAIL APPLICATION THREAD

    /*
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "--Service onStartCommand ---"+ intent.getStringExtra("empid"));
        return super.onStartCommand(intent, flags, startId);
    }*/

    //USED THIS METHOD BECAUSE FOR THIS INTENTSERVICE WILL USER WORKER THREAD
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d(TAG, "--Service onHandleIntent ---"+ intent.getStringExtra("empid"));
    }

    @Override
    public IBinder onBind(Intent intent) {
       // return null so that no one can bind with this service
        return  null;
    }

}

Note: For IntentService we need to implement onHandleIntent() function to receive new Intent. So with IntentService you no need to create worker thread because its by default run on separate thread and once task completed automatically stop the service. So you also no need to worry about stop service in this case.

 

Second type is Bounded Service

Bound: 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, receive results, and even do so across processes with inter-process communication (IPC). A bound service runs only as long as another application component is bound to it. Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed.

Note: For started and Bound service both are same only it depends on you which method you are implementing in service and how you are starting the service.

1. Create the MessangerService.java by extending the Service class and implement onBind() function to receive Binder object for IPC.

@Override
public IBinder onBind(Intent intent) {
    return messenger.getBinder();
}

Full service class is here where we implemented Messenger to handle message.

/**
 * @author Khushvinders
 */
public class MessangerService extends Service {
    static final int MSG_SAY_HELLO = 1;
    Messenger messenger = new Messenger(new MyBinder());
    public MessangerService() {
    }

    class MyBinder extends Handler{
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MSG_SAY_HELLO:
                    Bundle bundle = msg.getData();
                    Toast.makeText(getApplicationContext(), bundle.getString("sms"), Toast.LENGTH_LONG).show();
                    Message message = Message.obtain(null, MessangerService.MSG_SAY_HELLO, 0, 0);

                    try {
                        Bundle bundle1 = new Bundle();
                        bundle1.putString("response", "Your Message Delivered!!");
                        message.setData(bundle1);
                        msg.replyTo.send(message);
                    }
                    catch (RemoteException e){
                        e.printStackTrace();
                    }

                break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return messenger.getBinder();
    }
}

2. Created activity to bind the service. In the BindMessangerActivity.java activity also I implemented Messenger to receive message from Binded Service. To bound service below is the code:

bindService(new Intent(this, MessangerService.class), serviceConnection, BIND_AUTO_CREATE);

3. While binding the service we need to pass ServiceConnection interface’s object. Under ServiceConnection interface defined two methods to check the connection status

ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        messenger = new Messenger(iBinder);
    }

    @Override
    public void onServiceDisconnected(ComponentName componentName) {
        Log.d("BindMessangerActivity: ", "--onServiceDisconnected--");
    }
};

 

For IPC implement Messenger in activity also and given replyTo messenger object so that service can replied to activity client

((Button)findViewById(R.id.message)).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Message message = Message.obtain(null, MessangerService.MSG_SAY_HELLO, 0, 0);

        message.replyTo = clientMessenger;

        try {
            Bundle bundle = new Bundle();
            bundle.putString("sms", mySMS.getText().toString());
            message.setData(bundle);
            messenger.send(message);

        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
});

Full activity code is here:

/**
 * @author Khushvinders
 */
public class BindMessangerActivity extends AppCompatActivity {

    private Messenger messenger;

    static final int MSG_SAY_HELLO = 1;

    EditText mySMS;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bind_messanger);
        mySMS = (EditText)findViewById(R.id.mySMS);

        bindService(new Intent(this, MessangerService.class), serviceConnection, BIND_AUTO_CREATE);


        ((Button)findViewById(R.id.message)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Message message = Message.obtain(null, MessangerService.MSG_SAY_HELLO, 0, 0);

                message.replyTo = clientMessenger;

                try {
                    Bundle bundle = new Bundle();
                    bundle.putString("sms", mySMS.getText().toString());
                    message.setData(bundle);
                    messenger.send(message);

                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });

    }

    private Messenger clientMessenger = new Messenger(new ClientBinder());
    class ClientBinder extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MSG_SAY_HELLO:
                    Bundle bundle = msg.getData();
                    Toast.makeText(getApplicationContext(), bundle.getString("response"), Toast.LENGTH_LONG).show();

                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    }

    ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            messenger = new Messenger(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d("BindMessangerActivity: ", "--onServiceDisconnected--");
        }
    };

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopService(new Intent(this, MessangerService.class));
    }

Note: in case of bound service you no need to worry about stop service because bound service automatically will be close once your task is completed.

After run the application showing how we are passing message to service from activity and getting confirmation from service

bound_service

Getting confirmation after successfully message delivery.

bound_service1

 

Scheduled Service : 

A service is scheduled when an API such as the JobScheduler, introduced in Android 5.0 (API level 21), launches the service. You can use the JobScheduler by registering jobs and specifying their requirements for network and timing. The system then gracefully schedules the jobs for execution at the appropriate times.

Note: If your app targets Android 5.0 (API level 21), Google recommends that you use the JobScheduler to execute background services

In the Scheduled type service there is three main classes are there
1. JobService : This is the base class that handles asynchronous requests that were previously scheduled. You are responsible for overriding onStartJob(JobParameters), which is where you will implement your job logic. if your task completed and need to clear the resource then onStopJob(android.app.job.JobParameters) function will be called.

@Override
public boolean onStartJob(JobParameters jobParameters) {
    new MyJob().execute(jobParameters);
    return true;
}

@Override
public boolean onStopJob(JobParameters jobParameters) {
    return JOB_DONE_FLAG;
}

2. JobInfo: Container of data passed to the JobScheduler fully encapsulating the parameters required to schedule work against the calling application. These are constructed using the JobInfo.Builder. You must specify at least one sort of constraint on the JobInfo object that you are creating. 

JobInfo jobInfo = new JobInfo.Builder(JOB_ID, serviceName)
        .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
        .setOverrideDeadline(10000)  //Use this if you want to run your job forcefully
        .build();

In the above code block given two constraint 1. Network type should be UNMETERED (without data limit) 2. if this network is not there then after 10 second it complete the job forcefully. if network is there then it will not wait for 10 second to complete the job. it will start job on the spot (Actually it depends on job queue which is already there)

3. JobScheduler : This is an API for scheduling various types of jobs against the framework that will be executed in your application’s own process. To apply the job in JobScheduler we can use below code:

JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
int result = scheduler.schedule(jobInfo);
if (result == JobScheduler.RESULT_SUCCESS)
    Log.d("Scheduled Activity", "Job scheduled successfully!");

Here I am sharing the full service code:

/**
 * Created by Khushvinders on 15-Feb-17.
 */

public class MyJobService extends JobService {
    @Override
    public boolean onStartJob(JobParameters jobParameters) {
        new MyJob().execute(jobParameters);
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters jobParameters) {
        return JOB_DONE_FLAG;
    }

    boolean JOB_DONE_FLAG = false;
    private class MyJob extends AsyncTask<JobParameters, Void, JobParameters[]> {

        @Override
        protected JobParameters[] doInBackground(JobParameters... jobParameterses) {
            for(int i=0;i<=5;i++){
                System.out.println("Looping ...."+i);
            }
            JOB_DONE_FLAG = true;
            return jobParameterses;
        }

        @Override
        protected void onPostExecute(JobParameters[] jobParameterses) {
            for (JobParameters params : jobParameterses) {
                    jobFinished(params, false);
              }
        }


    }
}

Activity code is :

/**
 * @author Khushvinders 
 */
public class ScheduledActivity extends AppCompatActivity {

    public static int JOB_ID = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scheduled);
        ((Button)findViewById(R.id.schedule)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ComponentName serviceName = new ComponentName(ScheduledActivity.this, MyJobService.class);
                JobInfo jobInfo = new JobInfo.Builder(JOB_ID, serviceName)
                        .setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED)
                        .setOverrideDeadline(10000)  //Use this if you want to run your job forcefully
                        .build();

                JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
                int result = scheduler.schedule(jobInfo);
                if (result == JobScheduler.RESULT_SUCCESS)
                    Log.d("Scheduled Activity", "Job scheduled successfully!");
            }
        });
    }
}

Note: Please make sure you are adding all component into the Manifest file like below:

<service
    android:name=".started.MyService"
    android:enabled="true"
    android:exported="true" />

<activity android:name=".started.StartedActivity"></activity>

<service
    android:name=".binded.MessangerService"
    android:enabled="true"
    android:exported="true" />

<activity android:name=".binded.BindMessangerActivity" />

<service
    android:name=".scheduled.MyJobService"
    android:permission="android.permission.BIND_JOB_SERVICE" />

 <activity android:name=".scheduled.ScheduledActivity"></activity>

after run this service if network is UNMETERED then it will run the job and will complete the operation which we can see on the console. and after completing the job this service automatically will stopped.

Scheduled service log

 

Full code of all types of services you can download from here ServiceApplication

scheduled_service

 

6,930 total views, 12 views today

Leave a Reply

Your email address will not be published. Required fields are marked *