5

I am currently trying to implement a MediaBrowserService to build a media app for Android Auto. I followed the official Android Auto documentation (https://developer.android.com/training/cars/media#onLoadChildren) to implement theonLoadChildren function.

Following is a code snippet that I tried to show the content on the Android Auto screen:

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

This works pretty well, when the number of items is small enough. However, when the number of items is large (e.g., about 5,000 items), the following error appears:

E/JavaBinder: !!! FAILED BINDER TRANSACTION !!!  (parcel size = 1339384)

I found that several other media apps (e.g., Samsung Music) that support Android Auto can show a large number of items. Is there any way to return a large number of items on the onLoadChildren function, or is there any other way to solve this issue?

Thanks!

idearibosome
  • 684
  • 1
  • 7
  • 17
  • HI. I faced with the same problem. Have you found any solution? – Dmitriy Mitiai Apr 14 '21 at 14:45
  • @DmitriyMiyai Oh you are on the same boat... I couldn't find any solution for this, so I started a bounty for this question. – idearibosome Apr 19 '21 at 16:58
  • 1
    I found why this happens - because of Android limits of sending the data in intents(1 Mb or around this). When you call `result.sendResult(items)` it sends the intent to show the data in AA. The solution, which I came to is just split the content to small parts. For example, if you have 5000 items, divide them with 50 parts and call it Part 1 - Part 50. Each part will contain 100 items. This is not ideal, but it was the best trick for me. – Dmitriy Mitiai Apr 20 '21 at 05:56
  • @DmitriyMiyai Yes, it is because of the size limit of the Android's bundles. But how did you combine those splits into a single list on the Android Auto screen? Or did you show each part separately on the screen? – idearibosome Apr 20 '21 at 15:26
  • Please see my example. Hope you'll find it useful for your case – Dmitriy Mitiai Apr 21 '21 at 08:29
  • Did you find an answer, @idearibosome? Going through this myself. – bernardo.g Jul 06 '21 at 13:33

2 Answers2

-1

Probably you have to split the large data into a small pieces. For example, you have a list of 5000 items. So inside you MediaBrowserService in onLoadChildren do something like this

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

I didn't check this code, but I think the idea is clear.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Dmitriy Mitiai
  • 1,112
  • 12
  • 15
  • 2
    This can be a workaround, but it shows the "Part 1", "Part 2", ... page first and the user has to look all parts menu to find a media item that the user wants to play. As I mentioned in the question, there are some Android Auto apps that supports showing more than 1000 items without any error. – idearibosome Apr 26 '21 at 10:15
  • 1
    So I think there should be a way to solve this issue without splitting data into several chunks... – idearibosome Apr 26 '21 at 10:16
  • This does not solve the problem as asked. User wants one scrolling list. – w0mbat Dec 20 '22 at 20:59
-1

If you look into Android SDK document:

Note: Android Auto and Android Automotive OS have strict limits on how many media items they can display in each level of the menu. These limits minimize distractions for drivers and help them operate your app with voice commands. ...

So, I think the best approach is to limit # of media items in UX design. For what you saw from the other apps working with lots of media items, they might used Jetpack Media 2 for pagination.

Wonil
  • 6,364
  • 2
  • 37
  • 55
  • 1
    The limit that Android is mentioning is max 4 tabs in navigation row. – Starwave Jun 07 '22 at 07:05
  • This answer is irrelevant. The UI limit is not what is being encountered here, it's the limited size of the Android IPC buffer. – w0mbat Mar 18 '23 at 20:30