在后台使用应用程序播放媒体项目会触发 ForegroundServiceStartNotAllowedException

问题描述 投票:0回答:1

我目前正在使用 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 exoplayer
1个回答
0
投票

从 Android 12 开始,每当您的应用程序处于后台时,启动前台服务变得更加困难。

根据这个答案,您可能需要传入

FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
作为
startForeGround(..)
调用的第三个参数(您提供的代码中未显示该参数。

进一步查看您提供的代码,我怀疑将

dataSync
标志作为
foregroundServiceType
声明的一部分可能会让 Android 认为您不应该从后台执行任何操作,但您必须尝试这样做自己出去吧!

© www.soinside.com 2019 - 2024. All rights reserved.