In my Service, I need to call on onStartCommand some methods that require withContext(Dispatchers.IO) instead CoroutineScope(Dispatchers.IO) like:
But Suspend function 'withContext' should be called only from a coroutine or another suspend function. So if onStartCommand can't be a suspend function because it has override and withContext can't be called by CoroutineScope because Inappropriate blocking method call of methods
val url = URL(pokemon.linkImage)
val iS = url.openConnection().getInputStream()
How can I resolve this problem?
My onStartCommand():
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
//create the directory on internal storage that will contains all pokemon images
val path = applicationContext.filesDir.absolutePath
val dirName = "/pokeimg"
val dir = File(path, dirName)
if(!dir.exists())
dir.mkdir()
CoroutineScope(Dispatchers.IO).launch {
//get the list of pokemon when they are loaded from repository
val listOfPokemon =
PersistenceSingletonRepository.getInstance(applicationContext).getListOfPokemon()
//download all the image for each pokemon in the list, but only if the image is
//not present in the directory
for(pokemon in listOfPokemon) {
val imageName = "${pokemon.name}.png"
val file = File("${dir.absolutePath}/$imageName")
//check if image not exists on internal storage and if is not an official-artwork
//images that aren't official-artwork has less quality so don't resize
if(!file.exists()) {
//download img
val url = URL(pokemon.linkImage)
val iS = url.openConnection().getInputStream()
val opts = BitmapFactory.Options()
if (!Utils.isBadImage(pokemon.linkImage)) {
//request a smaller image
opts.inSampleSize = 2
}
val bitmap = BitmapFactory.decodeStream(iS, null, opts)
val fOut= FileOutputStream(file)
bitmap?.compress(Bitmap.CompressFormat.PNG, 100, fOut)
fOut.flush()
fOut.close()
}
}
stopSelf()
}
return START_NOT_STICKY
}
You can safely ignore that warning, it's known to have many false positives. You launched the coroutine in the IO dispatcher, which is designed for blocking calls.
On the other hand, launching anything with an ad-hoc CoroutineScope that has no parent and no lifecycle binding, is usually the wrong thing to do. You should respect the Service lifecycle and cancel your coroutine in onDestroy. See for example here.
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