LibreShift / red-moon

Android screen filter app for night time phone use.
GNU General Public License v3.0
642 stars 80 forks source link

fix crash when starting FilterService from a quick setting tile #285

Closed gilbsgilbs closed 3 years ago

gilbsgilbs commented 3 years ago

When launching FilterService from a quick setting tile with Red Moon shut, the service would fail to start on recent Android versions with the following traceback:

02-17 10:26:47.938  1442  2008 W ActivityManager: Background start not allowed: service Intent { cmp=com.jmstudios.redmoon/.filter.FilterService (has extras) } to com.jmstudios.redmoon/.filter.FilterService from pid=18936 uid=10077 pkg=com.jmstudios.redmoon startFg?=false
02-17 10:26:47.939 18936 18936 D AndroidRuntime: Shutting down VM
02-17 10:26:47.940 18936 18936 E AndroidRuntime: FATAL EXCEPTION: main
02-17 10:26:47.940 18936 18936 E AndroidRuntime: Process: com.jmstudios.redmoon, PID: 18936
02-17 10:26:47.940 18936 18936 E AndroidRuntime: java.lang.IllegalStateException: Not allowed to start service Intent { cmp=com.jmstudios.redmoon/.filter.FilterService (has extras) }: app is in background uid UidRecord{69dcdfc u0a77 CEM  idle change:cached procs:1 seq(0,0,0)}
02-17 10:26:47.940 18936 18936 E AndroidRuntime:    at android.app.ContextImpl.startServiceCommon(ContextImpl.java:1715)
02-17 10:26:47.940 18936 18936 E AndroidRuntime:    at android.app.ContextImpl.startService(ContextImpl.java:1670)
02-17 10:26:47.940 18936 18936 E AndroidRuntime:    at android.content.ContextWrapper.startService(ContextWrapper.java:720)
02-17 10:26:47.940 18936 18936 E AndroidRuntime:    at com.jmstudios.redmoon.filter.Command.send(Command.kt:71)
02-17 10:26:47.940 18936 18936 E AndroidRuntime:    at com.jmstudios.redmoon.filter.Command$Companion.toggle(Command.kt:94)
02-17 10:26:47.940 18936 18936 E AndroidRuntime:    at com.jmstudios.redmoon.widget.TileReceiver.onClick(TileReceiver.kt:27)
02-17 10:26:47.940 18936 18936 E AndroidRuntime:    at android.service.quicksettings.TileService$H.handleMessage(TileService.java:449)
02-17 10:26:47.940 18936 18936 E AndroidRuntime:    at android.os.Handler.dispatchMessage(Handler.java:106)
02-17 10:26:47.940 18936 18936 E AndroidRuntime:    at android.os.Looper.loop(Looper.java:223)
02-17 10:26:47.940 18936 18936 E AndroidRuntime:    at android.app.ActivityThread.main(ActivityThread.java:7660)
02-17 10:26:47.940 18936 18936 E AndroidRuntime:    at java.lang.reflect.Method.invoke(Native Method)
02-17 10:26:47.940 18936 18936 E AndroidRuntime:    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
02-17 10:26:47.940 18936 18936 E AndroidRuntime:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

This is because recent versions of Android disallow starting a foreground services using startService directly. You have to use startForegroundService and ensure the started service calls startForeground 5 seconds at most after the service is started. This behavior change is documented here.

Let me know if you think any improvement should be made.

gilbsgilbs commented 3 years ago

Thanks @smichel17 for the fast review.

We already call startForeground, so we're good on that front.

Yup, I double checked that. It's required anyways if we want the service to display something I guess.

It looks like starting with targeting Android 9.0, there's an additional permission we'll need to request, and in Android 10 it'll have to go in the manifest — https://developer.android.com/reference/android/app/Service#startForeground(int,%20android.app.Notification)

That's good catch, but unless I'm missing something, the permission is already requested in the manifest. Red Moon already targets API 29 (Android 10), so it wouldn't work otherwise.

smichel17 commented 3 years ago

Ha, you're right. I guess I haven't done much in the red moon code base for a while 😅