最近在公司做锁屏项目,需要在锁屏界面上显示音乐播放器的状态,类似小米的锁屏界面,网上也有类似的功能介绍,我在这里做个总结吧。
首先说下,这个数据信息是音乐播放器中service(com.android.music.MediaPlaybackService)以广播的形式发出来的。
有的第三方播放器也有这个服务,比如天天动听,如果手机上面有多个以上的播放器实现了这个服务,那么会出现混乱现象(小米手机也有此现象)。
主要的数据包括,音乐文件id,作者,等,界面中的专辑图片是从数据查询出来的,后面会介绍。
public long id;
public String artistName;public String album;public String track;public boolean playing;public long duration;public long position;
再说下播放控制吧,锁屏上可以使用的功能比较简单,播放、暂停、上一曲、下一曲。
这写播放控制都是以启动一个服务,把命令以参数形式,发送过去,然后会服务就会返回一个广播,返回当前音乐播放器的状态。
再说说专辑图片,这个专辑图片是从音乐文件中提取出来的,有类似的协议和算法,这里不做介绍,这些东西Android系统都有实现,我们只需要拿来使用就好了。
完全的拿来主义,鄙视下自己~~~
刚刚上面的实体类中有个id的字段,这样我们可以从安卓的媒体内容提供者中查询(MediaStore),可以根据id查询到 MediaStore.Audio.Media.ALBUM_ID ,在根据ALBUM_ID 打开相应的文件。
/**
* 得到当前音乐播放的专辑图片,如果没有则返回null
* @param context
* @return
*/
public Bitmap getAlbumCover(Context context) {
Bitmap bmp = null;
if (id <= 0) {
return null;
}
Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToNext()) {
long albumID = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
Uri AlbumUriPath = Uri.parse(ALBUM_COVER_URI_PATH);
Uri albumIDUri = ContentUris.withAppendedId(AlbumUriPath, albumID);
ParcelFileDescriptor fd = null;
try {
fd = context.getContentResolver().openFileDescriptor(albumIDUri, "r");
} catch (FileNotFoundException e) {
}
if (fd != null) {
FileDescriptor fdc = fd.getFileDescriptor();
bmp = BitmapFactory.decodeFileDescriptor(fdc);
try {
if (fd != null) {
fd.close();
}
} catch (IOException e) {
}
}
}
return bmp;
}
}
下面是完整代码:
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.IOException;
import android.content.BroadcastReceiver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.provider.MediaStore;
/**
* 远程音乐控制控件
* Title: RemoteMusicControl.java<br>
* author:xiaqiulei@gmail.com <br>
* Date: 2013-5-30<br>
* Version:v1.0
*/
public class RemoteMusicControl {
static final String PLAYSTATE_CHANGED = "com.android.music.playstatechanged";
static final String META_CHANGED = "com.android.music.metachanged";
static final String QUEUE_CHANGED = "com.android.music.queuechanged";
static final String PLAYBACK_COMPLETE = "com.android.music.playbackcomplete";
static final String QUIT_PLAYBACK = "com.android.music.quitplayback";
static final String SERVICE_ACTION = "com.android.music.MediaPlaybackService";
static final String SERVICECMD = "com.android.music.musicservicecommand";
static final String CMDNAME = "command";
static final String CMDTOGGLEPAUSE = "togglepause";
static final String CMDSTOP = "stop";
static final String CMDPAUSE = "pause";
static final String CMDPLAY = "play";
static final String CMDPREVIOUS = "previous";
static final String CMDNEXT = "next";
private Context mContext;
private boolean playing = false;
private boolean mIsRegister = false;
private OnRemoteMusicControlCallback onRemoteMusicControlCallback;
private Handler hander;
public RemoteMusicControl(Context context) {
mContext = context;
}
/**
* 注册
*/
public void register() {
hander = new Handler();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(PLAYSTATE_CHANGED);
intentFilter.addAction(META_CHANGED);
// intentFilter.addAction(QUEUE_CHANGED);
intentFilter.addAction(PLAYBACK_COMPLETE);
//intentFilter.addAction(QUIT_PLAYBACK);
mContext.registerReceiver(receiver, intentFilter);
Intent it = new Intent(SERVICE_ACTION);
mContext.startService(it);
mIsRegister = true;
}
/**
* 注销
*/
public void unRegister() {
if (receiver != null) {
mContext.unregisterReceiver(receiver);
}
mIsRegister = false;
hander = null;
}
/**
* 执行命令
* @param cmd
*/
void doRemoteMusic(String cmd) {
Intent intent = new Intent(SERVICECMD);
intent.putExtra(CMDNAME, cmd);
mContext.sendBroadcast(intent);
}
/**
* 下一曲
*/
public void doRemoteMusicNext() {
doRemoteMusic(CMDNEXT);
}
/**
* 上一曲
*/
public void doRemoteMusicPerv() {
doRemoteMusic(CMDPREVIOUS);
}
/**
* 播放
*/
public void doRemoteMusicPlay() {
doRemoteMusic(CMDPLAY);
}
/**
* 暂停
*/
public void doRemoteMusicPause() {
doRemoteMusic(CMDPAUSE);
}
/**
* 暂停或者播放
*/
public void doRemoteMusicPlayOrPause() {
if (playing) {
doRemoteMusic(CMDPAUSE);
} else {
doRemoteMusic(CMDPLAY);
}
}
/**
* 音乐服务接受广播
*/
BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
final MusicExtra me = new MusicExtra();
me.id = intent.getLongExtra("id", 0);
me.artistName = intent.getStringExtra("artist");
me.album = intent.getStringExtra("album");
me.track = intent.getStringExtra("track");
me.playing = intent.getBooleanExtra("playing", false);
me.duration = intent.getLongExtra("duration", 3000);
me.position = intent.getLongExtra("position", 1000);
playing = me.playing;
if (hander != null) {
hander.post(new Runnable() {
public void run() {
if (onRemoteMusicControlCallback != null) {
onRemoteMusicControlCallback.onCallback(me);
}
}
});
}
}
};
/**
* 是否注册
* @return
*/
public boolean isRegister() {
return mIsRegister;
}
public OnRemoteMusicControlCallback getOnRemoteMusicControlCallback() {
return onRemoteMusicControlCallback;
}
public void setOnRemoteMusicControlCallback(OnRemoteMusicControlCallback onRemoteMusicControlCallback) {
this.onRemoteMusicControlCallback = onRemoteMusicControlCallback;
}
/**
* 音乐播放状态
*/
public static class MusicExtra {
static final String ALBUM_COVER_URI_PATH = "content://media/external/audio/albumart";
public long id;
public String artistName;
public String album;
public String track;
public boolean playing;
public long duration;
public long position;
public String toString() {
return "MusicExtra [id=" + id + ", artistName=" + artistName + ", album=" + album + ", track=" + track + ", playing=" + playing + ", duration="
+ duration + ", position=" + position + "]";
}
/**
* 得到当前音乐播放的专辑图片,如果没有则返回null
* @param context
* @return
*/
public Bitmap getAlbumCover(Context context) {
Bitmap bmp = null;
if (id <= 0) {
return null;
}
Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
if (cursor != null && cursor.moveToNext()) {
long albumID = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
Uri AlbumUriPath = Uri.parse(ALBUM_COVER_URI_PATH);
Uri albumIDUri = ContentUris.withAppendedId(AlbumUriPath, albumID);
ParcelFileDescriptor fd = null;
try {
fd = context.getContentResolver().openFileDescriptor(albumIDUri, "r");
} catch (FileNotFoundException e) {
}
if (fd != null) {
FileDescriptor fdc = fd.getFileDescriptor();
bmp = BitmapFactory.decodeFileDescriptor(fdc);
try {
if (fd != null) {
fd.close();
}
} catch (IOException e) {
}
}
}
return bmp;
}
}
/**
* 远程音乐播放控制空间回调
*/
public interface OnRemoteMusicControlCallback {
public void onCallback(MusicExtra extra);
}
}