You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android MediaBrowserService音频播放器定制:添加歌曲与网络专辑封面

Let's tackle your two issues one by one—they're both common hurdles when building a media player with Android's Media framework, so I'll break down practical steps for each:

问题1:从其他Activity添加歌曲到播放列表(支持两种操作)

The key here is using Android's MediaController and MediaSession to communicate between your Activity and MediaBrowserService. Here's how to implement both "Add and Play" and "Add to Queue End" actions:

Step 1: Define custom actions in your MediaBrowserService

First, add constants for your custom commands in your service class so your Activity can reference them:

public class YourMediaService extends MediaBrowserServiceCompat {
    public static final String ACTION_ADD_AND_PLAY = "com.your.app.package.ACTION_ADD_AND_PLAY";
    public static final String ACTION_ADD_TO_QUEUE_END = "com.your.app.package.ACTION_ADD_TO_QUEUE_END";
    public static final String EXTRA_MEDIA_ITEM = "com.your.app.package.EXTRA_MEDIA_ITEM";

    // ... existing service code ...
}

Step 2: Handle custom commands in the MediaSession Callback

Update your MediaSession.Callback to process these commands and modify the playback queue:

mediaSession.setCallback(new MediaSessionCompat.Callback() {
    // ... existing callbacks (onPlay, onPause, etc.) ...

    @Override
    public void onCommand(String command, Bundle extras, ResultReceiver cb) {
        super.onCommand(command, extras, cb);
        if (extras == null || !extras.containsKey(EXTRA_MEDIA_ITEM)) {
            sendResult(cb, 0);
            return;
        }

        MediaItemCompat mediaItem = extras.getParcelable(EXTRA_MEDIA_ITEM);
        if (mediaItem == null) {
            sendResult(cb, 0);
            return;
        }

        switch (command) {
            case ACTION_ADD_AND_PLAY:
                addAndPlayItem(mediaItem);
                sendResult(cb, 1);
                break;
            case ACTION_ADD_TO_QUEUE_END:
                addItemToQueueEnd(mediaItem);
                sendResult(cb, 1);
                break;
            default:
                sendResult(cb, 0);
        }
    }

    private void sendResult(ResultReceiver cb, int resultCode) {
        if (cb != null) {
            cb.sendResult(resultCode, null);
        }
    }

    private void addAndPlayItem(MediaItemCompat item) {
        List<MediaSessionCompat.QueueItem> currentQueue = mediaSession.getQueue();
        List<MediaSessionCompat.QueueItem> newQueue = new ArrayList<>();
        
        if (currentQueue != null) {
            newQueue.addAll(currentQueue);
        }
        newQueue.add(new MediaSessionCompat.QueueItem(item.getDescription(), newQueue.size()));
        
        mediaSession.setQueue(newQueue);
        // Switch to the new item and play
        mediaSession.getController().getTransportControls().skipToQueueItem(newQueue.size() - 1);
    }

    private void addItemToQueueEnd(MediaItemCompat item) {
        List<MediaSessionCompat.QueueItem> currentQueue = mediaSession.getQueue();
        List<MediaSessionCompat.QueueItem> newQueue = new ArrayList<>();
        
        if (currentQueue != null) {
            newQueue.addAll(currentQueue);
        }
        newQueue.add(new MediaSessionCompat.QueueItem(item.getDescription(), newQueue.size()));
        
        mediaSession.setQueue(newQueue);
    }
});

Step 3: Trigger actions from your other Activity

In your search (or other) Activity, use MediaController to send the commands to the service. Make sure you've already connected to the MediaBrowser first:

// Get the MediaController (you can get this via MediaBrowser's connection callback)
MediaControllerCompat mediaController = MediaControllerCompat.getMediaController(this);

// Example: "Add and Play" button click
buttonAddAndPlay.setOnClickListener(v -> {
    Bundle extras = new Bundle();
    extras.putParcelable(YourMediaService.EXTRA_MEDIA_ITEM, yourTargetMediaItem);
    
    mediaController.sendCommand(YourMediaService.ACTION_ADD_AND_PLAY, extras, new ResultReceiver(new Handler(Looper.getMainLooper())) {
        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            super.onReceiveResult(resultCode, resultData);
            Toast.makeText(SearchActivity.this, 
                resultCode == 1 ? "Added and playing" : "Failed to add", 
                Toast.LENGTH_SHORT).show();
        }
    });
});

// Example: "Add to Queue End" button click
buttonAddToQueue.setOnClickListener(v -> {
    Bundle extras = new Bundle();
    extras.putParcelable(YourMediaService.EXTRA_MEDIA_ITEM, yourTargetMediaItem);
    
    mediaController.sendCommand(YourMediaService.ACTION_ADD_TO_QUEUE_END, extras, new ResultReceiver(new Handler(Looper.getMainLooper())) {
        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            super.onReceiveResult(resultCode, resultData);
            Toast.makeText(SearchActivity.this, 
                resultCode == 1 ? "Added to queue" : "Failed to add", 
                Toast.LENGTH_SHORT).show();
        }
    });
});
问题2:加载Last FM API网络图片作为专辑封面

The default Google example uses local drawables, but switching to remote images just requires adjusting how you set the album art URI, plus using an image loader library (like Glide) to handle network loading and caching.

Step 1: Fetch album art URL from Last FM API

First, make sure you're requesting the album info from Last FM with your API key. A sample API request looks like this:

https://ws.audioscrobbler.com/2.0/?method=album.getinfo&api_key=YOUR_LASTFM_API_KEY&artist=ARTIST_NAME&album=ALBUM_NAME&format=json

Parse the JSON response to get the album art URL—look for the image array, and pick the size you need (e.g., large or extralarge).

Step 2: Update MusicLibrary to use remote URIs

Modify your MusicLibrary class to set the remote URL as the icon URI in your MediaDescription:

public class MusicLibrary {
    // ... existing code ...

    public static MediaDescriptionCompat getMediaDescription(Context context, String mediaId) {
        // Fetch your song data (artist, album, etc.)
        Song song = getSongById(mediaId);
        
        // Get the album art URL from your Last FM response
        String albumArtUrl = song.getAlbumArtUrl();
        Uri albumArtUri = Uri.parse(albumArtUrl != null ? albumArtUrl : 
            "android.resource://" + context.getPackageName() + "/" + R.drawable.default_cover);

        return new MediaDescriptionCompat.Builder()
                .setMediaId(mediaId)
                .setTitle(song.getTitle())
                .setSubtitle(song.getArtist())
                .setIconUri(albumArtUri)
                .build();
    }
}

Step 3: Load remote images with Glide in your UI

Android's default image loading won't handle remote URLs reliably, so use Glide to load the album art in your RecyclerView adapters and playback UI:

// In your RecyclerView.ViewHolder bind method
Glide.with(itemView.getContext())
        .load(mediaItem.getDescription().getIconUri())
        .placeholder(R.drawable.default_cover) // Show while loading
        .error(R.drawable.default_cover) // Show if load fails
        .centerCrop()
        .into(albumArtImageView);

Step 4: Add required permissions

Don't forget to add internet permission to your AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />

内容的提问来源于stack exchange,提问作者Sunil Meena

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:47:07