編輯:關於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 getAudioList(Context context) { List audioList = new ArrayList(); 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做一個列表展示。
先上圖:這裡以添加 afinal_0.5.1_bin.jar 為例。第一步:添加jar包到libs裡面,系統自動把jar加載到android private librar
這篇來講一下觀察者模式,觀察者模式在實際項目中使用的也是非常頻繁的,它最常用的地方是GUI系統、訂閱——發布系統等。因為這個模式的一個重要作用就是
Android與JS之間跨平台異步調用 為什麼突然要搞這個問題呢? 在開發浏覽器的時候遇到這個狗血的問題,花了將近1天的時間才想到這個解決方案,Androi
研究了一下android的apk的簽名和代碼的混淆打包,如果不混淆打包,那麼apk可以直接被人反編譯出來查看源碼,混淆打包雖然還是能看懂,但是沒有那麼好懂了,至少要話費些