最近在公司做锁屏项目,需要在锁屏界面上显示音乐播放器的状态,类似小米的锁屏界面,网上也有类似的功能介绍,我在这里做个总结吧。
首先说下,这个数据信息是音乐播放器中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); } }