首页 > 代码库 > 如何写一个正经的Android音乐播放器 一

如何写一个正经的Android音乐播放器 一

以前写过很多次音乐播放器,但是总有一些问题出现,例如:

1,音乐长时间播放问题(即便是放在service中去播放,依然会被杀死);

2,音乐的播放进度如何掌握?(如何利用mediaplayer.getCurrentPosition()来有效的通知界面变更进度?); 

3,在我以往的经验中,音乐播放完毕下一曲时候,经常出现当前音乐播放还差几秒钟的时候就下一曲了的情况。

从网上找到教程中,通常都是一个播放器的demo,简单的直接把MediaPlayer放在了一个Activity中去操作,稍有良心的教程把MediaPlayer放在了Servic中,但是这是远远不够的。

最好的教程还是谷歌官方的TrainingAPI Guides,尽管很久以前就简单粗暴的读过有关service的文档,但是,古人都说温故而知新嘛,经过这次温故,对比以前的代码经验,觉得可以有更好的方式来实现一个音乐播放器。遂决定重新写一个音乐播放器。

如果有大神有更好 方案,还望知会我。

注意:这篇文章,不适合对MediaPlayer不了解的同学,假定看这篇文章的,都是已经会初步使用Service的同学。


一,音乐列表的读取。

关于音乐列表的读取,不同的音乐播放器都会有不同的方案,有的是有多重方案并用。例如说,全盘扫描音乐格式文件等,但是Android本身有媒体库,可以读取本地媒体库的数据,来快速获知设备上的音乐。

首先我封装了一个Audio类来存储读取的音频信息。

public class Audio {
	
	
	private String mTitle,
				   mTitleKey,
				   mArtist,
				   mArtistKey,
				   mComposer,
				   mAlbum,
				   mAlbumKey,
				   mDisplayName,
				   mMimeType,
				   mPath;
	
	private int mId,
                mArtistId,
				mAlbumId,
                mYear,
				mTrack;
	
	private int mDuration = 0,
				 mSize = 0;
	
	private boolean isRingtone = false,
					isPodcast = false,
					isAlarm = false,
					isMusic = false,
					isNotification = false;
	
	public Audio (Bundle bundle) {
        mId = bundle.getInt(MediaStore.Audio.Media._ID);
		mTitle = bundle.getString(MediaStore.Audio.Media.TITLE);
		mTitleKey = bundle.getString(MediaStore.Audio.Media.TITLE_KEY);
		mArtist = bundle.getString(MediaStore.Audio.Media.ARTIST);
		mArtistKey = bundle.getString(MediaStore.Audio.Media.ARTIST_KEY);
		mComposer = bundle.getString(MediaStore.Audio.Media.COMPOSER);
		mAlbum = bundle.getString(MediaStore.Audio.Media.ALBUM);
		mAlbumKey = bundle.getString(MediaStore.Audio.Media.ALBUM_KEY);
		mDisplayName = bundle.getString(MediaStore.Audio.Media.DISPLAY_NAME);
		mYear = bundle.getInt(MediaStore.Audio.Media.YEAR);
		mMimeType = bundle.getString(MediaStore.Audio.Media.MIME_TYPE);
		mPath = bundle.getString(MediaStore.Audio.Media.DATA);
		
		mArtistId = bundle.getInt(MediaStore.Audio.Media.ARTIST_ID);
		mAlbumId = bundle.getInt(MediaStore.Audio.Media.ALBUM_ID);
		mTrack = bundle.getInt(MediaStore.Audio.Media.TRACK);
		mDuration = bundle.getInt(MediaStore.Audio.Media.DURATION);
		mSize = bundle.getInt(MediaStore.Audio.Media.SIZE);
		isRingtone = bundle.getInt(MediaStore.Audio.Media.IS_RINGTONE) == 1;
		isPodcast = bundle.getInt(MediaStore.Audio.Media.IS_PODCAST) == 1;
		isAlarm = bundle.getInt(MediaStore.Audio.Media.IS_ALARM) == 1;
		isMusic = bundle.getInt(MediaStore.Audio.Media.IS_MUSIC) == 1;
		isNotification = bundle.getInt(MediaStore.Audio.Media.IS_NOTIFICATION) == 1;
				 
	}

