I have a foreground service that changes wallpapers with a delay, so I'm using coroutines inside of it,I call it from another class with startService(Intent(this,MySerivce::class.java)) but when I stop it with stopService(Intent(this,MySerivce::class.java)), only functions on main thread stop (like showNotification()), here's my code:
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val externalStorageState = Environment.getExternalStorageState()
if (externalStorageState.equals(Environment.MEDIA_MOUNTED)){
val root=getExternalFilesDir(null)?.absolutePath
val myDir = File("$root/saved_images")
val list = myDir.listFiles()
if (myDir.exists()&&list.size>=2){
CoroutineScope(Dispatchers.IO).launch {
val time = intent?.getIntExtra("TIME",0)
if (time != null) {
manageWallpapers(list,time)
}
}
}}
showNotification()
return START_STICKY
}
}
and here's manageWallpapers function
private suspend fun manageWallpapers(list: Array<File>?, time:Int){
while (true){
if (list != null) {
for (image in list){
setWallpaper(image)
delay(time.toLong())
}
}
}
}
You need to keep a reference to the job returned by launch and call cancel() on it when your service is stopped.
private var job: Job? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val externalStorageState = Environment.getExternalStorageState()
if (externalStorageState.equals(Environment.MEDIA_MOUNTED)){
val root=getExternalFilesDir(null)?.absolutePath
val myDir = File("$root/saved_images")
val list = myDir.listFiles()
if (myDir.exists()&&list.size>=2){
job = CoroutineScope(Dispatchers.IO).launch { // HERE
val time = intent?.getIntExtra("TIME",0)
if (time != null) {
manageWallpapers(list,time)
}
}
}}
showNotification()
return START_STICKY
}
}
override fun onDestroy() {
job?.cancel()
job = null
super.onDestroy()
}
Another option is to keep a reference to your CoroutineScope and call cancel on it.
If you subclass from LifecycleService, you can use lifecycleScope to launch your coroutine, so it will be cancelled automatically when the service stops.
build.gradle:
implementation 'androidx.lifecycle:lifecycle-service:2.3.1'
In your service, a subclass of LifecycleService:
lifecycleScope.launch {
val time = intent?.getIntExtra("TIME",0)
if (time != null) {
manageWallpapers(list,time)
}
}
There's no need to specify Dispatchers.IO, since you are only calling a suspend function, not a blocking function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With