通过一段时间的学习,我制作了一个简单的音乐播放器,可以实现一些音乐功能,界面如下图所示:
1、界面的制作
2、页面制作完成后,则在MainActivity中将控件声明和初始化
private TextView musicStatus, musicTime, musicTotal;
private SeekBar seekBar;
private Button btnPlayOrPause, btnStop, btnQuit, btnNext, btnLast;
musicTime = (TextView) findViewById(R.id.MusicTime);
musicTotal = (TextView) findViewById(R.id.MusicTotal);
seekBar = (SeekBar) findViewById(R.id.MusicSeekBar);
btnPlayOrPause = (Button) findViewById(R.id.BtnPlayorPause);
btnStop = (Button) findViewById(R.id.BtnStop);
btnQuit = (Button) findViewById(R.id.BtnQuit);
btnLast = (Button) findViewById(R.id.BtnPre);
btnNext = (Button) findViewById(R.id.BtnNext);
musicStatus = (TextView) findViewById(R.id.MusicStatus);
3、本音乐播放器运用server来进行控制,以实现后台播放。所以,之后新建MusicService类,用来继承server。并在MusicService中定义MediaPlayer用来控制音乐的播放。
public MusicService() {
mediaPlayer = new MediaPlayer();
try {
musicIndex = 0;
mediaPlayer.setDataSource(musicDir[musicIndex]);
mediaPlayer.prepare();
mediaPlayer.setLooping(false);
} catch (Exception e) {
e.printStackTrace();
}
}
音乐播放的停止和开始等功能(上一首和下一首代码类似):
public void playOrPause() {
if (mediaPlayer.isPlaying()) {
mediaPlayer.pause();
} else {
mediaPlayer.start();
}
}
public void stop() {
if (mediaPlayer != null) {
mediaPlayer.stop();
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(musicDir[musicIndex]);
mediaPlayer.prepare();
mediaPlayer.seekTo(0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//下一首
public void nextMusic() {
if(mediaPlayer != null && musicIndex < 2) {
mediaPlayer.stop();
try {
mediaPlayer.reset();
mediaPlayer.setDataSource(musicDir[musicIndex+1]);
musicIndex++;
mediaPlayer.prepare();
mediaPlayer.seekTo(0);
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
}else {
Toast.makeText(this, "没有更多歌曲啦", Toast.LENGTH_SHORT).show();
}
}
4、Activity 和 Service 的通信
public MyBinder binder = new MyBinder();
public class MyBinder extends Binder {
MusicService getService() {
return MusicService.this;
}
}
// 在Activity中调用 bindService 保持与 Service 的通信
private void bindServiceConnection() {
Intent intent = new Intent(MainActivity.this, MusicService.class);
startService(intent);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}
// 回调onServiceConnected 函数,通过IBinder 获取 Service对象,实现Activity与 Service的绑定
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
musicService = ((MusicService.MyBinder) (service)).getService();
Log.i("musicService", musicService + "");
musicTotal.setText(time.format(musicService.mediaPlayer.getDuration()));
//musicService = ((MusicService.MyBinder)service).getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
musicService = null;
}
};
5、handler的使用。
public Handler handler = new Handler();
public Runnable runnable = new Runnable() {
@Override
public void run() {
musicTime.setText(time.format(musicService.mediaPlayer.getCurrentPosition()));
seekBar.setProgress(musicService.mediaPlayer.getCurrentPosition());
seekBar.setMax(musicService.mediaPlayer.getDuration());
musicTotal.setText(time.format(musicService.mediaPlayer.getDuration()));
handler.postDelayed(runnable, 200);
}
};
6、各个控件的监听事件
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (fromUser == true) {
musicService.mediaPlayer.seekTo(progress);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
btnPlayOrPause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (musicService.mediaPlayer != null) {
seekBar.setProgress(musicService.mediaPlayer.getCurrentPosition());
seekBar.setMax(musicService.mediaPlayer.getDuration());
}
// 由tag的变换来控制事件的调用
if (musicService.tag != true) {
btnPlayOrPause.setText("PAUSE");
musicStatus.setText("Playing");
musicService.playOrPause();
musicService.tag = true;
if (tag1 == false) {
animator.start();
tag1 = true;
} else {
imageView.clearAnimation(); //animator.resume();
}
} else {
btnPlayOrPause.setText("PLAY");
musicStatus.setText("Paused");
musicService.playOrPause();
imageView.clearAnimation(); //animator.pause();
musicService.tag = false;
}
if (tag2 == false) {
handler.post(runnable);
tag2 = true;
}
}
});
各个控件的监听大同小异,我就一一列举,最主要的是下面这个监听
// 停止服务时,必须解除绑定,写入btnQuit按钮中
btnQuit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.removeCallbacks(runnable);
unbindService(serviceConnection);
Intent intent = new Intent(MainActivity.this, MusicService.class);
stopService(intent);
try {
MainActivity.this.finish();
} catch (Exception e) {
}
}
});
7、从sdcard中读取音乐文件,
有两种不同的方式
private String[] musicDir = new String[]{"/mnt/sdcard/LOST.DIR/a1.mp3","/mnt/sdcard/LOST.DIR/b2.mp3"}; //虚拟机上的目录
// private String[] musicDir = new String[]{Environment.getExternalStorageDirectory().getAbsolutePath()+"/music/Honor.mp3",
// Environment.getExternalStorageDirectory().getAbsolutePath()+"/music/Jive_Cool.mp3"};读取外部储存卡(手机的目录)
8、大概代码和流程就是这些了,制作比较简单。下面是下载的地址:
下载地址:点击打开链接