Life Cycle of Android Services
Two paths for completion of an android service's lifecycle are as follows:
Started Service
When an application component calls the startService() method, a service will start. Once a service is started on this path, it will not stop even if the component which called this service gets killed itself. The service will come to a halt only when the stopService() or the stopSelf() method is invoked.
Bounded Service
The bindService() method is used to bind an application component to a Bounded Service. The execution of this service will not stop unless all the bound components unbind themselves, which can be done using the unbindService() method. It functions like a client-server interface where the components can interact with it by sending requests, and the service will then respond by sending some data back in return.
This is how the android services lifecycle looks like by following these paths:
Image Source: androidcookbook
Callback Methods of Android Services Lifecycle
Following are some important methods that need to be overridden to write an android service:
- onCreate(): When a new service is started, this is the method that gets invoked the first. It is used to perform a one-time-set-up upon starting of a service.
- onStartCommand(): As the name suggests, this method is called when you need to start a service. To stop the started service, the stopService() or stopSelf() method can be used.
- onBind(): When an application component calls the bindService() method to bind itself with a particular service, this method is invoked. This method is mandatory to implement. In case you don't need to bind anything, you can simply return null from this method.
- onUnbind(): This method is used when an application component needs to unbind itself from a service.
- onRebind(): When all the existing components have unbinded themselves from the service, and you need to add new components with the service, this method is called.
- onDestroy(): This method is invoked when the service finishes and is being cleared from the memory. This is the final callback received by any service, as after this, the service is destroyed.
Example
In this example, we will create a service to play the default mobile ringtone.
First, we need to create a new project in Android Studio by selecting the empty activity option. In this activity_main.xml file, we have added code for adding two buttons for a start and stop of service.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:text="Start Service"
app:layout_constraintBaseline_toBaselineOf="@+id/button2"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="29dp"
android:layout_marginBottom="82dp"
android:text="Stop Service"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/button1" />
</androidx.constraintlayout.widget.ConstraintLayout>
Now we will create a CustomService.kt file in the same directory as your MainActivity.kt file. In this file, we have created a service to play the mobile ringtone.
CustomService.kt
import android.content.Intent
import android.app.Service
import android.os.IBinder
import android.media.MediaPlayer
import android.provider.Settings
import android.util.Log
import android.widget.Toast
// Custom Service extending the Service Class
class CustomService : Service() {
// declaring object of MediaPlayer
lateinit var ringtone_player:MediaPlayer
var show_text = ""
// overriding the onStartCommand
override fun onStartCommand(intent: Intent, flags: Int, Id: Int): Int {
var ringtone = Settings.System.DEFAULT_RINGTONE_URI // default ringtone of the device
// creating a MediaPlayer
ringtone_player = MediaPlayer.create(this, ringtone)
show_text = "Service has been Started"
ringtone_player.setLooping(true)
val duration = Toast.LENGTH_LONG // setting the duration to Long
// start the process
ringtone_player.start()
Toast.makeText(this, show_text, duration).show()
return START_STICKY
}
// stop on calling this method
override fun onDestroy() {
super.onDestroy()
// text that needs to be displayed when this function gets invoked
show_text = "Service has been Stopped"
ringtone_player.stop() // stop the ringtone_player
val duration = Toast.LENGTH_LONG // setting the duration to Long
Toast.makeText(this, show_text, duration).show()
}
// overriding the onBind Method
override fun onBind(intent: Intent): IBinder? {
//as we don't need to bind anything to this service
// we are returning null from this method
return null
}
}
Now that, we have created a custom service, we will now add it to the MainActivtiy.kt file.
MainActivtiy.kt
import android.util.Log
import android.os.Bundle
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.widget.Button
import android.view.View
// Main Activity class extends the OnClickListener and AppCompactActivity
class MainActivity : View.OnClickListener, AppCompatActivity() {
// declaring objects of Button class
var button1: Button? = null
lateinit var tag_name : String // tag for logging
var button2: Button? = null
lateinit var msg: String
// overriding the onCreate Function
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tag_name = "Android Services: "
// assign id to button1
button1 = findViewById<View>(R.id.button1) as Button
// declaring listeners for button 1
msg = "Declaring Listener for button 1"
button1!!.setOnClickListener(this)
Log.d(tag_name, msg)
// assign id to button1
button2 = findViewById<View>(R.id.button2) as Button
// declaring listeners for button 1
msg = "Declaring Listener for button 1"
button2!!.setOnClickListener(this) // declaring listeners for button 2
Log.d(tag_name, msg)
}
override fun onClick(current_view: View) {
var custom_service = CustomService::class.java
lateinit var var_intent: Intent
// check if the current_view is equal to button1
// if yes, then we need to start the service
if (current_view === button1 ) {
var_intent = Intent(this, custom_service)
startService(var_intent)
}
// stop the service if current_view is equal to button2
else if (current_view === button2) {
var_intent = Intent(this, custom_service)
stopService(var_intent)
}
}
}
Finally, we will register the service in the AndroidManifest.xml file.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidservices">
<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/Theme.AndroidServices">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!--Registering the New Service-->
<service android:name=".CustomService"/>
</application>
</manifest>
Output
When the Start Service button is clicked, the following message is displayed on the screen, and the ringtone starts playing in the background.
Upon clicking the stop Service button, the ringtone is stopped, and the following message is displayed on the screen.
FAQs
-
What does START_STICKY do?
START STICKY instructs the OS to recreate the service and run onStartCommand() with a null intent once it has enough memory.
-
What is the purpose of using Toast.Length_Long?
It signifies the amount of time the message will be displayed on the screen. Length_Long is used when we need to show the message for a longer duration.
-
When do we use lateinit?
While working with variables that are declared first but initialized at a later time, we use the lateinit tag in the front of those variables.
Key Takeaways
In this article, we have extensively discussed Services in Android topics and their implementation in Android Studio. We discussed how Services could be created and registered in an android application.
Read more: Operating System, Free Space Management in OS and Usb debugging
We hope that this blog has helped you enhance your knowledge regarding Android Services and if you would like to learn more, check out our articles on Android Intents. Do upvote our blog to help other ninjas grow. Happy Coding!