0
点赞
收藏
分享

微信扫一扫

【达内课程】音乐播放器2.0(中)

接着 ​​音乐播放器2.0(上)​​ 对 音乐播放器1.0做改造。把音乐播放改为使用 Service,实现可以后台播放音乐。

开发步骤是按照 ​​【达内课程】Service​​ 中总结的开发步骤做的。

1、新建 PlayMusicService
新建 PlayMusicService 继承 Service,放到 Service 文件夹下。

public class PlayMusicService extends Service {
public PlayMusicService() {
}

@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}

检查下 AndroidManifest.xml 中是否注册了

<service
android:name=".Service.PlayMusicService"
android:enabled="true"
android:exported="true"/>

2、创建 IMusicPlayer 接口,定义要实现的方法
创建 IMusicPlayer 接口,并在接口中定义由 Service 实现功能,但由 Activity 调用的方法。例如点击一个播放按钮,当然是由 Activity 调用的,但是为了保证优先级,这些方法应该在 Service 中定义。

public interface IMusicPlayer<T> {
//播放歌曲
void play();

/**
* 播放指定position对应的歌曲
*
* @param position
*/
void play(int position);

//暂停歌曲
void pause();

//下一首歌曲
void next();

//上一首歌曲
void previous();

/**
* 获取当前播放歌曲的总时长
*
* @return 当前播放歌曲的总时长
*/
int getDuration();

/**
* 获取当前播放到的位置
*
* @return 当前播放到的位置 单位:毫秒
*/
int getCurrentPosition();

/**
* 获取当前正在播放的歌曲的索引
*/
int getCurrentMusicPosition();

/**
* 获取当前播放歌曲的播放状态
*
* @return 当前播放歌曲的播放状态,true:正在播放;false:停止播放
*/
boolean isPlaying();
}

这些方法都是我们在 MainActivity 中使用的。如果一次性写不完可以用到再添加。把这个文件放在Util(Utility工具文件夹)或Core(核心文件夹)中。

3、在 PlayMusicService 中创建内部类 IBinder类,为和 Activity 连接做准备
在 PlayMusicService 中创建内部类 IBinder 类,继承自 Binder,实现 IMusicPlayer接口,并实现接口中的方法。

然后 PlayMusicService 的​​onBind()​​方法中创建 InnerBiner 对象,并作为该方法的返回值。

public class PlayMusicService extends Service {
public PlayMusicService() {
}

@Override
public IBinder onBind(Intent intent) {
InnerBinder binder = new InnerBinder();
return binder;
}

private class InnerBinder extends Binder implements IMusicPlayer {

@Override
public void play() {
Log.d("Music", "由Service调用play()");
}

@Override
public void play(int position) {
Log.d("Music", "由Service调用play(int position)");
}

@Override
public void pause() {

}

@Override
public void previous() {

}

@Override
public void next() {

}

@Override
public int getCurrentMusicPosition() {
return 0;
}

@Override
public int getCurrentPosition() {
return 0;
}

@Override
public int getDuration() {
return 0;
}

@Override
public boolean isPlaying() {
return false;
}
}
}

4、MainActivity 中绑定 Service
MainActivity 中创建内部类 InnerServiceConnection,实现 ServiceConnection 接口。声明 IMusicPlayer 类型的全局变量 player,并在 InnerServiceConnection 中 ​​​onServiceConnected()​​方法中通过第二个参数直接赋值,并强制转换类型。

/**
* 与Service实现绑定时建立的连接对象
* 声明成内部类或接口类型都可以
*/
private ServiceConnection conn;
/**
* 调用Service中实现的功能的对象
*/
private IMusicPlayer player;


private class InnerServiceConnection implements ServiceConnection {

@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
player = (IMusicPlayer)iBinder;
}

@Override
public void onServiceDisconnected(ComponentName componentName) {

}
}

​onCreate()​​​方法中增加绑定 Service 的方法:​​bindService()​

//绑定Service
Intent intent = new Intent(this, PlayMusicService.class);
conn = new InnerServiceConnection();
bindService(intent,conn,BIND_AUTO_CREATE);

5、MainActivity 中调用 PlayMusicService 中的方法

MainActivity 中需要调用 PlayMusicService 中的方法时,直接用 player 调用即可。所以可以把 onClick 中代码改为:

//按钮监听
private class InnerClassOnClickListener implements View.OnClickListener {
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.ib_play:
if (player.isPlaying()) {
player.pause();
} else {
player.play();
}
break;
case R.id.ib_previous:
player.previous();
break;
case R.id.ib_next:
player.next();
break;
}
}
}

6、MainActivity 中的 onDestroy 中解除与 Service 的绑定

@Override
protected void onDestroy() {
//解除与Service的绑定
unbindService(conn);
//停止更新进度的线程
stopThread();
//释放资源
mediaPlayer.release();
mediaPlayer = null;

super.onDestroy();
}

现在运行程序,点击播放按钮,输出日志如下
【达内课程】音乐播放器2.0(中)_内部类
7、PlayMusicService 中完善播放器的方法
PlayMusicService 中完善播放器的方法,把 MainActivity 中的相应方法、相关变量拿过来,稍作修改。有些改变页面上图标的地方,例如 ​​​play()​​的时候会把暂停按钮改成播放按钮,这个操作可以放在 Activity 的 onClick() 事件中,这样写比较方便。

内部类 InnerBinder 直接调用上面写的方法,同时在 ​​onDestroy​​ 方法执行时释放相关资源。

相应的 MainActivity 中的相应方法、相关变量都可以删除了。调用方法的地方可以使用刚刚声明的 IMusicPlayer 类型的全局变量 player 直接调用。

8、在 MainActivity 中开启一个线程,查询 service 中状态
显示歌曲的时候 Activity 是主动方,Service 没有办法主动告诉 Activity 自己目前播放的是哪首歌,因此应该在 MainActivity 中开启一个线程,每隔 1 秒查询 Service 中状态。同时增加开启线程,关闭线程的方法。可以对之前的 UpdateProgressThread 进行修改。

把格式化时间的方法单独放到一个 CommonUtil 的工具类中方便使用。

在点击播放/暂停,上一首,下一首等按钮时,开启或关闭相应线程即可,同时在​​onDestroy()​​方法中停止线程。

这部分代码先不放了,有点繁琐,下一章直接上完整代码。


举报

相关推荐

0 条评论