    public int getId() {
        return mId;
    }

    public String getMimeType () {
		return mMimeType;
	}
	
	public int getDuration () {
		return mDuration;
	}
	
	public int getSize () {
		return mSize;
	}
	
	public boolean isRingtone () {
		return isRingtone;
	}
	
	public boolean isPodcast () {
		return isPodcast;
	}
	
	public boolean isAlarm () {
		return isAlarm;
	}
	
	public boolean isMusic () {
		return isMusic;
	}
	
	public boolean isNotification () {
		return isNotification;
	}
	
	public String getTitle () {
		return mTitle;
	}
	
	public String getTitleKey () {
		return mTitleKey;
	}
	
	public String getArtist () {
		return mArtist;
	}
	
	public int getArtistId () {
		return mArtistId;
	}
	
	public String getArtistKey () {
		return mArtistKey;
	}
	
	public String getComposer () {
		return mComposer;
	}
	
	public String getAlbum () {
		return mAlbum;
	}
	
	public int getAlbumId () {
		return mAlbumId;
	}
	
	public String getAlbumKey () {
		return mAlbumKey;
	}
	
	public String getDisplayName () {
		return mDisplayName;
	}
	
	public int getYear () {
		return mYear;
	}
	
	public int getTrack () {
		return mTrack;
	}
	
	public String getPath () {
		return mPath;
	}
	
}

以上类来封装音乐媒体信息,一些变量看名字也能看出来是什么,例如说title,duration此类,无非就是歌曲名称,时长之类的信息,有些变量名字单词认识,但是并不知道干什么用,其实我也不知道是什么信息,虽然打印出来过,但是并不懂到底哪里能用到,反正一股脑都读出来了先,以后再打印输出看看都是些什么。

其次,一个读取媒体音频的方法:

public class MediaUtils {
    public static final String[] AUDIO_KEYS = new String[]{
            MediaStore.Audio.Media._ID,
            MediaStore.Audio.Media.TITLE,
            MediaStore.Audio.Media.TITLE_KEY,
            MediaStore.Audio.Media.ARTIST,
            MediaStore.Audio.Media.ARTIST_ID,
            MediaStore.Audio.Media.ARTIST_KEY,
            MediaStore.Audio.Media.COMPOSER,
            MediaStore.Audio.Media.ALBUM,
            MediaStore.Audio.Media.ALBUM_ID,
            MediaStore.Audio.Media.ALBUM_KEY,
            MediaStore.Audio.Media.DISPLAY_NAME,
            MediaStore.Audio.Media.DURATION,
            MediaStore.Audio.Media.SIZE,
            MediaStore.Audio.Media.YEAR,
            MediaStore.Audio.Media.TRACK,
            MediaStore.Audio.Media.IS_RINGTONE,
            MediaStore.Audio.Media.IS_PODCAST,
            MediaStore.Audio.Media.IS_ALARM,
            MediaStore.Audio.Media.IS_MUSIC,
            MediaStore.Audio.Media.IS_NOTIFICATION,
            MediaStore.Audio.Media.MIME_TYPE,
            MediaStore.Audio.Media.DATA
    };

    public static List<Audio> getAudioList(Context context) {
        List<Audio> audioList = new ArrayList<Audio>();

        ContentResolver resolver = context.getContentResolver();
        Cursor cursor = resolver.query(
                MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                AUDIO_KEYS,
                null,
                null,
                null);

        for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
            Bundle bundle = new Bundle ();
            for (int i = 0; i < AUDIO_KEYS.length; i++) {
                final String key = AUDIO_KEYS[i];
                final int columnIndex = cursor.getColumnIndex(key);
                final int type = cursor.getType(columnIndex);
                switch (type) {
                    case Cursor.FIELD_TYPE_BLOB:
                        break;
                    case Cursor.FIELD_TYPE_FLOAT:
                        float floatValue = http://www.mamicode.com/cursor.getFloat(columnIndex);>

如此返回一个AudioList,现在我们可以用这个List做一个列表展示。




如何写一个正经的Android音乐播放器 一