android - 如何在 Spotify 和 Google Music 等后台播放音乐时让通知消失
问题描述
Spotify 和谷歌音乐允许用户在后台播放音乐,也允许媒体通知被关闭。当您将这些应用程序之一移至后台,然后暂停播放时,您可以关闭媒体通知。但是,如果您不关闭通知,使其长时间处于暂停状态,系统不会终止“音频服务”,因为通知始终可见并立即对播放/暂停做出反应。
据我所知,不可能使用前台服务来关闭通知,我们需要调用 stopForeground(false),这会让系统终止服务。
这是我们现在在我们的应用程序中的操作方式:
开始播放时,我们使用以下代码将 MusicService 作为前台服务运行:
startForeground(mediaNotification)
然后,当用户离开应用程序时,他可以通过媒体通知控制播放。由于通知与 MusicService 紧密耦合,用户将无法关闭它,直到我们调用:
stopForeground(false)
这就是我们在用户按下暂停按钮时调用此方法的原因。但是,这会产生一个服务背景,因此系统会在短时间内将其杀死。
Spotify 和 Google Music 如何解决这个问题?实现它的方法是什么?
解决方案
结合 Pouya 的回答和一些独立研究,我有一个代码片段,其行为与使用 OOTB MediaPlayer 的 Spotify 等应用程序相当接近。可能有一个更优雅的解决方案,但这是快速而肮脏的版本 - 我有太多代码要发布,所以有一个概述:
当媒体播放器暂停时,我运行两段代码。首先,在更新通知栏后,我将其从前台服务降级为后台服务:
public void demoteNotifyBar() {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
stopForeground(STOP_FOREGROUND_DETACH);
else
stopForeground(false);
}
然后我启动一个新的计时器,它每秒重新制作一次通知栏:
// Put this in the onCreate method
pauseRefresh = new Runnable() {
@Override
public void run() {
// Check if media is playing to prevent race conditions
if (!isPlaying()) {
startForeground(FOREGROUND_SERVICE, notification);
demoteNotifyBar();
handler.postDelayed(pauseRefresh, 1000);
}
}
};
// Call this wherever you're handling the pause button
pauseRefresh.run();
要取消自动刷新,您需要在重新制作通知栏并将媒体从暂停切换到播放之前调用这段代码(是的,您可以忽略此切换音频,但请阅读下文了解为什么需要这样做):
handler.removeCallbacks(pauseRefresh);
您还需要监听带有删除意图的滑动关闭,以防止通知在用户关闭时重新生成;只需使用相同的代码来取消用户单击播放时使用的计时器。
推荐阅读
- r - for循环中的锯齿先验
- angular - 我可以像创建 Angular 库一样创建 Ionic 库吗?
- date - 从昨天开始计数和记录,并在 Bigquery、standardSQL 中使用昨天的日期在其旁边添加 datecolumn
- python - Heroku:AttributeError:模块'tensorflow_hub.tf_v1'没有属性'estimator'
- java - 使用Java Spark逐行读取大文本文件
- javascript - 在 Whatsapp 中预览 Smooch 视频
- c++ - c++ 重载 =operator, RAII
- angular - ag-Grid:如何从单元测试中访问 gridApi?
- django - Django:在 init() 中获取 DetailView 的模型
- c++ - 试图了解 .External() 是什么?