当服务被系统自动杀死时取消Android个通知
Cancelling Android notifications when the service is automatically killed by the system
我有一个实现 MediaBrowserServiceCompat
的应用程序。播放音乐时,它在前台运行,并带有系统不可关闭的媒体控制通知。暂停时,它从前台出来,并保留通知。标准的东西。
当此服务被系统自动杀死时,通知并没有被移除。
您可以通过将应用程序置于非前台暂停状态、离开应用程序并发出以下命令来模拟此情况:
adb shell am kill com.myapp.package
通知仍然存在。您收到此 Logcat 消息:
W/ActivityManager: Scheduling restart of crashed service com.myapp.package/com.myapp.package.playback.platform.AndroidMediaService
None 服务上明显的钩子(例如 onDestroy
、onTaskRemoved
等)似乎被调用了——它似乎被彻底杀死了。因为服务是从 START_NOT_STICKY
开始的,所以我们也不会在新实例上调用 onCreate
。
对此的部分解决方案是使服务具有粘性,并在服务 恢复时取消通知。然而,这可能需要很长时间才能真正发生,在此期间通知不起作用,因此并不理想。它还可能产生进一步的后果。
其他应用程序似乎对此没有问题。
重复此场景(暂停、离开应用)并执行命令,例如 Google 播放音乐:
adb shell am kill com.google.android.music
或 Spotify:
adb shell am kill com.spotify.music
并且您发现他们的通知立即消失,就好像它们在拆卸时被取消一样。
他们可能会做些什么来实现这一目标?
尝试在清单中添加此标志以在应用程序被终止时停止服务:
<service
...
android:stopWithTask="true"/>
如果它没有删除通知,将其设置为 false 应该会在服务中触发回调,您应该可以在其中删除通知
@Override
public void onTaskRemoved(Intent rootIntent) {
...
}
此外,这 answer 可能是相关的。
更新
由于上述方法无效,我查看了清单中如何声明本机音乐应用程序,但他们没有使用我建议的方法。
他们使用的,可能相关的是
<service
...
android:process=":main" />
在所有服务中以及在更改通知的接收器中。
值得一试。
我已经找到了答案,当然,这是我自己的错。其他应用程序没有做任何特别的事情 - 这是一种平台行为,我们是异常值。
我后来发现,当从前景过渡到背景时,我们调用:
ServiceCompat.stopForeground(service, ServiceCompat.STOP_FOREGROUND_DETACH)
我通过 dumpsys
发现了这个,例如:
adb shell dumpsys activity services com.google.android.music
我发现了一些不同。
我的应用程序:
ServiceRecord{294309d u0 com.myapp.debug/com.myapp.playback.platform.AndroidMediaService}
intent={cmp=com.myapp.debug/com.myapp.playback.platform.AndroidMediaService}
packageName=com.myapp.debug
processName=com.myapp.debug:main
baseDir=/data/app/com.myapp.debug-GM-nBaeXA_e47EmJKnM27g==/base.apk
dataDir=/data/user/0/com.myapp.debug
app=ProcessRecord{83fb4ffd0 23567:com.myapp.debug:main/u0a381}
createTime=-27s211ms startingBgTimeout=--
lastActivity=-26s911ms restartTime=-27s211ms createdFromFg=true
startRequested=true delayedStop=false stopIfKilled=true callStart=true lastStartId=2
播放音乐:
ServiceRecord{8693ccb u0 com.google.android.music/.playback2.MusicPlaybackService}
intent={cmp=com.google.android.music/.playback2.MusicPlaybackService}
packageName=com.google.android.music
processName=com.google.android.music:main
baseDir=/data/app/com.google.android.music-lrn1VQr_3_RDi5PMbqozdw==/base.apk
dataDir=/data/user/0/com.google.android.music
app=ProcessRecord{9a3c417d0 22921:com.google.android.music:main/u0a191}
isForeground=false foregroundId=1 foregroundNoti=Notification(channel=playback_v1 pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x2 color=0xffff5722 category=transport actions=5 vis=PUBLIC semFlags=0x0 semPriority=0 semMissedCount=0)
createTime=-9m33s792ms startingBgTimeout=--
lastActivity=-20s825ms restartTime=-9m33s792ms createdFromFg=true
startRequested=true delayedStop=false stopIfKilled=false callStart=true lastStartId=1
您可以在我的应用程序日志中看到缺少的 foregroundNoti
属性。这是分离调用的产物。我们选择在很久以前的某个时候这样做是为了避免通知被系统收集。经过反思,我们应该允许它像其他应用程序一样被杀死。
你应该设置通知的优先级"LOW"并且在服务销毁方法中你可以通过下面的代码手动删除通知,
notificationManager.cancelAll();
我有一个实现 MediaBrowserServiceCompat
的应用程序。播放音乐时,它在前台运行,并带有系统不可关闭的媒体控制通知。暂停时,它从前台出来,并保留通知。标准的东西。
当此服务被系统自动杀死时,通知并没有被移除。
您可以通过将应用程序置于非前台暂停状态、离开应用程序并发出以下命令来模拟此情况:
adb shell am kill com.myapp.package
通知仍然存在。您收到此 Logcat 消息:
W/ActivityManager: Scheduling restart of crashed service com.myapp.package/com.myapp.package.playback.platform.AndroidMediaService
None 服务上明显的钩子(例如 onDestroy
、onTaskRemoved
等)似乎被调用了——它似乎被彻底杀死了。因为服务是从 START_NOT_STICKY
开始的,所以我们也不会在新实例上调用 onCreate
。
对此的部分解决方案是使服务具有粘性,并在服务 恢复时取消通知。然而,这可能需要很长时间才能真正发生,在此期间通知不起作用,因此并不理想。它还可能产生进一步的后果。
其他应用程序似乎对此没有问题。
重复此场景(暂停、离开应用)并执行命令,例如 Google 播放音乐:
adb shell am kill com.google.android.music
或 Spotify:
adb shell am kill com.spotify.music
并且您发现他们的通知立即消失,就好像它们在拆卸时被取消一样。
他们可能会做些什么来实现这一目标?
尝试在清单中添加此标志以在应用程序被终止时停止服务:
<service
...
android:stopWithTask="true"/>
如果它没有删除通知,将其设置为 false 应该会在服务中触发回调,您应该可以在其中删除通知
@Override
public void onTaskRemoved(Intent rootIntent) {
...
}
此外,这 answer 可能是相关的。
更新
由于上述方法无效,我查看了清单中如何声明本机音乐应用程序,但他们没有使用我建议的方法。 他们使用的,可能相关的是
<service
...
android:process=":main" />
在所有服务中以及在更改通知的接收器中。 值得一试。
我已经找到了答案,当然,这是我自己的错。其他应用程序没有做任何特别的事情 - 这是一种平台行为,我们是异常值。
我后来发现,当从前景过渡到背景时,我们调用:
ServiceCompat.stopForeground(service, ServiceCompat.STOP_FOREGROUND_DETACH)
我通过 dumpsys
发现了这个,例如:
adb shell dumpsys activity services com.google.android.music
我发现了一些不同。
我的应用程序:
ServiceRecord{294309d u0 com.myapp.debug/com.myapp.playback.platform.AndroidMediaService}
intent={cmp=com.myapp.debug/com.myapp.playback.platform.AndroidMediaService}
packageName=com.myapp.debug
processName=com.myapp.debug:main
baseDir=/data/app/com.myapp.debug-GM-nBaeXA_e47EmJKnM27g==/base.apk
dataDir=/data/user/0/com.myapp.debug
app=ProcessRecord{83fb4ffd0 23567:com.myapp.debug:main/u0a381}
createTime=-27s211ms startingBgTimeout=--
lastActivity=-26s911ms restartTime=-27s211ms createdFromFg=true
startRequested=true delayedStop=false stopIfKilled=true callStart=true lastStartId=2
播放音乐:
ServiceRecord{8693ccb u0 com.google.android.music/.playback2.MusicPlaybackService}
intent={cmp=com.google.android.music/.playback2.MusicPlaybackService}
packageName=com.google.android.music
processName=com.google.android.music:main
baseDir=/data/app/com.google.android.music-lrn1VQr_3_RDi5PMbqozdw==/base.apk
dataDir=/data/user/0/com.google.android.music
app=ProcessRecord{9a3c417d0 22921:com.google.android.music:main/u0a191}
isForeground=false foregroundId=1 foregroundNoti=Notification(channel=playback_v1 pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x2 color=0xffff5722 category=transport actions=5 vis=PUBLIC semFlags=0x0 semPriority=0 semMissedCount=0)
createTime=-9m33s792ms startingBgTimeout=--
lastActivity=-20s825ms restartTime=-9m33s792ms createdFromFg=true
startRequested=true delayedStop=false stopIfKilled=false callStart=true lastStartId=1
您可以在我的应用程序日志中看到缺少的 foregroundNoti
属性。这是分离调用的产物。我们选择在很久以前的某个时候这样做是为了避免通知被系统收集。经过反思,我们应该允许它像其他应用程序一样被杀死。
你应该设置通知的优先级"LOW"并且在服务销毁方法中你可以通过下面的代码手动删除通知,
notificationManager.cancelAll();