Kotlin (Flutter)- Remove Sticky notification for background service

Viewed 519

I'm building an app that does some processing in the background.

This is my code:-

@RequiresApi(Build.VERSION_CODES.N)
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
    
    Intent notificationIntent = new Intent();

    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    Notification notification = new NotificationCompat.Builder(this)
         .setSmallIcon(R.mipmap.ic_launcher)
         .setContentTitle(getString(R.string.app_name)) 
         .setContentText("Welcome To TestApp") 
         .setContentIntent(pendingIntent).build();
    
    // startForeground(105, builder.setNotificationSilent().build())

    // Handler
    eventLoop = object : Runnable {
        override fun run() {
            println("Inside Run.") // does not prints when `startForeground` is commented, and the code is broken.
            handler.postDelayed(this, 1000) // Subsequent runs
        }
    }
    CoroutineScope(IO).launch {
        handler.post(eventLoop) // first launch
    }

    return START_STICKY
}

The above code works fine when startForeground is not commented. This is the function that brings up the sticky notification. I read about it in the docs and by the looks of it, I'm ok if my service is killed to reclaim more memory. I've my work manager set which automatically starts the service if killed.

However, when I comment it, the code breaks. The run function is not executed upon moving the app to the background or killing it or even if the notification bar is pulled down.

This is the exception which is thrown.

I/in.zoffers(20132): Wrote stack traces to tombstoned
F/crash_dump64(21223): crash_dump.cpp:465] failed to attach to thread 567: Permission denied
D/AndroidRuntime(20132): Shutting down VM
E/AndroidRuntime(20132): FATAL EXCEPTION: main
E/AndroidRuntime(20132): Process: in.zoffers, PID: 20132
E/AndroidRuntime(20132): android.app.RemoteServiceException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{737e848 u0 in.zoffers/.AutoOffersService}
E/AndroidRuntime(20132):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2151)
E/AndroidRuntime(20132):    at android.os.Handler.dispatchMessage(Handler.java:107)
E/AndroidRuntime(20132):    at android.os.Looper.loop(Looper.java:228)
E/AndroidRuntime(20132):    at android.app.ActivityThread.main(ActivityThread.java:7782)
E/AndroidRuntime(20132):    at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(20132):    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
E/AndroidRuntime(20132):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:981)
W/MixpanelAPI.SysInfo(20132): Permission READ_PHONE_STATE not granted. Property $radio will not be available.
Lost connection to device.

What exactly is happening here?? Since, I'm ok with my service being killed upon memory management, I don't need startForeground.

1 Answers

I read about it in the docs and by the looks of it, I'm ok if my service is killed to reclaim more memory

It will be killed in 60 seconds on Android 8.0+, unless you make it a foreground service with startForeground().

What exactly is happening here?

You called startForegroundService() to start the service. This means that you are required to call startForeground() within the ANR time period (~15 seconds IIRC). If you do not want to call startForeground(), do not use startForegroundService() to start the service.

Related