1. 程式人生 > >手把手教你做音樂播放器(五)音樂列表的儲存(下)

手把手教你做音樂播放器(五)音樂列表的儲存(下)

5.2 MusicService的配合

MusicService對外提供新增播放列表的介面,對內要管理PlayListContentProvider。它提供了下面的介面,

  • addPlayList():新增播放列表。這裡新增列表應該有兩種形式,一種是一次性新增多首音樂,一種是一次就新增一首音樂。

  • getPlayList():獲取播放列表

播放列表要儲存到一個數組裡面,所以我們要建立一個mPlayList實現列表的儲存,

public class MusicService extends Service {

    private List<MusicItem> mPlayList;
    private
ContentResolver mResolver; @Override public void onCreate() { super.onCreate(); //獲取ContentProvider的解析器,避免以後每次使用的時候都要重新獲取 mResolver = getContentResolver(); //儲存播放列表 mPlayList = new ArrayList<MusicItem>(); } }

5.2.1 新增播放列表

addPlayList()應該有兩種形式,一次新增一首音樂和一次新增多首音樂。

public class MusicService extends Service {
    public class MusicServiceIBinder extends Binder {
        ......

        //一次新增多首音樂
       public void addPlayList(List<MusicItem> items) {
           addPlayListInner(items);
       }

        //一次新增一首音樂
       public void addPlayList(MusicItem item) {
           addPlayListInner(item);
       }
    }

    //一次新增多首音樂具體實現
private void addPlayListInner(List<MusicItem> items) { } //一次新增一首音樂具體實現 private void addPlayListInner(MusicItem item) { } }

5.2.1.1 新增一首音樂

private void addPlayListInner(MusicItem item) {

    //判斷列表中是否已經儲存過該音樂,如果儲存過就不管它
    if(mPlayList.contains(item)) {
      return;
    }

    //新增到播放列表的第一個位置
    mPlayList.add(0, item);
    //將音樂資訊儲存到ContentProvider中
    insertMusicItemToContentProvider(item);
}

//訪問ContentProvider,儲存一條資料
private void insertMusicItemToContentProvider(MusicItem item) {

    ContentValues cv = new ContentValues();
    cv.put(DBHelper.NAME, item.name);
    cv.put(DBHelper.DURATION, item.duration);
    cv.put(DBHelper.LAST_PLAY_TIME, item.playedTime);
    cv.put(DBHelper.SONG_URI, item.songUri.toString());
    cv.put(DBHelper.ALBUM_URI, item.albumUri.toString());
    Uri uri = mResolver.insert(PlayListContentProvider.CONTENT_SONGS_URI, cv);
}

判斷mPlayList是否儲存了音樂,需要對MusicItem做特別的處理:給它定義一個比較的準則–什麼情況下兩個相比較的內容是相同的。我們這個例子當中,應該是音樂的Uri相同,則認為兩者相同。重寫MusicItemequals()方法,當使用mPlayList.contains(item)判斷的時候,會呼叫到這個重寫的方法進行比較,

public class MusicItem {

    ......
    //重寫MusicItem的equals()方法
    @Override
    public boolean equals(Object o) {
        MusicItem another = (MusicItem) o;

        //音樂的Uri相同,則說明兩者相同
        return another.songUri.equals(this.songUri);
    }
}

5.2.1.2 新增多首音樂

private void addPlayListInner(List<MusicItem> items) {

    //清空資料庫中的playlist_table
    mResolver.delete(PlayListContentProvider.CONTENT_SONGS_URI, null, null);
    //清空快取的播放列表
    mPlayList.clear();

    //將每首音樂新增到播放列表的快取和資料庫中
    for (MusicItem item : items) {
        //利用現成的程式碼,便於程式碼的維護
        addPlayListInner(item);
    }
}

5.2.2 獲取播放列表

為了獲取播放列表在ContentProvider啟動的時候,需要它將資料庫中現有的列表,載入到mPlayList當中,

public class MusicService extends Service {

    @Override
    public void onCreate() {
        super.onCreate();

        ......
        initPlayList();
        ......
    }

    private void initPlayList() {
        mPlayList.clear();

        Cursor cursor = mResolver.query(
                PlayListContentProvider.CONTENT_SONGS_URI,
                null,
                null,
                null,
                null);

        while(cursor.moveToNext()) {
            String songUri = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.SONG_URI));
            String albumUri = cursor.getString(cursor.getColumnIndexOrThrow(DBHelper.ALBUM_URI));
            String name = cursor.getString(cursor.getColumnIndex(DBHelper.NAME));
            long playedTime = cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.LAST_PLAY_TIME));
            long duration = cursor.getLong(cursor.getColumnIndexOrThrow(DBHelper.DURATION));
            MusicItem item = new MusicItem(Uri.parse(songUri), Uri.parse(albumUri), name, duration, playedTime);
            mPlayList.add(item);
        }

