我目前正在使用 Media3 库来播放内容,当应用程序位于前台时触发 mediaController.play() 时,一切都运行良好。
**用例:** 播放列表中的曲目没有 mediaUri(指向实际 .mp3 的链接)。我们需要获取一个播放列表(假设有 30 个曲目),然后获取每个给定曲目的 url。问题是我们收到的网址只有 2 分钟有效。
**我们现在使用的解决方案是:** 我们有一个工作类,它观察(通过流)播放器状态,当 STATE_ENDED 时,它获取下一首曲目的 url 并播放它 (mediaController.setMediaItems >prepare() > play())
问题: 当应用程序处于后台(屏幕关闭)并且曲目结束时,新曲目开始播放,但我们收到 ForegroundServiceStartNotAllowedException 错误(没有崩溃),并且媒体通知图像不会更新。
Failed to start foreground android.app.ForegroundServiceStartNotAllowedException: Service.startForeground() not allowed due to mAllowStartForeground false: service 'APPNAME.media.MediaService
我是否遗漏了一些明显的东西,或者 Media3 仍然无法处理这些我们需要按需获取 mediaUri 的情况
MediaLibraryService 已使用给定权限正确设置:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application>...
<service
android:name=".MediaService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="mediaPlayback|dataSync">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService" />
<action android:name="android.media.browse.MediaBrowserService" />
</intent-filter>
</service>
</application>
这是被调用来播放内容的函数:
private fun playAppPlaylist(startAtIndex: Int = 0) {
val browser = this.browser ?: return
val items = browser.getChildren(
Catalog.AppPlaylist.path, 0, Int.MAX_VALUE, null
)
items.addListener({
val result = items.get()
val children = result.value!!
browser.setMediaItems(children)
browser.prepare()
if (startAtIndex != 0) browser.seekTo(startAtIndex, 0)
else browser.seekToDefaultPosition()
browser.play()
}, MoreExecutors.directExecutor())
}
似乎当应用程序不在前台时调用
browser.play()
会触发导致错误的notificationChange。
我尝试过考虑不使用 .play() 而是使用 controller.replaceMediaItem()
的解决方案,但媒体不会开始播放,因为它在变为 Player.STATE_ENDED
时已暂停
从 Android 12 开始,每当您的应用程序处于后台时,启动前台服务变得更加困难。
根据这个答案,您可能需要传入
FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
作为 startForeGround(..)
调用的第三个参数(您提供的代码中未显示该参数。
进一步查看您提供的代码,我怀疑将
dataSync
标志作为 foregroundServiceType
声明的一部分可能会让 Android 认为您不应该从后台执行任何操作,但您必须尝试这样做自己出去吧!