Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

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

$
0
0

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智能硬件相关的教程,您可以在我们的网店安豆的杂货铺中购买相关硬件。同时也感谢大家对我们这些码农的支持。

*最后再次感谢各位读者对安豆的支持,谢谢:)
/*******************************************************************/

作者:anddlecn 发表于2016/9/28 22:47:35 原文链接
阅读:89 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles