Yod*_*ltz 5 android kotlin android-mediasession mediabrowserservice mediabrowserservicecompat
TL;DR:我已经成功地创建和耦合(通过订阅)一个活动到媒体浏览器服务。此媒体浏览器服务可以继续运行并在后台播放音乐。我希望能够在某个阶段刷新内容,无论是在应用程序再次出现在前台时还是在 SwipeRefreshLayout 事件期间。
我想实现以下功能:
我收到的问题是在 MediaBrowserService 中(在创建订阅后)您只能从 onLoadChildren() 方法调用 sendResult() 一次,因此下次尝试使用相同的根订阅媒体浏览器服务时,第二次调用 sendResult() 时会出现以下异常:
E/UncaughtException: java.lang.IllegalStateException: sendResult() called when either sendResult() or sendError() had already been called for: MEDIA_ID_ROOT
at android.support.v4.media.MediaBrowserServiceCompat$Result.sendResult(MediaBrowserServiceCompat.java:602)
at com.roostermornings.android.service.MediaService.loadChildrenImpl(MediaService.kt:422)
at com.roostermornings.android.service.MediaService.access$loadChildrenImpl(MediaService.kt:50)
at com.roostermornings.android.service.MediaService$onLoadChildren$1$onSyncFinished$playerEventListener$1.onPlayerStateChanged(MediaService.kt:376)
at com.google.android.exoplayer2.ExoPlayerImpl.handleEvent(ExoPlayerImpl.java:422)
at com.google.android.exoplayer2.ExoPlayerImpl$1.handleMessage(ExoPlayerImpl.java:103)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:150)
at android.app.ActivityThread.main(ActivityThread.java:5665)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:822)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:712)
Run Code Online (Sandbox Code Playgroud)
我调用以下方法来连接和断开媒体浏览器(同样,第一次连接时一切运行顺利,但在第二次连接时,我不确定如何通过订阅刷新内容):
override fun onStart() {
super.onStart()
mMediaBrowser = MediaBrowserCompat(this, ComponentName(this, MediaService::class.java), connectionCallback, null)
if (!mMediaBrowser.isConnected)
mMediaBrowser.connect()
}
override fun onPause() {
super.onPause()
//Unsubscribe and unregister MediaControllerCompat callbacks
MediaControllerCompat.getMediaController(this@DiscoverFragmentActivity)?.unregisterCallback(mediaControllerCallback)
if (mMediaBrowser.isConnected) {
mMediaBrowser.unsubscribe(mMediaBrowser.root, subscriptionCallback)
mMediaBrowser.disconnect()
}
}
Run Code Online (Sandbox Code Playgroud)
我取消订阅并断开 onPause() 而不是 onDestroy() 以便即使活动保留在后台堆栈中也会重新创建订阅。
用于滑动刷新的实际方法,分别在活动和服务中:
活动
if (mMediaBrowser.isConnected)
mMediaController?.sendCommand(MediaService.Companion.CustomCommand.REFRESH.toString(), null, null)
Run Code Online (Sandbox Code Playgroud)
服务
inner class MediaPlaybackPreparer : MediaSessionConnector.PlaybackPreparer {
...
override fun onCommand(command: String?, extras: Bundle?, cb: ResultReceiver?) {
when(command) {
// Refresh media browser content and send result to subscribers
CustomCommand.REFRESH.toString() -> {
notifyChildrenChanged(MEDIA_ID_ROOT)
}
}
}}
Run Code Online (Sandbox Code Playgroud)
其他研究:
我参考了 Github 上的 Google Samples 代码,以及...
在创建媒体浏览器服务并且至少订阅了一次 Activity 之后,上述存储库似乎都没有处理刷新内容的问题- 我想避免重新启动服务,以便音乐可以继续在后台播放。
可能的相关问题:
我的问题与 MediaBrowserServiceCompat 类无关。出现这个问题是因为我调用是result.detach()为了实现一些异步数据获取,而我使用的侦听器将onLoadChildren 方法中的parentId和变量传入并分配为 Final而不是。resultvalvar
我仍然不完全理解为什么会发生这种情况,是否是Player.EventListener在另一个异步网络调用侦听器中使用 a 的潜在结果,但解决方案是创建并分配一个变量(也许其他人可以解释这种现象):
// Create variable
var currentResult: Result<List<MediaBrowserCompat.MediaItem>>? = null
override fun onLoadChildren(parentId: String, result: MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>) {
// Use result.detach to allow calling result.sendResult from another thread
result.detach()
// Assign returned result to temporary variable
currentResult = result
currentParentId = parentId
// Create listener for network call
ChannelManager.onFlagChannelManagerDataListener = object : ChannelManager.Companion.OnFlagChannelManagerDataListener {
override fun onSyncFinished() {
// Create a listener to determine when player is prepared
val playerEventListener = object : Player.EventListener {
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
when(playbackState) {
Player.STATE_READY -> {
if(mPlayerPreparing) {
// Prepare content to send to subscribed content
loadChildrenImpl(currentParentId, currentResult as MediaBrowserServiceCompat.Result<List<MediaBrowserCompat.MediaItem>>)
mPlayerPreparing = false
}
}
...
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2018 次 |
| 最近记录: |