1

Why calling context.stopService(stopIntent) is going to execute onStartCommand am i missing something? i had to do this in the onStartCommand

if (ACTION_STOP_SERVICE == intent?.action) { stopSelf() }

While the doc said specifically this:

onStartCommand Called by the system every time a client explicitly starts the service by calling Context.startService

The code sample

@AndroidEntryPoint
class MyService : Service() {

    private val ACTION_STOP_SERVICE: String = "ACTION_STOP_SERVICE"
    private val ACTION_START_SERVICE: String = "ACTION_START_SERVICE"

    @OptIn(InternalCoroutinesApi::class)
    @ExperimentalCoroutinesApi
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

        if (ACTION_START_SERVICE == intent?.action) {
            // Start mqtt client "org.eclipse.paho:org.eclipse.paho.client"
        }

        if (ACTION_STOP_SERVICE == intent?.action) {
            mqtt.disconnect()
            stopSelf()
        }        
        val stopIntent = Intent(this.applicationContext, BPSMqttService::class.java)
        stopIntent.action = ACTION_STOP_SERVICE

        val pStopIntent =
            PendingIntent.getService(
                BPSApp.instance.applicationContext,
                0,
                stopIntent,
                PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
            )
        val notificationIntent =
            Intent(this.applicationContext, MainActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(
            this.applicationContext,
            0, notificationIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )

        val notification =
            NotificationCompat.Builder(this.applicationContext, SERVICE_CHANNEL_ID)
                .setContentTitle("My service")
                .setContentText(input)
                .setSmallIcon(R.drawable.ic_alarms_sync)
                .setContentIntent(pendingIntent)
                .addAction(0, "Stop", pStopIntent)
                .build()
        startForeground(1, notification)
        return START_STICKY
    }

    override fun onDestroy() {
        try {
            super.onDestroy()
            Log.d("MyService ", "onDestroy is done")
        } catch (ex: Throwable) {
            Log.d("MyService ", "onDestroy ${ex.message}")
        }
    }

    override fun onCreate() {
        try {
            super.onCreate()
            Log.d("MyService ", "nCreate is done")
        } catch (ex: Throwable) {
            Log.d("MyService ", "onCreate ${ex.message}")
        }
    }
    
    override fun onBind(intent: Intent?): IBinder? {
        return null
    }
}

And in other places other than the notification i am doing this to stop

val stopIntent = Intent(BPSApp.instance.applicationContext, BPSMqttService::class.java)
stopIntent.action = "ACTION_STOP_SERVICE"
BPSApp.instance.applicationContext.stopService(stopIntent)

And doing this to start

val startIntent = Intent(BPSApp.instance.applicationContext, BPSMqttService::class.java)
startIntent.action = "ACTION_START_SERVICE"
BPSApp.instance.applicationContext.startForegroundService(startIntent);
Hak
  • 69
  • 8
  • Makes no sense. The only thing I can think of is that your `Service` is crashing when stopped, which causes Android to restart your `Service`. Please add logging to `onDestroy()` and `onCreate()` in your `Service` and see what happens when you call `stopService()`. – David Wasser Apr 11 '22 at 17:25
  • Also, `ACTION_STOP_SERVICE` is not defined in the Android framework. It sounds to me like you may be using some middleware or something that is generating the call to `startService()` using ACTION_STOP_SERVICE`. – David Wasser Apr 11 '22 at 17:28
  • Tested and both onCreate and onDestroy worked as expected, ACTION_STOP_SERVICE is just a constant to use as the stop action ID, When you create a service you define at least two actions one for the start and another for the stop. – Hak Apr 21 '22 at 08:29
  • Sorry, still makes no sense. Your statement about creating actions for start and stop also make no sense. This is not standard Android behaviour, maybe post your code so we can see what you are doing. Maybe add logging to `startService()` so that it logs the stack trace and maybe you can see where this call is coming from. – David Wasser Apr 21 '22 at 08:49
  • @DavidWasser Can you provide an example, link, documentation to demonstrate what you mean with standard?! as you can see i provided the DOCs in my question i except a reference showing me what i missed. you know standard is not always expected or makes sense. – Hak Apr 21 '22 at 08:50
  • There are hundreds of howtos and examples of how to build Android `Service` on the Internet, and none of them use these ACTIONs. Please also post the code that shows how you actually use this `Service` (how to start the service and how to stop it). – David Wasser Apr 21 '22 at 09:48
  • Based on what I see, I don't believe that you are actually calling `stopService()` to stop your `Service`. I can only assume that you are actually calling `startService()` and passing an `Intent` that contains `ACTION_STOP_SERVICE`. Please look at your code again. – David Wasser Apr 21 '22 at 09:50
  • The code sample is updated and i am calling stopService(). – Hak Apr 21 '22 at 10:35
  • The notification action "stop" will call `startService()`, so that's what you are seeing. In the other places in the code, when you call `stopService()`, `onStartCommand()` will not be called. – David Wasser Apr 21 '22 at 10:41
  • Also, in one place in the code you are using `BPSMqttService` as your `Service`, in another place you have `MyService`. Is this a typo? Are they actually different? Or the same? – David Wasser Apr 21 '22 at 10:45
  • Dose it make more sense for you now?!, thanks for the hard earned input. – Hak Apr 21 '22 at 10:46
  • Another thing, if you call `startForegroundService()` to start your `Service`, your `Service` **must call `startForeground()` inside `onStartCommand()`**, which your code does not do. – David Wasser Apr 21 '22 at 10:47
  • It dose on the last line :) – Hak Apr 21 '22 at 10:48
  • You call `return START_STICKY` in the middle of that method. No code after that will get executed. Please check. – David Wasser Apr 21 '22 at 10:49
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/244078/discussion-between-hak-and-david-wasser). – Hak Apr 21 '22 at 11:12

1 Answers1

1

It looks like you are seeing onStartCommand() being called as a result of your Notification.

The notification action "stop" will call startService(), so that's what you are seeing. In the other places in the code, when you call stopService(), onStartCommand() will not be called.

David Wasser
  • 93,459
  • 16
  • 209
  • 274