写了个比较简单的音乐播放器用来练习一下Service的使用方法,以及Android系统内置的多媒体播放的类MediaPlay的使用方法。
下面看一下程序的运行效果:
下面直接贴源码:
MainActivity.java
public class MainActivity extends AppCompatActivity {
private MusicService.MyBinder binder;
private Myconn conn;
private static SeekBar mSeekBar;
private static TextView textViewCurrent;
private static TextView textViewTotal;
//使用mHandler接收从Service发回的歌曲播放的当前进度与总进度
public static Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int current = msg.getData().getInt("current");
int total = msg.getData().getInt("total");
textViewCurrent.setText(getTime(current));
textViewTotal.setText(getTime(total));
mSeekBar.setMax(total);
mSeekBar.setProgress(current);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSeekBar = (SeekBar) findViewById(R.id.seekBar);
textViewCurrent = (TextView) findViewById(R.id.textview_current);
textViewTotal = (TextView) findViewById(R.id.textview_total);
Intent intent = new Intent(this,MusicService.class);
conn = new Myconn();
bindService(intent, conn,BIND_AUTO_CREATE);
//设置SeekBar的监听
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
int currentProgress = seekBar.getProgress();
textViewCurrent.setText(getTime(currentProgress));
binder.callSetMusicPosition(currentProgress);
}
});
}
//开始播放
public void clickPlay(View v){
binder.callPlayMusic();
}
//暂停播放
public void clickPause(View v){
binder.callPauseMusic();
}
//继续播放
public void clickStart(View v){
binder.callStartMusic();
}
//当Activity销毁的时候接触与服务的绑定
@Override
protected void onDestroy() {
super.onDestroy();
//解绑服务
unbindService(conn);
}
//实现ServiceConnectionj实现实接口
private class Myconn implements ServiceConnection{
//Activity与Service成功绑定的时候调用
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//获取Service中创建的Binder对象
binder = (MusicService.MyBinder) iBinder;
}
//Activity与Service断开连接的时候调用
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.i("wk","断开连接了");
}
}
//时间转换
private static String getTime(int total) {
SimpleDateFormat sdf = new SimpleDateFormat("mm:ss");
Date date= new Date(total);
return sdf.format(date);
}
}
MusicService.java
/**
* Created by wangke on 2017/2/19.
*/
public class MusicService extends Service {
private MediaPlayer mediaPlayer;
@Nullable
@Override
public IBinder onBind(Intent intent) {
//将Binder的实现类返回
return new MyBinder();
}
//Service创建时调用
@Override
public void onCreate() {
super.onCreate();
String Path = Environment.getExternalStorageDirectory().toString();
mediaPlayer = new MediaPlayer();
try {
mediaPlayer.setDataSource(Path + "/misc.mp3");
mediaPlayer.prepare();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
new Timer().schedule(new TimerTask() {
@Override
public void run() {
Message msg = Message.obtain();
Bundle bundle = new Bundle();
bundle.putInt("current",mediaPlayer.getCurrentPosition());
bundle.putInt("total",mediaPlayer.getDuration());
msg.setData(bundle);
MainActivity.mHandler.sendMessage(msg);
}
},100,1000);
}
//在每次服务启动的时候调用
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
//释放播放器资源
mediaPlayer.release();
}
//开始播放音乐
public void playMusic() {
mediaPlayer.start();
Toast.makeText(getApplicationContext(), "开始播放音乐", Toast.LENGTH_SHORT).show();
}
//暂停播放音乐
public void pauseMusic() {
if(mediaPlayer.isPlaying()){
mediaPlayer.pause();
}
Toast.makeText(getApplicationContext(), "暂停播放音乐", Toast.LENGTH_SHORT).show();
}
//继续播放音乐
public void startMusic() {
if(!mediaPlayer.isPlaying()){
mediaPlayer.start();
}
Toast.makeText(getApplicationContext(), "继续播放音乐", Toast.LENGTH_SHORT).show();
}
private void setMusicPosition(int position) {
mediaPlayer.seekTo(position);
}
//创建Binder的实现类,在里面创建需要在Activity中调用的方法
public class MyBinder extends Binder {
public void callPlayMusic() {
playMusic();
}
public void callPauseMusic() {
pauseMusic();
}
public void callStartMusic() {
startMusic();
}
public void callSetMusicPosition(int position){
setMusicPosition(position);
}
}
}
下面回顾下Service的相关知识:
startService方法开启服务的特点:
- 服务通过startService的方式开启,第一次点击按钮开启服务器,会执行服务的onCreate 和 onStart方法。
- 第二次点击按钮开启服务后只会执行 onStartCommand方法
bindService 方式开启服务的特点
- 当点击按钮第一次开启服务会执行服务的onCreate方法 和 onBind()方法
- 当第二次点击按钮在调用bindservice 服务没有响应
- 当Activity销毁的时候服务也跟着销毁
bindService不能多次解除绑定否则会报错
因此实现在后台播放音乐的功能还需要使用混合模式来开启一个服务,在bindService前使用startService方法开启服务。
下面简单梳理一下在Activity中使用bindservice方式调用服务里的方法的几个过程(拿上面Demo为例):
(1):创建一个服务,并在里面声明需要Activity进行调用的方法
//开始播放音乐
public void playMusic() {
mediaPlayer.start();
Toast.makeText(getApplicationContext(), "开始播放音乐", Toast.LENGTH_SHORT).show();
}
//暂停播放音乐
public void pauseMusic() {
if(mediaPlayer.isPlaying()){
mediaPlayer.pause();
}
Toast.makeText(getApplicationContext(), "暂停播放音乐", Toast.LENGTH_SHORT).show();
}
//继续播放音乐
public void startMusic() {
if(!mediaPlayer.isPlaying()){
mediaPlayer.start();
}
Toast.makeText(getApplicationContext(), "继续播放音乐", Toast.LENGTH_SHORT).show();
}
private void setMusicPosition(int position) {
mediaPlayer.seekTo(position);
}
(2):创建Binder的实现类,在里面创建需要在Activity中调用的方法
public class MyBinder extends Binder {
public void callPlayMusic() {
playMusic();
}
public void callPauseMusic() {
pauseMusic();
}
public void callStartMusic() {
startMusic();
}
public void callSetMusicPosition(int position){
setMusicPosition(position);
}
}
(3):在onBind( )方法中将创建好的Binder对象返回
@Override
public IBinder onBind(Intent intent) {
//将Binder的实现类返回
return new MyBinder();
}
(4):在Activity的onCreate( )方法中调用bindService方法来获取在service中定义好的Binder对象
Intent intent = new Intent(this,MusicService.class);
conn = new Myconn();
bindService(intent, conn,BIND_AUTO_CREATE);
(4.1):实现ServiceConnection接口在onServiceConnected方法中获取在Service中定义好的Binder对象
private class Myconn implements ServiceConnection{
//Activity与Service成功绑定的时候调用
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
//获取Service中创建的Binder对象
binder = (MusicService.MyBinder) iBinder;
}
//Activity与Service断开连接的时候调用
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.i("wk","断开连接了");
}
}
(5):获取到Binder对象之后,就可以在相应的事件中调用Service中的相关方法
//开始播放
public void clickPlay(View v){
binder.callPlayMusic();
}
以上就是在Activity中调用Service中方法的实现过程。
MediaPlay类的相关用法
1.获得MediaPlay实例:
MediaPlayer mediaPlayer = new MediaPlayer();
MediaPlayer mediaPlayer = MediaPlayer.create(getApplicationContext(),R.raw.music.mp3)
2.设置播放的文件:
//设置文件资源的三种来源:
//1.网络资源
//2.存储目录中
//3.当前工程下的res资源
mediaPlayer.setDataSource(Path + "/misc.mp3");
3.对MediaPlay控制的相关方法:
prepare() //使播放器进入准备状态,如果是使用create方式创建的MediaPlayer内部已经调用,不需要再次调用
start() //进行文件播放的方法
pause() //暂停播放
stop() //停止播放
release() //可以释放播放器占用的资源,一旦确定不再使用播放器时应当尽早调用它释放资源。
reset()可以使播放器从Error状态中恢复过来,重新会到闲置状态。