kotlinandroid-jetpack-composeandroid-service

Why is my android services process ends the moment it starts?


I'm trying to build an android service that continues the bluetooth low energy scan from my jetpack compose app that interacts with a ble beacon. My goal now is simply to get my foreground service started once I put my app in the background. My code compiles, the log statements that keep track of the process shows up normally in my logcat, but the service process ends the moment it is started and the notification never appears on the status bar.

Here is my bluetooth service class code


@AndroidEntryPoint
class BluetoothScanService : Service() {

    @Inject lateinit var bluetoothUtils: BluetoothUtils
    @Inject lateinit var sharedDataManager: SharedDataManager
    @Inject lateinit var bleScanCallback: BleScanCallback

    override fun onCreate() {
        super.onCreate()
        // Initialize your BluetoothUtils, SharedDataManager, and ScanCallback here
        Log.i("foreground", "Inside onCreate in Bluetooth Service")

        val notification = createForegroundNotification()
        startForeground(1, notification)

        Log.i("foreground", "BluetoothUtils: $bluetoothUtils")
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if (intent == null) {
            Log.e("foreground", "Received null intent in onStartCommand")
            return START_NOT_STICKY // or return an appropriate value
        }



        Log.i("foreground", "Inside onStartCommand in Bluetooth Service")
        // Start the Bluetooth scan in the foreground service
        bluetoothUtils.startScanning(bleScanCallback)

        return START_NOT_STICKY
    }

    private fun createForegroundNotification(): Notification {
        val channelId = "BluetoothScanChannel"
        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        // Create notification channel for Android 8.0 and above
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                channelId,
                "Bluetooth Scan",
                NotificationManager.IMPORTANCE_DEFAULT
            )
            notificationManager.createNotificationChannel(channel)
        }

        // Create the notification
        val notification = NotificationCompat.Builder(this, channelId)
            .setContentTitle("Bluetooth Scanning")
            .setContentText("Bluetooth scanning is running in the background.")
            //.setSmallIcon(R.drawable.ic_bluetooth)
            .build()

        return notification
    }

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

and this is how I call the service in my onPause() and onResume() from my MainActivity (I have only one activity, because I am using Jetpack compose. Every screen in my app is a composable).

   override fun onPause(){
        super.onPause()
        Log.i("foreground", "Inside onPause in MainActivity")
        val intent = Intent(this, BluetoothScanService::class.java)
        Log.i("foreground", "the intent ${intent}")

        startService(intent)

    }
    override fun onResume() {
        super.onResume()
        Log.i("foreground", "Inside onResume in MainActivity")
        val intent = Intent(this, BluetoothScanService::class.java)
        stopService(intent)

    }

And this is my logcat results

2025-01-21 13:49:32.544 32677-32677 foreground              com.myApp.bleApp              I  Inside onPause in MainActivity
2025-01-21 13:49:32.545 32677-32677 foreground              com.myApp.bleApp              I  the intent Intent { cmp=com.myApp.bleApp/.common.foregroundServices.BluetoothScanService }
2025-01-21 13:49:32.590 32677-32677 foreground              com.myApp.bleApp              I  Inside onCreate in Bluetooth Service
2025-01-21 13:49:32.691 32677-32677 foreground              com.myApp.bleApp              I  BluetoothUtils: com.myApp.bleApp.hardware.bluetooth.BluetoothUtils@7da3008
2025-01-21 13:49:32.693 32677-32677 foreground              com.myApp.bleApp              I  Inside onStartCommand in Bluetooth Service
---------------------------- PROCESS ENDED (32677) for package com.myApp.bleApp ----------------------------

If I use return START_STICKY instead of return START_NOT_STICKY, the process still ends but it is restarted with a null intent and the notification appears in my status bar. These are my logcat results

2025-01-21 13:51:45.677  1960-1960  foreground              com.myApp.bleApp              I  Inside onPause in MainActivity
2025-01-21 13:51:45.678  1960-1960  foreground              com.myApp.bleApp              I  the intent Intent { cmp=com.myApp.bleApp/.common.foregroundServices.BluetoothScanService }
2025-01-21 13:51:45.739  1960-1960  foreground              com.myApp.bleApp              I  Inside onCreate in Bluetooth Service
2025-01-21 13:51:45.809  1960-1960  foreground              com.myApp.bleApp              I  BluetoothUtils: com.myApp.bleApp.hardware.bluetooth.BluetoothUtils@eaa3f16
2025-01-21 13:51:45.811  1960-1960  foreground              com.myApp.bleApp              I  Inside onStartCommand in Bluetooth Service
---------------------------- PROCESS ENDED (1960) for package com.myApp.bleApp ----------------------------
---------------------------- PROCESS STARTED (2496) for package com.myApp.bleApp ----------------------------
2025-01-21 13:51:49.731  2496-2496  foreground              com.myApp.bleApp              I  Inside onCreate in Bluetooth Service
2025-01-21 13:51:49.741  2496-2496  foreground              com.myApp.bleApp              I  BluetoothUtils: com.myApp.bleApp.hardware.bluetooth.BluetoothUtils@861bce1
2025-01-21 13:51:49.742  2496-2496  foreground              com.myApp.bleApp              E  Received null intent in onStartCommand

This is the error I get when the process ends

FATAL EXCEPTION: main Process: com.myApp.bleApp, PID: 7298 java.lang.StackOverflowError: stack size 8188KB at com.myapp.bleApp.hardware.bluetooth.bleScanner.BleScanCallback.onScanFailed(BleScanCallback.kt:237)

And this is where the error is happening in my bleScanCallback class at onScanFailed(errorCode)


    override fun onScanFailed(errorCode: Int) {
        super.onScanFailed(errorCode)
        // Handle scan failure
        onScanFailed(errorCode)
    }

The only thing i want to happen right now is that the service stays alive when the app is in the background and I want to see the notification appear in the status bar. How can I solve this?


Solution

  • This is very meta! The issue is that this function is calling itself recursively, which causes the StackOverflowError.

        override fun onScanFailed(errorCode: Int) {
            super.onScanFailed(errorCode)
            // Handle scan failure
            onScanFailed(errorCode) // Do you really want to call recursively?
        }