简单明了的从中式英语去理解,Media 多媒体、 Session 会话
MediaSession 是Google 官方提供的多媒体框架
框架主要分为两部分:服务端、客户端
服务端提供播放器的参数配置啥的
客户端控制服务端具体操作;比如:播放、暂停、上一曲、下一曲等等自定义方式
想要官方一点的理解自己去看官方文档:
https://developer.android.google.cn/guide/topics/media-apps/media-apps-overview
话不多说,直接撸代码:
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaBrowserServiceCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.util.Log;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class MediaService extends MediaBrowserServiceCompat {
private static final String TAG = "TEST_MediaService";
/**
* 媒体会话,受控端
* 设置session 到界面响应
*/
private MediaSessionCompat mediaSession;
/**
* 返回到界面的播放状态/播放的ID3信息
*/
private PlaybackStateCompat mPlaybackState;
/**
* 当前播放下标
*/
private int currentPostion = 0;
/**
*
*/
private String parentId;
/**
* 当前播放列表
*/
private List mPlayBeanList = MusicListData.getPlayList();
boolean isHaveAudioFocus = false;
private AudioManager mAudioManager;
/**
* 进度条更新时间1s
*/
private static final int UPDATE_TIME = 1000;
private final Handler mHandler = new Handler();
/**
* 音乐进度条
*/
private final Runnable mRunnable = new Runnable() {
@Override
public void run() {
if (null == mMediaPlayer || null == mPlaybackState || null == mediaSession) {
Log.d(TAG, "run: mMediaPlayer = " + mMediaPlayer + " mPlaybackState = " + mPlaybackState + " mediaSession = " + mediaSession);
return;
}
if (!mMediaPlayer.isPlaying()) {
Log.d(TAG, "run: not playing");
return;
}
Log.d(TAG, "run: currentPostion = " + mMediaPlayer.getCurrentPosition() + " duration = " + mMediaPlayer.getDuration());
Bundle extras = new Bundle();
extras.putLong("currentPostion", mMediaPlayer.getCurrentPosition());
extras.putLong("duration", mMediaPlayer.getDuration());
sendPlaybackState(PlaybackStateCompat.STATE_PLAYING, extras);
mHandler.postDelayed(mRunnable, UPDATE_TIME);
}
};
/**
* 播放器
*/
private MediaPlayer mMediaPlayer;
/**
* 准备就绪?
*/
private boolean isPrepare = false;
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: ");
mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
mPlaybackState = new PlaybackStateCompat.Builder()
.setState(PlaybackStateCompat.STATE_NONE, currentPostion, 1.0f)
.setActions(getAvailableActions(PlaybackStateCompat.STATE_NONE))
.build();
//初始化,第一个参数为context,第二个参数为String类型tag,这里就设置为类名了
mediaSession = new MediaSessionCompat(this, "MediaService");
//设置token
setSessionToken(mediaSession.getSessionToken());
//设置callback,这里的callback就是客户端对服务指令到达处
mediaSession.setCallback(mCallback);
mediaSession.setActive(true);
//初始化播放器
mMediaPlayer = new MediaPlayer();
//准备监听
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
Log.d(TAG, "onPrepared: ");
isPrepare = true;
// 准备就绪
sendPlaybackState(PlaybackStateCompat.STATE_BUFFERING);
handlePlay();
}
});
//播放完成监听
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
Log.d(TAG, "onCompletion: ");
sendPlaybackState(PlaybackStateCompat.STATE_NONE);
// 播放完成 重置 播放器
// mMediaPlayer.reset();
// 下一曲
mCallback.onSkipToNext();
}
});
//播放错误监听
mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
Log.d(TAG, "onError: what = " + what + " extra = " + extra);
isPrepare = false;
sendPlaybackState(PlaybackStateCompat.STATE_ERROR);
// 播放错误 重置 播放器
mMediaPlayer.reset();
return false;
}
});
// 设置音频流类型
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//设置声音
AudioManager mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
if (null != mAudioManager) {
int mVolumn = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
mMediaPlayer.setVolume(mVolumn, mVolumn);
}
}
//mediaSession设置的callback,也是客户端控制指令所到达处
private final MediaSessionCompat.Callback mCallback = new MediaSessionCompat.Callback() {
//重写的方法都是选择性重写的,不完全列列举,具体可以查询文章末尾表格
@Override
public void onPlay() {
super.onPlay();
Log.d(TAG, "onPlay: isPrepare = " + isPrepare);
//客户端mMediaController.getTransportControls().play()就会调用到这里,以下类推
//处理播放逻辑
//处理完成后通知客户端更新,这里就会回调给客户端的MediaController.Callback
if (null != mMediaPlayer && !isPrepare) {
handleOpenUri(MusicListData.rawToUri(MediaService.this, Objects.requireNonNull(getPlayBean()).mediaId));
} else {
handlePlay();
}
}
@Override
public void onPause() {
super.onPause();
Log.d(TAG, "onPause: ");
handlePause(true);
}
@Override
public void onSeekTo(long pos) {
super.onSeekTo(pos);
//设置到指定进度时触发
}
@Override
public void onSkipToPrevious() {
int pos = (currentPostion + mPlayBeanList.size() - 1) % mPlayBeanList.size();
Log.e(TAG, "onSkipToPrevious pos = " + pos);
handleOpenUri(MusicListData.rawToUri(MediaService.this, Objects.requireNonNull(setPlayPosition(pos)).mediaId));
}
@Override
public void onSkipToNext() {
super.onSkipToNext();
//下一首
//通知媒体信息改变
// mediaSession.setMetadata(mediaMetadata);
int pos = (currentPostion + 1) % mPlayBeanList.size();
Log.d(TAG, "onSkipToNext: pos = " + pos);
handleOpenUri(MusicListData.rawToUri(MediaService.this, Objects.requireNonNull(setPlayPosition(pos)).mediaId));
}
/**
* 响应MediaControllerCompat.getTransportControls().playFromUri
*
* @param uri uri
* @param extras extras
*/
@Override
public void onPlayFromUri(Uri uri, Bundle extras) {
Log.e(TAG, "onPlayFromUri");
int position = extras.getInt("playPosition");
setPlayPosition(position);
handleOpenUri(uri);
}
@Override
public void onCustomAction(String action, Bundle extras) {
super.onCustomAction(action, extras);
//自定义指令发送到的地方
//对应客户端 mMediaController.getTransportControls().sendCustomAction(...)
}
};
/**
* 控制客户端 链接
*
* @param clientPackageName clientPackageName
* @param clientUid clientUid
* @param rootHints rootHints
* @return BrowserRoot
*/
@Nullable
@Override
public BrowserRoot onGetRoot(@android.support.annotation.NonNull @NonNull String clientPackageName, int clientUid, @Nullable Bundle rootHints) {
//MediaBrowserService必须重写的方法,第一个参数为客户端的packageName,第二个参数为Uid
//第三个参数是从客户端传递过来的Bundle。
//通过以上参数来进行判断,若同意连接,则返回BrowserRoot对象,否则返回null;
//构造BrowserRoot的第一个参数为rootId(自定义),第二个参数为Bundle;
Log.d(TAG, "onGetRoot: clientPackageName = " + clientPackageName + " clientUid = " + clientUid);
return new BrowserRoot(clientPackageName, null);
}
/**
* 播放列表
*
* @param parentId parentId
* @param result result
*/
@Override
public void onLoadChildren(@android.support.annotation.NonNull @NonNull String parentId, @NonNull Result> result) {
//MediaBrowserService必须重写的方法,用于处理订阅信息,文章后面会提及
// 设置播放列表
Log.e(TAG, "onLoadChildren-------- parentId = " + parentId);
this.parentId = parentId;
// 将信息从当前线程中移除,允许后续调用sendResult方法
result.detach();
// 我们模拟获取数据的过程,真实情况应该是异步从网络或本地读取数据
ArrayList mediaItems = MusicListData.transformPlayList(mPlayBeanList);
// 向Browser发送 播放列表数据
result.sendResult(mediaItems);
// 刷新 播放数据数据
// notifyChildrenChanged(parentId);
// 模拟定时加载数据
if (mediaItems.size() == 2) {
getSyncData();
}
}
/**
* 模拟刷新数据
*/
private void getSyncData() {
Log.d(TAG, "getSyncData: ");
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, "run: load data for update ");
mPlayBeanList = MusicListData.getPlayListUpdate();
currentPostion = 0;
notifyChildrenChanged(parentId);
}
}, 30000);
}
@Override
public void onDestroy() {
super.onDestroy();
isPrepare = false;
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
if (mediaSession != null) {
mediaSession.release();
mediaSession = null;
}
}
/**
* 申请焦点
*
* @return 焦点
*/
private int requestAudioFocus() {
int result = mAudioManager.requestAudioFocus(mOnAudioFocusChangeListener, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN);
isHaveAudioFocus = AudioManager.AUDIOFOCUS_REQUEST_GRANTED == result;
return result;
}
/**
* 释放焦点
*/
private void abandAudioFocus() {
int result = mAudioManager.abandonAudioFocus(mOnAudioFocusChangeListener);
isHaveAudioFocus = AudioManager.AUDIOFOCUS_REQUEST_GRANTED == result;
}
/**
* open
*
* @param uri uri
*/
private void handleOpenUri(Uri uri) {
Log.d(TAG, "handleOpenUri: uri = " + uri);
if (uri == null) {
Log.d(TAG, "handlePlayUri: URL == NULL ");
return;
}
if (requestAudioFocus() != AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
Log.d(TAG, "handlePlayUri: requestAudioFocus() != AudioManager.AUDIOFOCUS_REQUEST_GRANTED");
return;
}
isPrepare = false;
mMediaPlayer.reset();
mMediaPlayer.setLooping(false);
try {
mMediaPlayer.setDataSource(this, uri);
} catch (IOException e) {
Log.e(TAG, "handlePlayUri: ", e);
e.printStackTrace();
}
mMediaPlayer.prepareAsync();
}
/**
* 播放
*/
private void handlePlay() {
Log.d(TAG, "handlePlay: play isPrepare = " + isPrepare);
if (null == mMediaPlayer || !isPrepare) {
Log.d(TAG, "handlePlay: null == mMediaPlayer || isPrepare " + isPrepare);
return;
}
if (!mMediaPlayer.isPlaying()) {
mMediaPlayer.start();
}
mHandler.removeCallbacks(mRunnable);
mHandler.postDelayed(mRunnable, UPDATE_TIME);
sendPlaybackState(PlaybackStateCompat.STATE_CONNECTING);
//我们可以保存当前播放音乐的信息,以便客户端刷新UI
mediaSession.setMetadata(MusicListData.transformPlayBean(Objects.requireNonNull(getPlayBean())));
}
/**
* 暂停
*
* @param isAbandFocus 焦点
*/
private void handlePause(boolean isAbandFocus) {
Log.d(TAG, "handlePause: isAbandFocus = " + isAbandFocus);
if (mMediaPlayer == null || !isPrepare) {
return;
}
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
}
mHandler.removeCallbacks(mRunnable);
sendPlaybackState(PlaybackStateCompat.STATE_PAUSED);
}
/**
* 当前播放 歌曲
*
* @return playbean
*/
private MusicData getPlayBean() {
if (currentPostion >= 0 && currentPostion < mPlayBeanList.size()) {
return mPlayBeanList.get(currentPostion);
}
return null;
}
/**
* 设置列表 播放下标
*
* @param pos pos
* @return playbean
*/
private MusicData setPlayPosition(int pos) {
if (pos >= 0 && pos < mPlayBeanList.size()) {
currentPostion = pos;
return mPlayBeanList.get(currentPostion);
}
return null;
}
/**
* Set the current capabilities available on this session. This should
* use a bitmask of the available capabilities.
*
* @param state 歌曲状态
* @return 可用的操作Actions
*/
public long getAvailableActions(int state) {
long actions = PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
| PlaybackStateCompat.ACTION_SKIP_TO_NEXT
| PlaybackStateCompat.ACTION_REWIND
| PlaybackStateCompat.ACTION_FAST_FORWARD
| PlaybackStateCompat.ACTION_SEEK_TO;
if (state == PlaybackStateCompat.STATE_PLAYING) {
actions |= PlaybackStateCompat.ACTION_PAUSE;
} else {
actions |= PlaybackStateCompat.ACTION_PLAY;
}
return actions;
}
/**
* 音源切换监听
*/
AudioManager.OnAudioFocusChangeListener mOnAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
@Override
public void onAudioFocusChange(int focusChange) {
Log.d(TAG, "onAudioFocusChange focusChange = " + focusChange + ", before isHaveAudioFocus = " +
isHaveAudioFocus);
switch (focusChange) {
case AudioManager.AUDIOFOCUS_LOSS:
// 音源丢失
isHaveAudioFocus = false;
mCallback.onPause();
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
// 音源短暂丢失
isHaveAudioFocus = false;
Log.d(TAG, " AUDIOFOCUS_LOSS_TRANSIENT ");
handlePause(false);
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
// 降低音量
break;
case AudioManager.AUDIOFOCUS_GAIN:
// 获得音源
isHaveAudioFocus = true;
mCallback.onPlay();
break;
case AudioManager.AUDIOFOCUS_REQUEST_FAILED:
// 音源申请失败
break;
default:
break;
}
}
};
/**
* 发送歌曲状态
*
* @param state 状态
*/
private void sendPlaybackState(int state) {
sendPlaybackState(state, null);
}
/**
* 发送歌曲状态
*
* @param state 状态
* @param extras 参数
*/
private void sendPlaybackState(int state, Bundle extras) {
mPlaybackState = new PlaybackStateCompat.Builder()
.setState(state, currentPostion, 1.0f)
.setActions(getAvailableActions(state))
.setExtras(extras)
.build();
mediaSession.setPlaybackState(mPlaybackState);
}
}
别忘了在AndroidManifest.xml 新增 和启动服务
启动服务
// 避免ui unbind后,后台播放音乐停止
startService(new Intent(this, MediaService.class));
MediaSession 服务端 主要做的是:
MediaPlayer 初始化
AudioManager 申请音源
实现MediaBrowserServiceCompat
onGetRoot 客户端链接
onLoadChildren 服务端把数据传给对应的客户端
PlaybackStateCompat.Builder() 是用于发送歌曲状态到客户端的实体
MediaMetadataCompat 传输的歌曲实体
MediaSessionCompat 主要用于把歌曲信息、歌曲状态等,发送到客户端进行操作
import android.content.ComponentName;
import android.media.session.PlaybackState;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaControllerCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.support.v4.media.session.PlaybackStateCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import java.util.List;
public class DemoActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "TEST_DemoActivity";
private MediaBrowserCompat mMediaBrowser;
PlayInfo mPlayInfo = new PlayInfo();
private TextView mTvInfo;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
mTvInfo = findViewById(R.id.tv_music_name);
findViewById(R.id.btn_play_or_puse).setOnClickListener(this);
findViewById(R.id.btn_pre).setOnClickListener(this);
findViewById(R.id.btn_next).setOnClickListener(this);
}
@Override
protected void onResume() {
super.onResume();
connectRemoteService();
}
private void connectRemoteService() {
// 1.连接的服务
ComponentName componentName = new ComponentName("com.xxx.xxxx", "com.xxx.xxxx.session.MossMusicService");
// 2.创建MediaBrowser
mMediaBrowser = new MediaBrowserCompat(this, componentName, mConnectionCallbacks, null);
// 3.建立连接
mMediaBrowser.connect();
}
private void refreshPlayInfo() {
mTvInfo.setText(mPlayInfo.debugInfo());
}
private final MediaBrowserCompat.ConnectionCallback mConnectionCallbacks = new MediaBrowserCompat.ConnectionCallback() {
@Override
public void onConnected() {
Log.d(TAG, "MediaBrowser.onConnected");
if (mMediaBrowser.isConnected()) {
String mediaId = mMediaBrowser.getRoot();
mMediaBrowser.unsubscribe(mediaId);
//之前说到订阅的方法还需要一个参数,即设置订阅回调SubscriptionCallback
//当Service获取数据后会将数据发送回来,此时会触发SubscriptionCallback.onChildrenLoaded回调
mMediaBrowser.subscribe(mediaId, browserSubscriptionCallback);
try {
MediaControllerCompat mediaController = new MediaControllerCompat(DemoActivity.this,
mMediaBrowser.getSessionToken());
MediaControllerCompat.setMediaController(DemoActivity.this, mediaController);
// mediaController = new MediaControllerCompat(DemoActivity.this, mMediaBrowser.getSessionToken());
mediaController.registerCallback(mMediaControllerCallback);
if (mediaController.getMetadata() != null) {
updatePlayMetadata(mediaController.getMetadata());
updatePlayState(mediaController.getPlaybackState());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onConnectionSuspended() {
// 连接中断回调
Log.d(TAG, "onConnectionSuspended");
}
@Override
public void onConnectionFailed() {
Log.d(TAG, "onConnectionFailed");
}
};
private void updatePlayMetadata(MediaMetadataCompat metadata) {
if (metadata == null) {
return;
}
mPlayInfo.setMetadata(metadata);
refreshPlayInfo();
}
/**
* 被动接收播放信息、状态改变
*/
MediaControllerCompat.Callback mMediaControllerCallback = new MediaControllerCompat.Callback() {
@Override
public void onSessionDestroyed() {
// Session销毁
Log.d(TAG, "onSessionDestroyed");
}
@Override
public void onQueueChanged(List queue) {
// 当前播放列表更新回调
}
@Override
public void onMetadataChanged(MediaMetadataCompat metadata) {
// 数据变化
Log.e(TAG, "onMetadataChanged ");
updatePlayMetadata(metadata);
}
@Override
public void onPlaybackStateChanged(PlaybackStateCompat state) {
// 播放状态变化
Log.d(TAG, "onPlaybackStateChanged PlaybackState:" + state.getState());
updatePlayState(state);
}
@Override
public void onQueueTitleChanged(CharSequence title) {
super.onQueueTitleChanged(title);
//播放列表信息回调,QueueItem在文章后面会提及
}
@Override
public void onSessionEvent(String event, Bundle extras) {
super.onSessionEvent(event, extras);
//自定义的事件回调,满足你各种自定义需求
}
@Override
public void onExtrasChanged(Bundle extras) {
super.onExtrasChanged(extras);
//额外信息回调,可以承载播放模式等信息
}
};
/**
* 向媒体浏览器服务(MediaBrowserService)发起数据订阅请求的回调接口b
*/
private final MediaBrowserCompat.SubscriptionCallback browserSubscriptionCallback = new MediaBrowserCompat.SubscriptionCallback() {
@Override
public void onChildrenLoaded(@NonNull String parentId, @NonNull List children, @NonNull Bundle options) {
super.onChildrenLoaded(parentId, children, options);
//订阅消息时添加了Bundle参数,会回调到此方法
//即mMediaBrowser.subscribe("PARENT_ID_1", mCallback,bundle)的回调
Log.d(TAG, "onChildrenLoaded: parentId = " + parentId + " children = " + children + " options = " + options);
}
@Override
public void onChildrenLoaded(@NonNull String parentId, @NonNull List children) {
Log.d(TAG, "onChildrenLoaded: parentId = " + parentId + " children = " + children);
mPlayInfo.setChildren(children);
refreshPlayInfo();
}
@Override
public void onError(@NonNull String parentId) {
super.onError(parentId);
Log.d(TAG, "onError: parentId = " + parentId);
}
@Override
public void onError(@NonNull String parentId, @NonNull Bundle options) {
super.onError(parentId, options);
Log.d(TAG, "onError: parentId = " + parentId + " options = " + options);
}
};
@Override
public void onClick(View v) {
MediaControllerCompat mediaController = MediaControllerCompat.getMediaController(DemoActivity.this);
switch (v.getId()) {
case R.id.btn_play_or_puse:
PlaybackStateCompat playbackState = mediaController.getPlaybackState();
if (null != playbackState && playbackState.getState() == PlaybackState.STATE_PLAYING) {
Log.d(TAG, "onClick: 暂停");
mediaController.getTransportControls().pause();
} else {
Log.d(TAG, "onClick: 播放");
// Log.d(TAG, "onClick: play or puse " + .getState());
mediaController.getTransportControls().play();
}
break;
case R.id.btn_pre:
mediaController.getTransportControls().skipToPrevious();
break;
case R.id.btn_next:
mediaController.getTransportControls().skipToNext();
break;
}
}
private void updatePlayState(PlaybackStateCompat state) {
if (state == null) {
return;
}
mPlayInfo.setState(state);
refreshPlayInfo();
}
static class PlayInfo {
private MediaMetadataCompat metadata;
private PlaybackStateCompat state;
private List children;
public void setMetadata(MediaMetadataCompat metadata) {
this.metadata = metadata;
}
public void setState(PlaybackStateCompat state) {
this.state = state;
}
public void setChildren(List children) {
this.children = children;
}
public String debugInfo() {
StringBuilder builder = new StringBuilder();
if (state != null) {
builder.append("当前播放状态:\t").append(state.getState() == PlaybackState.STATE_PLAYING ? "播放中" : "未播放");
Bundle extras = state.getExtras();
if (null != extras) {
long currentPostion = extras.getLong("currentPostion", 0);
long duration = extras.getLong("duration", 0);
builder.append("\n当前播放进度:\t").append("currentPostion = ").append(currentPostion).append(" / duration = ").append(duration);
}
builder.append("\n\n");
}
if (metadata != null) {
builder.append("当前播放信息:\t").append(transform(metadata));
builder.append("\n\n");
}
if (children != null && !children.isEmpty()) {
builder.append("当前播放列表:").append("\n");
for (int i = 0; i < children.size(); i++) {
MediaBrowserCompat.MediaItem mediaItem = children.get(i);
builder.append(i + 1).append(" ").append(mediaItem.getDescription().getTitle()).append(" - ").append(mediaItem.getDescription().getSubtitle()).append("\n");
}
}
return builder.toString();
}
public static String transform(MediaMetadataCompat data) {
if (data == null) {
return null;
}
String title = data.getString(MediaMetadataCompat.METADATA_KEY_TITLE);
String artist = data.getString(MediaMetadataCompat.METADATA_KEY_ARTIST);
String albumName = data.getString(MediaMetadataCompat.METADATA_KEY_ALBUM);
long mediaNumber = data.getLong(MediaMetadataCompat.METADATA_KEY_TRACK_NUMBER);
long mediaTotalNumber = data.getLong(MediaMetadataCompat.METADATA_KEY_NUM_TRACKS);
return title + " - " + artist;
}
}
}
MediaBrowserCompat 客户端
主要用于控制Service的播放:
启动连接:
// 1.待连接的服务
ComponentName componentName = new ComponentName("com.xxx.xxxx", "com.xxx.xxxx.session.MossMusicService");
// 2.创建MediaBrowser
mMediaBrowser = new MediaBrowserCompat(this, componentName, mConnectionCallbacks, null);
// 3.建立连接
mMediaBrowser.connect();
服务连接后,需要订阅数据的监听、MediaBrowserCompat.ConnectionCallback
被动接收播放信息、状态改变等信息回调:MediaControllerCompat.Callback
数据组装:
import android.content.Context;
import android.net.Uri;
import android.support.v4.media.MediaBrowserCompat;
import android.support.v4.media.MediaMetadataCompat;
import java.util.ArrayList;
import java.util.List;
public class MusicListData {
/**
* rwa 转换成Uri
*
* @param context context
* @param id 资源 id
* @return Uri
*/
public static Uri rawToUri(Context context, int id) {
String uriStr = "android.resource://" + context.getPackageName() + "/" + id;
return Uri.parse(uriStr);
}
public static List getPlayList() {
List list = new ArrayList<>();
MusicData playBean = new MusicData();
playBean.mediaId = R.raw.cesinspire;
playBean.tilte = "cesinspire.mp3";
playBean.artist = "test";
list.add(playBean);
MusicData playBean2 = new MusicData();
playBean2.mediaId = R.raw.bigbigbig;
playBean2.tilte = "bigbigbig";
playBean2.artist = "罗罗罗罗罗罗";
list.add(playBean2);
return list;
}
public static List getPlayListUpdate() {
List list = new ArrayList<>();
MusicData playBean = new MusicData();
playBean.mediaId = R.raw.cesinspire;
playBean.tilte = "cesinspire.mp3";
playBean.artist = "test";
list.add(playBean);
MusicData playBean2 = new MusicData();
playBean2.mediaId = R.raw.bigbigbig;
playBean2.tilte = "bigbigbig";
playBean2.artist = "罗罗罗罗罗罗";
list.add(playBean2);
MusicData playBean3 = new MusicData();
playBean3.mediaId = R.raw.fengtimo_shuosanjiusan;
playBean3.tilte = "说散就散";
playBean3.artist = "fengtimo";
list.add(playBean3);
return list;
}
/**
* 数据转换
*
* @param playBeanList playBeanList
* @return MediaSession 数据实体
*/
public static ArrayList transformPlayList(List playBeanList) {
//我们模拟获取数据的过程,真实情况应该是异步从网络或本地读取数据
ArrayList mediaItems = new ArrayList<>();
for (int i = 0; i < playBeanList.size(); i++) {
MediaMetadataCompat metadata = new MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, "" + playBeanList.get(i).mediaId)
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, playBeanList.get(i).tilte)
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, playBeanList.get(i).artist)
.build();
mediaItems.add(createMediaItem(metadata));
}
return mediaItems;
}
public static MediaMetadataCompat transformPlayBean(MusicData bean) {
return new MediaMetadataCompat.Builder()
.putString(MediaMetadataCompat.METADATA_KEY_MEDIA_ID, "" + bean.mediaId)
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, bean.tilte)
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, bean.artist)
.build();
}
private static MediaBrowserCompat.MediaItem createMediaItem(MediaMetadataCompat metadata) {
return new MediaBrowserCompat.MediaItem(metadata.getDescription(), MediaBrowserCompat.MediaItem.FLAG_PLAYABLE);
}
}
数据实体
public class MusicData {
int mediaId;
String tilte;
String artist;
}
以上 就是 MediaSession 的简单使用方式。