In this post, I will explain the foreground service android in Kotlin. We’ll see the real implementation of foreground service. So let’s get started.
In the previous Foreground Service tutorial, I have explained about Foreground Service? and the advantage of Foreground Service. Basically the previous article is based on Java. In this android app tutorial, we’ll learn how to implement is Kotlin.
Steps of implementation Foreground Service
- Create and Project Setup
- Create a derived class of Service named is ForegroundService.kt
- Make Notification Channel
- Override methods
- onStartCommand
- mandatory
- onBind
- mandatory
- must return null
- onCreate
- optional to override
- call only once when Service is being created
- onDestory
- optional to override
- Call when background service is destroyed
- onStartCommand
- Declare your service and permission in AndroidManifest.xml
1. Create and Project Setup
Let’s open the Android Studio and create a new project with Kotlin. In this demo, I’m using androidx artifact for this sample project.
2. Create a subclass of Service name is ForegroundService.kt
package com.foregroundservice import android.app.NotificationChannel import android.app.NotificationManager import android.app.PendingIntent import android.app.Service import android.content.Context import android.content.Intent import android.os.Build import android.os.IBinder import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat class ForegroundService : Service() { private val CHANNEL_ID = "ForegroundService Kotlin" companion object { fun startService(context: Context, message: String) { val startIntent = Intent(context, ForegroundService::class.java) startIntent.putExtra("inputExtra", message) ContextCompat.startForegroundService(context, startIntent) } fun stopService(context: Context) { val stopIntent = Intent(context, ForegroundService::class.java) context.stopService(stopIntent) } } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { //do heavy work on a background thread val input = intent?.getStringExtra("inputExtra") createNotificationChannel() val notificationIntent = Intent(this, MainActivity::class.java) val pendingIntent = PendingIntent.getActivity( this, 0, notificationIntent, 0 ) val notification = NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("Foreground Service Kotlin Example") .setContentText(input) .setSmallIcon(R.drawable.ic_notification) .setContentIntent(pendingIntent) .build() startForeground(1, notification) //stopSelf(); return START_NOT_STICKY } override fun onBind(intent: Intent): IBinder? { return null } private fun createNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val serviceChannel = NotificationChannel(CHANNEL_ID, "Foreground Service Channel", NotificationManager.IMPORTANCE_DEFAULT) val manager = getSystemService(NotificationManager::class.java) manager!!.createNotificationChannel(serviceChannel) } } }
In this source file, we are doing two things. first, one is we are creating notification channel. The second part is starting foreground service, So its take two parameters id and notification instance for showing the notification.
You guys well know after android oreo imposed some implication on service. As per Android Developer team, you can’t perform long-running operations in the background without notifying users. That by we are pass notification object inside the startForeground() method.
3. Declare your service and permission in AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.foregroundservice"> <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> <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"> <service android:name=".ForegroundService"> </service> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest>
4. Add a button inside activity_main.xml layout
Let’s open the activity_main.xml file. I make some changes to test foreground service.
<?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" > <androidx.appcompat.widget.AppCompatTextView android:id="@+id/buttonStart" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:layout_marginTop="220dp" android:background="@color/colorPrimary" android:padding="8dp" android:text="Start Service" android:textColor="@color/colorWhite" android:textSize="18sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <androidx.appcompat.widget.AppCompatTextView android:id="@+id/buttonStop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:background="@color/colorPrimary" android:padding="8dp" android:onClick="onStopServiceClick" android:text="Stop Service" android:textColor="@color/colorWhite" android:textSize="18sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/buttonStart" app:layout_constraintVertical_bias="0.113" /> </androidx.constraintlayout.widget.ConstraintLayout>
5. For testing, foreground service paste below code in MainActivity
package com.foregroundservice import android.os.Bundle import android.view.View import androidx.appcompat.app.AppCompatActivity import kotlinx.android.synthetic.main.activity_main.buttonStart import kotlinx.android.synthetic.main.activity_main.buttonStop class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) buttonStart.setOnClickListener(View.OnClickListener { ForegroundService.startService(this, "Foreground Service is running...") }) buttonStop.setOnClickListener(View.OnClickListener { ForegroundService.stopService(this) }) } }
Conclusion
Now your job is done, In this post, we learned foreground service implementation in Kotlin. Let’s run the project, you click on ‘start service’ button than service will be started, and notification will appear on notification bar. Notification will disappear once you clicked on ‘stop service’ button.
Keep in touch
If you want to keep in touch and get an email when I write new blog posts, follow me on facebook or subscribe us. It only takes about 10 seconds to register.
Still, if you have any queries please put your comment below.
4 Comments
can you explain the need for companion object here ??
In Kotlin companion object can be like static methods in Java so we add two “static”methods startService and stopService to be able to call them from any activity or fragment
Hi, somebody knows why the notification still eve if the service is stopped? PLEASE
you need to call stop foreground() in your sevice class in onDestrory in these example