首页 > 解决方案 > 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,或者有没有其他方法可以解决这个问题?

谢谢!

标签: androidandroid-automediabrowserservice

解决方案


可能您必须将大数据分成小块。例如,您有一个包含 5000 个项目的列表。所以在你里面MediaBrowserServiceonLoadChildren这样的事情

 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)
}
 

我没有检查这段代码,但我认为这个想法很清楚。


推荐阅读