Android Service-LifeCycle and Working | With Example

Spread knowledge

 

Ever wondered how a song that you started on your music app plays even after you have killed the app? Well, this happens because of service. Service is a indefinitely running background operation without an UI . Google explains service as

A Service is an 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. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC). For example, a service can handle network transactions, play music, perform file I/O, or interact with a content provider, all from the background.

  • Service is an Android Component without an UI
  • It is used to perform long running operations in background. Services run indefinitly unless they are explicitly stopped or destroyed
  • It can be started by any other application component. Components can even infact bind to a service to perform Interprocess- Comminication
  • It can still be running even if the application is killed unless it stops itself by calling stopself() or is stopped by a Android component by calling stopService().
  • If not stopped it goes on running unless is terminated by Android due to resource shortage
  • The android.app.Service is subclass of ContextWrapper class.

Note: Service always runs on the main thread by default. When the doc says “long running processes in background” it means that processes without an UI. So if you are performing a time consuming task  you must be creating a background thread in the service.

As explained above service can either be started or bound. You just need to call either startService() or bindService() from any of your android components. Based on how your service was started it will either be “started” or “bound”

  • Started
    A service is started when an application component, such as an activity, starts it by calling startService(). Now the service can run in the background indefinitely, even if the component that started it is destroyed.
  • 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, get results, and even do so across processes with interprocess communication (IPC).

 

service_lifecycle
Android Service Lifecycle

Like any other components service also has callback methods. These will be invoked while the service is running to inform the application of its state. Implementing these in your custom service would help you in performing the right operation in the right state.

There is always only a single instance of service running in the app. If you are calling startService() for a single service multiple times in your application it just invokes the onStartCommand() on that service. Neither is the service restarted multiple times nor are its multiple instances created

 onCreate()

This is the first callback which will be invoked when any component starts the service. If the same service is called again while it is still running this method wont be invoked. Ideally one time setup and intializing should be done in this callback.

onStartCommand()

This callback is invoked when service is started by any component by calling startService(). It basically indicates that the service has started and can now run indefinetly. Now its your responsibilty to stop the service. This callback also has  a int return type. This return type describes what happens to the service once it is destroyed by the system.There are three possible return types

  • START_STICKY
    Returning this indicates that once the service is killed by the system it will be recreated and onStartCommand method will be invoked again.But the  previous intent is not redelivered. Instead onStartCommand is called with a null intent
  • START_NOT_STICKY
    Returning this indicates that the service wont be recreated if it is killed by the system
  • START_REDELIVER_INTENT
    Returning this indicates that once the service is killed by the system it will be recreated and onStartCommand method will be invoked again.But here the original intent is redelivered again.

onBind()

This is invoked when any component starts the service by calling onBind. Basically the component has now binded with the service. This method needs to return your implementation of IBinder which will be used for Interprocess Communication. If you dont want your service to bind with any component you should just return null nevertheless this method needs to be implemented

onUnbind()

This is invoked when all the clients are disconnected from the service.

onRebind()

This is invoked when new clients are connected to the service. It is called after onUnbind

onDestroy()

This is a final clean up call from the system. This is invoked just before the service is being destroyed. Could be very useful to cleanup any resources such as threads, registered listeners, or receivers. But very rarely it happens that the service is destroyed with onDestroy not being invoked

Example :

In this example we will create a service with runs in background and prints logs until we stop it. 

Step-1- Create a Custom Service

As we have already discussed Service doesn’t have a its own layout hence no xml file is required.

  •  Right click on your package and select New->Java Class. Name your class as MyService. This should extend the Android’s Service class.
  • We will be using a Handler and  Runnable implemenation to print the logs every 5 seconds as long as the service is running

Then implement all the callbacks as shown in the code snippet below

public class MyService extends Service {
    
    //Declaring the handler
    private Handler handler;
    //Declaring your implementation of Runnable
    private Runner runner;
    /*
    Regardless of whether you want your service to be binded
    or not you should always implement onBind. You should return null if you
    dont want it to bind
    */
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    /*
    Initialization of Handler and Runner
    */
    public void onCreate() {
        super.onCreate();

        Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
        handler = new Handler();
        runner = new Runner();

    }
    // Starting the Runnable with handler
    public int onStartCommand(Intent intent, int id, int startID) {
        handler.post(runner);
        return START_STICKY;
    }
    //Removing the callbacks from handler once the service is destroyed
    @Override
    public void onDestroy() {
        super.onDestroy();
        handler.removeCallbacks(runner);
        Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
    }

    /*
    A runnable class designed in such a way that it is runs every 5 seconds
    */
    public class Runner implements Runnable {

        @Override
        public void run() {

            Log.d("AndroidClarified", "Running");
            handler.postDelayed(this, 1000 * 5);
        }
    }

}

Step -2 Declaring the service in Manifest

As for every android component we first need to declare our service inside the AndroidManifest.xml. For this  you just need to add the below code snippet under the <application> tag

<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.androidclarified.serviceapp">
    <application
       android:allowBackup="true"
       android:icon="@mipmap/ic_launcher"
       android:label="@string/app_name"
       android:roundIcon="@mipmap/ic_launcher_round"
       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>
        <service android:name=".MyService"/>
    </application>
</manifest>

Step -3  -Starting the service

Since every service needs to be started from some other Android component. We will first create a Android Activity( If you are not sure how to create a activity read this ) . You can just right click on your package and select New->Activity->Empty Activity. This will automatically create an Activity class and a layout file.

  • We add two buttons to the layout file as shown in the snippet below
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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.example.androidclarified.serviceapp.MainActivity">
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_centerInParent="true"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/start_button"
            android:layout_margin="20dp"
            android:text="Start Service"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <Button
            android:layout_width="wrap_content"
            android:text="Stop Service"
            android:layout_margin="20dp"
            android:id="@+id/stop_button"
            android:layout_height="wrap_content" />
    </LinearLayout>
</RelativeLayout>

 

  • Now we have to initialize both the buttons and add click listeners. This is how our activity class will look now
  • Starting the service is similar to starting any other activity. You just need to create an Intent object specifying the service and then call startService() .
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button startButton, stopButton;

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

        startButton = (Button) findViewById(R.id.start_button);
        stopButton = (Button) findViewById(R.id.stop_button);

        startButton.setOnClickListener(this);
        stopButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {

        Intent intent = new Intent(this, MyService.class);

        switch (v.getId()) {
            case R.id.start_button:
                startService(intent);
                break;
            case R.id.stop_button:
                stopService(intent);
                break;

        }

    }
}

 

service_shot
MainActivity

 

running
Logcat

Conclusion:

You must know now be clear of what a service is and what are its various states. As I said you Android service is one of the four Android components if you want  read about all of them click here. There is one more important component of an application-Activity (click here to read about it)


Spread knowledge

2 Replies to “Android Service-LifeCycle and Working | With Example”

Leave a Reply

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