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相同,则认为两者相同。重写MusicItem
的equals()
方法,当使用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
有两种方式添加播放列表:
单击音乐项,将单首音乐添加到播放列表中;
长按音乐项,界面切换成
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智能硬件相关的教程,您可以在我们的网店安豆的杂货铺中购买相关硬件。同时也感谢大家对我们这些码农的支持。
*最后再次感谢各位读者对安豆
的支持,谢谢:)
/*******************************************************************/