开发流程:
A,创建服务把想使用的方法暴露出来。
B,定义接口,bind调用时返回对象,在service 开启播放音乐实时更新进度条的位置
C,Activity 中创建hander 更新UI
【1】布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="click1"
android:text="播放" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="click2"
android:text="暂停" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="click3"
android:text="继续播放" />
<SeekBar
android:id="@+id/seekBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
【2】创建接口
interface Iservice {
//把想暴露的方法定义在接口里
public void callplayMusic();
public void callpauseMusic();
public void callrePlayMusic();
public void callplaySeekToPosition(int position);
}
【3】创建Service
A,onCredte 方法中是用MediaPlayer
B,为了调用Service 里面方法 Bind开启服务,提供Binder 对象 调用里面方法
C,定义方法,使用Binder的子类暴露出去。
public class MusicService extends Service {
private Timer timer;
private TimerTask task;
private MediaPlayer mediaPlayer;
//[2]把我们定义的中间人对象返回
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
@Override
public void onCreate() {
//[1]播放sd卡里面的小苹果音乐
mediaPlayer = new MediaPlayer();
super.onCreate();
}
// 播放音乐的方法
public void playMusic() {
try {
//[2]设置播放音乐的路径 设置数据 原:在sd卡
mediaPlayer.setDataSource("/mnt/sdcard/xpg.mp3");
//[3]准备播放
mediaPlayer.prepare();
//[4]播放音乐
mediaPlayer.start();
//[5]歌曲播放的同时 更新进度条
updateSeekBar();
} catch (Exception e) {
e.printStackTrace();
}
}
//更新进度条的方法
private void updateSeekBar() {
//[1]获取当前歌曲的总时长
final int duration = mediaPlayer.getDuration();
//[2]要不停的获取当前歌曲播放的进度 计时器 Timer
timer = new Timer();
task = new TimerTask() {
@Override
public void run() {
int currentPosition = mediaPlayer.getCurrentPosition();
//[3]更新进度条
Message msg = Message.obtain();
//[4]准备bundle
Bundle bundle = new Bundle(); //实际就是map
bundle.putInt("duration", duration);
bundle.putInt("currentPosition", currentPosition);
//[5]使用msg携带多条数据
msg.setData(bundle);
//[6]发消息 maniActivity的handlemessage方法就会执行
MainActivity.handler.sendMessage(msg);
//[7]给mediaplayer设置播放完成的监听
mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
System.out.println("歌曲播放完成了");
timer.cancel();
task.cancel();
}
});
}
};
//3秒后 执行task
timer.schedule(task, 1000,1000);
}
// 暂停音乐的方法
public void pauseMusic() {
mediaPlayer.pause();
}
// 继续播放音乐的方法
public void rePlayMusic() {
//继续播放也是start方法
mediaPlayer.start();
}
//设置歌曲播放位置的方法
public void playSeekToPosition(int position){
mediaPlayer.seekTo(position);
}
//[1]定义中间人的对象 (IBinder类型)
private class MyBinder extends Binder implements Iservice{
@Override
public void callplayMusic() {
//调用播放音乐的方法
playMusic();
}
@Override
public void callpauseMusic() {
//调用暂停音乐的方法
pauseMusic();
}
@Override
public void callrePlayMusic() {
//调用继续播放音乐的方法
rePlayMusic();
}
@Override
public void callplaySeekToPosition(int position) {
playSeekToPosition(position);
}
}
}
【3】MainActiivty 中调用:
A,获取控件,startService 开启服务确保能够在后台长期运行
B,BindService获取返回的接口对象,调用其中暴露给我们的方法,播放, 暂停。
C,seekBar.设置位置关联进度。
public class MainActivity extends Activity {
private Iservice iservice;//我们定义的中间人对象
private MyConn conn;
private static SeekBar seekBar;
public static Handler handler = new Handler(){
//这个方法处理消息的时候执行
public void handleMessage(android.os.Message msg) {
//[1]获取发消息携带的数据 数据是怎么发的 就怎么取 数据发的是什么类型就取什么类型
Bundle data = msg.getData();
//[2]获取歌曲的总时长和 当前进度
int duration = data.getInt("duration");
int currentPosition = data.getInt("currentPosition");
//[3]更新进度条
seekBar.setMax(duration);
seekBar.setProgress(currentPosition);
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//[1]调用startservice 保证服务在后台长期运行
Intent intent = new Intent(this,MusicService.class);
startService(intent);
//[2]想点击按钮的时候 调用服务里面的方法 获取我们在服务内部定义的中间人对象
conn = new MyConn();
bindService(intent, conn, BIND_AUTO_CREATE);
//[3]找到进度条
seekBar = (SeekBar) findViewById(R.id.seekBar1);
//[4]给seekbar设置监听
seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
//当拖动进度条停止 执行
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//在这个方法里面实现拖动到哪就播放歌曲对应的位置
iservice.callplaySeekToPosition(seekBar.getProgress());
}
//干开始托
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
}
});
}
//监视服务的状态
private class MyConn implements ServiceConnection {
//当连接服务成功后调用
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获取我们定义的中间人对象
iservice = (Iservice) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
@Override
protected void onDestroy() {
//当Activity销毁的时候 解绑服务
unbindService(conn);
super.onDestroy();
}
// 点击按钮实现音乐的播放
public void click1(View v) {
iservice.callplayMusic();
}
// 点击按钮实现音乐的暂停
public void click2(View v) {
iservice.callpauseMusic();
}
// 点击按钮实现音乐的继续播放
public void click3(View v) {
iservice.callrePlayMusic();
}
}