javamedia-playerandroid-auto

Android Auto app doesn't call onPlay, and no album art appears


I wrote an mp3 player (called DJ) and I want to add compatibility with Android Auto. I wrote the service and everything seems to work, except no album art appears on the Windows Desktop Head Unit, and no sound plays (doesn't even call onPlay). Clicking on a song in the head unit, it displays "Getting your selection..." - then seems to hang there. Should there be a play button? enter image description hereenter image description here

The songs are in an ArrayList called songItemList. Here's the code creating the MediaItems. I confirm that the album art file exists, then do Uri.parse on the file path. I also tried a fromFile with the same result. I do the same thing for the mp3 file. I must be missing something.

for (SongItem songItem:songItemList) {
    String id = SONG + "_" + songItem.getTrackid();
    Uri uri = null;
    Uri mediaUri = null;
    if (songItem.getArtLocation() != null) {
        File f = new File(songItem.getArtLocation());
        if (f.exists()) {
            //uri = Uri.fromFile(f);
            uri = Uri.parse(songItem.getArtLocation());
        } else {
            Log.d(TAG,"File doesn't exist:" + songItem.getArtLocation());
        }
        f = new File(songItem.getLocation());
        if (f.exists()) {
            //mediaUri = Uri.fromFile(f);
            mediaUri = Uri.parse(songItem.getLocation());
        } else {
            Log.d(TAG, "File doesn't exist: " + songItem.getLocation());
        }
    }
    Bundle extras = new Bundle();
    MediaBrowserCompat.MediaItem item =
            new MediaBrowserCompat.MediaItem(descBuilder.setMediaId(id)
                    .setDescription(songItem.getName())
                    .setSubtitle(songItem.getArtist())
                    .setIconUri(uri)
                    .setMediaUri(mediaUri)
                    .setMediaId(id)
                    .setTitle(songItem.getName())
                    .setExtras(extras)
                    .build(),MediaBrowserCompat.MediaItem.FLAG_PLAYABLE);
    mediaItems.add(item);
}

saveResult.sendResult(mediaItems);

Additional info: When I use the Uri.parse, I get uri's like this:

/data/data/com.emrick.dj/albumart/Judy Collins/Fires Of Eden/Fires Of Eden.jpg /data/data/com.emrick.dj/audio/Judy Collins/Fires Of Eden/From A Distance.mp3

When I use the Uri.fromFile call, I get uri's like this: file:///data/data/com.emrick.dj/albumart/Judy%20Collins/Fires%20Of%20Eden/Fires%20Of%20Eden.jpg file:///data/data/com.emrick.dj/audio/Judy%20Collins/Fires%20Of%20Eden/From%20A%20Distance.mp3

Also, running the mp3 player app (that this is based on) on my phone, I see all the album art and the mp3 files play, so I believe my music database is good.

Update: I tried using .setIconBitmap instead of .setIconUri, creating a bitmap instead of a Uri for the album art. If I limit the number of songs to 200 or less, then the album art appears. Somewhere between 200 and 390 songs apparently causes a problem, the head unit spins for a few seconds and then says the app isn't working. Then I tried going back to the .setIconUri and limited the songs to 200, that still doesn't work (gives blank album art like below). Still hangs on "Getting your selection...." if I click on a song.

Update (answer from Ben Sagmoe)

I'll put my follow up questions here - they don't show up well as a comment. Still not clear about implementing/accessing the ContentProvider.

I tried this: using uri = Uri.parse("content://" + songItem.getArtLocation()); uri = albumArtContent(uri);

public static Uri albumArtContent(Uri uri) {
        String path = uri.getEncodedPath() != null ? uri.getEncodedPath().substring(1).replace('/', ':') : Uri.EMPTY.toString();

        Uri contentUri = new Uri.Builder()
                .scheme(ContentResolver.SCHEME_CONTENT)
                .authority("com.emrick.dj")
                .path(path)
                .build();

        return contentUri;
    }

Still not working. Do I need to create a class that extends ContentProvider? I don't see any methods that return a Uri in the required methods for ContentProvider though... openFile and copy look promising, but how do I get a Uri from either of those?


Solution

  • For the album art to load using setIconUri, you need to implement a ContentProvider for the files to actually be loaded by Android Auto.

    What your code is currently doing is validating that the file exists and telling Android Auto what the location is. But it ultimately doesn't actually load the file and provide it to Android Auto. See Content provider basics for more details on how content providers work and why they're used.

    As you discovered, you could use setIconBitmap, which includes the full images in the serialized media items sent in sendResult. But, as you noticed, this breaks at a certain point, because of Android's 1MB binder size limit.

    As far as playing the mp3 files goes, that's generally handled using something like ExoPlayer. To allow Android Auto to control your player (e.g. to handle play/pause commands from the user), you need to expose control via MediaSession.