如何写一个正经的Android音乐播放器 一
以前写过很多次音乐播放器,但是总有一些问题出现,例如:
1,音乐长时间播放问题(即便是放在service中去播放,依然会被杀死);
2,音乐的播放进度如何掌握?(如何利用mediaplayer.getCurrentPosition()来有效的通知界面变更进度?);
3,在我以往的经验中,音乐播放完毕下一曲时候,经常出现当前音乐播放还差几秒钟的时候就下一曲了的情况。
从网上找到教程中,通常都是一个播放器的demo,简单的直接把MediaPlayer放在了一个Activity中去操作,稍有良心的教程把MediaPlayer放在了Servic中,但是这是远远不够的。
最好的教程还是谷歌官方的Training和API 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 = cursor.getFloat(columnIndex); bundle.putFloat(key, floatValue); break; case Cursor.FIELD_TYPE_INTEGER: int intValue = cursor.getInt(columnIndex); bundle.putInt(key, intValue); break; case Cursor.FIELD_TYPE_NULL: break; case Cursor.FIELD_TYPE_STRING: String strValue = cursor.getString(columnIndex); bundle.putString(key, strValue); break; } } Audio audio = new Audio (bundle); audioList.add(audio); } cursor.close(); return audioList; } }
如此返回一个Audio的List,现在我们可以用这个List做一个列表展示。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。