        cursor.close();
    }
}

之後在需要的時候,直接將mPlayList返回就可以了,

public class MusicService extends Service {
    public class MusicServiceIBinder extends Binder {
        ......

       public List<MusicItem> getPlayList() {
            return mPlayList;
        }
    }

}

5.3 主介面播放列表的新增

MusicListActivity有兩種方式新增播放列表:

  1. 單擊音樂項,將單首音樂新增到播放列表中;

  2. 長按音樂項,介面切換成ListView的多選模式,將多首音樂用替換掉方式新增到播放器當中;

這裡我們先來實現單擊音樂項的新增,多選模式我們放到後面單獨的章節來介紹。

修改點選列表的監聽器,通過MusicService提供的介面,把要新增的音樂交給MusicService處理,

//修改監聽器
private AdapterView.OnItemClickListener mOnMusicItemClickListener = new AdapterView.OnItemClickListener() {

   @Override
   public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

        MusicItem item = mMusicList.get(position);
        if(mMusicService != null) {
                //通過MusicService提供的介面,把要新增的音樂交給MusicService處理
                mMusicService.addPlayList(mMusicList.get(position));
        }
   }
};

接下來開始實現顯示播放列表的功能,給MusicListActivity做一個Menu選單,定義選單的xml檔案main_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:apps="http://schemas.android.com/apk/res-auto">
    <item
        android:title="@string/play_list"
        apps:showAsAction="always"
        android:icon="@mipmap/ic_playlist"
        android:id="@+id/play_list_menu"/>

</menu>

將選單新增到MusicListActivity當中,

public class MusicListActivity extends AppCompatActivity {
    ......
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return true;
    }
}

當用戶點選該選單的時候,彈出一個自帶列表的對話方塊,將播放列表顯示出來,

public class MusicListActivity extends AppCompatActivity {

    ......
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case R.id.play_list_menu: {
                //響應使用者對選單的點選,顯示播放列表
                showPlayList();
            }
            break;

        }

        return true;
    }

    private void showPlayList() {

        final AlertDialog.Builder builder=new AlertDialog.Builder(this);
        //設定對話方塊的圖示
        builder.setIcon(R.mipmap.ic_playlist);
        //設計對話方塊的顯示標題
        builder.setTitle(R.string.play_list);

        //獲取播放列表,把播放列表中歌曲的名字取出組成新的列表
        List<MusicItem> playList = mMusicService.getPlayList();
        ArrayList<String> data = new ArrayList<String>();
        for(MusicItem music : playList) {
            data.add(music.name);
        }
        if(data.size() > 0) {
            //播放列表有曲目,顯示音樂的名稱
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data);
            builder.setAdapter(adapter, null);
        }
        else {
            //播放列表沒有曲目,顯示沒有音樂
            builder.setMessage(getString(R.string.no_song));
        }

        //設定該對話方塊是可以自動取消的,例如當用戶在空白處隨便點選一下,對話方塊就會關閉消失
        builder.setCancelable(true);

        //建立並顯示對話方塊
        builder.create().show();
    }
}

/*******************************************************************/
* 版權宣告
* 本教程只在CSDN安豆網釋出,其他網站出現本教程均屬侵權。

*另外,我們還推出了Arduino智慧硬體相關的教程,您可以在我們的網店跟我學Arduino程式設計中購買相關硬體。同時也感謝大家對我們這些碼農的支援。

*最後再次感謝各位讀者對安豆的支援,謝謝:)
/*******************************************************************/