android - Android Auto:如何在 MediaBrowserService 的 loadChildren() 上返回大量子级?
问题描述
我目前正在尝试实现一个MediaBrowserService
为 Android Auto 构建媒体应用程序。我按照官方的 Android Auto 文档(https://developer.android.com/training/cars/media#onLoadChildren)来实现该onLoadChildren
功能。
以下是我尝试在 Android Auto 屏幕上显示内容的代码片段:
override fun onLoadChildren(parentId: String, result: Result<MutableList<MediaBrowserCompat.MediaItem>>) {
...
if (parentId == NODE_LIBRARY_ALBUMS) {
val items = mutableListOf<MediaBrowserCompat.MediaItem>()
val albumList = LibraryManager.getAlbumList()
for (it in albumList) {
val descriptionBuilder = MediaDescriptionCompat.Builder()
.setTitle(it.albumName)
items.add(MediaBrowserCompat.MediaItem(descriptionBuilder.build(), MediaBrowserCompat.MediaItem.FLAG_BROWSABLE))
}
result.sendResult(items)
}
...
}
当项目数量足够少时,这非常有效。但是,当项目数量很大(例如,大约 5,000 个项目)时,会出现以下错误:
E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 1339384)
我发现其他几个支持 Android Auto 的媒体应用程序(例如三星音乐)可以显示大量项目。有没有办法在函数上返回大量项目onLoadChildren
,或者有没有其他方法可以解决这个问题?
谢谢!
解决方案
可能您必须将大数据分成小块。例如,您有一个包含 5000 个项目的列表。所以在你里面MediaBrowserService
做onLoadChildren
这样的事情
public fun onLoadChildren(parentId: String, result: Result<List<MediaBrowserCompat.MediaItem>>) {
if (MEDIA_ID_ROOT == parentId || itemsList.size > 100) {
fillMediaBrowsableResult(parentId, result);
}
else {
fillMediaPlayableResult(parentId, result);
}
}
//Split the large number of content to a parts
private fun fillMediaBrowsableResult(parentId: String, result: Result<List<MediaBrowserCompat.MediaItem>>) {
// Detect count of parts
val partsCount = itemsList.size / 100
if(itemsList.size % 100 > 0){
partsCount ++
}
val mediaItems = mutableListOf<MediaBrowserCompat.MediaItem>()
//Create parts in a loop
for(i in 0 until partsCount){
val mediaDescription = MediaDescriptionCompat.Builder()
.setMediaId(i) // This is your next parent in onLoadChildren when you click on it in AA
.setTitle("Part ${i + 1}")
.build();
val mediaItem =. MediaBrowserCompat.MediaItem(mediaDescription, MediaBrowserCompat.MediaItem.FLAG_BROWSABLE)
mediaItems.add(mediaItem)
}
result.sendResult(mediaItems)
}
private fun fillMediaPlayableResult(parentId: String, result: Result<List<MediaBrowserCompat.MediaItem>>){
val intParent = parentId.toInt()
val startPosition = intParent * 100 // where to start for this part
val stopPosition = (intParent + 1) * 100 // where to finish for this part
if(stopPosition > itemsList.size){
stopPosition = itemsList.size
}
val mediaItems = mutableListOf<MediaBrowserCompat.MediaItem>()
for(i in startPosition..stopPosition){
//Generate playable content for this part
val item = itemsList[i]
val mediaDescription = MediaDescriptionCompat.Builder()
.setMediaId(item.id)
.setTitle(item.albumTitle)
.build();
val mediaItem =. MediaBrowserCompat.MediaItem(mediaDescription, MediaBrowserCompat.MediaItem.FLAG_PLAYABLE)
mediaItems.add(mediaItem)
}
result.sendResult(mediaItems)
}
我没有检查这段代码,但我认为这个想法很清楚。
推荐阅读
- c++ - 使用带有 boost asio 的光纤时 boost::fiber::yield 和 boost::fiber:sleep_for 之间的区别
- node.js - Nodejs密码重置我收到一个电子邮件并单击链接,但新密码没有改变。我只能用旧密码登录
- typescript - 在打字稿的自定义搜索栏组件中使用handleTextChange,谷歌自动完成
- r - 固定时间序列的 ARMA 模型预测,固定长度错误
- c# - C# 中定义的 Enumerable.Where 方法的参数在哪里?
- vue.js - 惯性 + vuejs 和 laravel 搜索框未捕获(承诺)TypeError
- c# - 使用 Http 请求 Rest API 失败,出现 401,但 Https 有效
- rust - Rust image::io::Reader: Permission Denied
- npm - 如何找到全局 npm 的 package.json?
- c# - 使用 WPF MediaElement 时如何确定是否安装了 Windows Media Player