idEntryPoint
class ImageProcessingService : Service() {

    @Inject
    lateinit var repository: ImageRepository
    private val serviceScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    override fun onCreate() {
        super.onCreate()

    }

    override fun onDestroy() {
        super.onDestroy()
        serviceScope.cancel()
    }

    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        startForegroundService()
        startProcessingImages()
        return START_STICKY
    }

    private fun startForegroundService() {


        val notification: Notification =
            NotificationCompat.Builder(this, ImageProcessingNotification.channel_id)
                .setContentTitle("Processing Images")
                .setContentText("Image processing is running in the background")
                .setSmallIcon(R.drawable.ic_notification)
                .build()

        startForeground(1, notification)
    }

    private fun startProcessingImages() {
        serviceScope.launch {
            try {
                withContext(Dispatchers.IO) {
                    processImages()

                }
            } catch (e: Exception) {
                // Handle exceptions
                Log.wtf("ImageProcessingService", "Error processing images", e)
            }
        }
    }

    private suspend fun processImages() = coroutineScope {
        // Fetch all images
        val allImages = repository.allImages.first() // Adjust based on actual implementation
        Log.wtf("ImageProcessingService", "All Images: $allImages")
        // Filter unprocessed images
        val processedIds =
            repository.processedImages.map { it.map { imageLabel -> imageLabel.imageId } }.first()
        val unprocessedImages = allImages.filter { it.id !in processedIds }
        val MLLabelGenerator = ImageLabeling.getClient(ImageLabelerOptions.DEFAULT_OPTIONS)
        val TextRecognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS)
        val time = measureTime {
            unprocessedImages.sortedByDescending { it.time }.chunked(50).forEach { batch ->
                val otherTime = measureTime {
                    batch.asFlow()
                        .mapNotNull { media ->
                            val inputImage = media.toInputImage(this@ImageProcessingService)
                                ?: return@mapNotNull null
                            val labels = async { MLLabelGenerator.getLabels(inputImage) }
                            val text = async { TextRecognizer.getText(inputImage) }
                            return@mapNotNull ImageLabel(
                                media.id,
                                media.uri.toString(),
                                media.time,
                                labels.await(),
                                text.await()
                            )
                        }
                        .buffer()
                        .collect { imageLabel ->
                            repository.addProcessedImage(imageLabel)
                        }

                }
                Log.wtf("imageProcessing_batch", "time is $otherTime")
            }
        }
        // Process images in batches of 100
        // Stop the service after processing
        Log.wtf("ImageProcessingService", "Processing of ${unprocessedImages.size} took $time")
        stopSelf()


    }

    suspend fun TextRecognizer.getText(inputImage: InputImage) = suspendCoroutine { continuation ->
        this.process(inputImage)
            .addOnSuccessListener { labels ->
                val words = labels.textBlocks.map { it.toWords() }.flatten()
                continuation.resume(words)
            }
            .addOnFailureListener { e ->
                continuation.resume(emptyList<String>())
            }

    }

    fun TextBlock.toWords(): List<String> {
        return this.lines.flatMap { it.elements.map { it.text } }
    }


    suspend fun ImageLabeler.getLabels(inputImage: InputImage) = suspendCoroutine { continuation ->
        this.process(inputImage)
            .addOnSuccessListener { labels ->
                continuation.resume(labels.map { it.text })
            }
            .addOnFailureListener { e ->
                continuation.resume(emptyList<String>())
            }

    }

}


I want a smart approach to make process images take the least amount of time possible