像音乐这种耗时的和适合后台操作的应当放在Service中进行操作,而不是放在Activity,下面就介绍使用Service的音乐播放器
先创建一个MusicService,在Android Studio中,点击包名右键New-->Service-->Service
如果是按照上面的方法创建的Service,配置清单中会自动生成 改Service的声明
在MusicService中的Java代码,里面包含了音乐的相关操作复写了onCreate()用于初始化播放器
public class MusicService extends Service {
private String path = "mnt/sdcard/123.mp3";
private MediaPlayer player;
@Override
public IBinder onBind(Intent intent) {
//当执行完了onCreate后,就会执行onBind把操作歌曲的方法返回
return new MyBinder();
}
@Override
public void onCreate() {
super.onCreate();
//这里只执行一次,用于准备播放器
player = new MediaPlayer();
try {
player.setDataSource(path);
//准备资源
player.prepare();
} catch (IOException e) {
e.printStackTrace();
}
Log.e("服务", "准备播放音乐");
}
//该方法包含关于歌曲的操作
public class MyBinder extends Binder {
//判断是否处于播放状态
public boolean isPlaying(){
return player.isPlaying();
}
//播放或暂停歌曲
public void play() {
if (player.isPlaying()) {
player.pause();
} else {
player.start();
}
Log.e("服务", "播放音乐");
}
//返回歌曲的长度,单位为毫秒
public int getDuration(){
return player.getDuration();
}
//返回歌曲目前的进度,单位为毫秒
public int getCurrenPostion(){
return player.getCurrentPosition();
}
//设置歌曲播放的进度,单位为毫秒
public void seekTo(int mesc){
player.seekTo(mesc);
}
}
}
布局中只添加一个按钮和进度条
<Button
android:id="@+id/play"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="play"
android:text="播放" />
<SeekBar
android:id="@+id/sb"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
在MainActivity中的Java代码
public class MainActivity extends AppCompatActivity {
private MyConnection conn;
private MusicService.MyBinder musicControl;
private Button playBtn;
private SeekBar seekBar;
private static final int UPDATE_PROGRESS = 0;
//使用handler定时更新进度条
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_PROGRESS:
updateProgress();
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
playBtn = (Button) findViewById(R.id.play);
seekBar = (SeekBar) findViewById(R.id.sb);
Intent intent3 = new Intent(this, MusicService.class);
conn = new MyConnection();
//使用混合的方法开启服务,
startService(intent3);
bindService(intent3, conn, BIND_AUTO_CREATE);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
//进度条改变
if (fromUser){
musicControl.seekTo(progress);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
//开始触摸进度条
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//停止触摸进度条
}
});
}
private class MyConnection implements ServiceConnection {
//服务启动完成后会进入到这个方法
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获得service中的MyBinder
musicControl = (MusicService.MyBinder) service;
//更新按钮的文字
updatePlayText();
//设置进度条的最大值
seekBar.setMax(musicControl.getDuration());
//设置进度条的进度
seekBar.setProgress(musicControl.getCurrenPostion());
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
@Override
protected void onResume() {
super.onResume();
//进入到界面后开始更新进度条
if (musicControl != null){
handler.sendEmptyMessage(UPDATE_PROGRESS);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//退出应用后与service解除绑定
unbindService(conn);
}
@Override
protected void onStop() {
super.onStop();
//停止更新进度条的进度
handler.removeCallbacksAndMessages(null);
}
//更新进度条
private void updateProgress() {
int currenPostion = musicControl.getCurrenPostion();
seekBar.setProgress(currenPostion);
//使用Handler每500毫秒更新一次进度条
handler.sendEmptyMessageDelayed(UPDATE_PROGRESS, 500);
}
//更新按钮的文字
public void updatePlayText() {
if (musicControl.isPlaying()) {
playBtn.setText("暂停");
handler.sendEmptyMessage(UPDATE_PROGRESS);
} else {
playBtn.setText("播放");
}
}
//调用MyBinder中的play()方法
public void play(View view) {
musicControl.play();
updatePlayText();
}
}
最后别忘了添加读写内存卡的权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
效果图
既然说到音乐播放器了,就顺便说说如何播放网络上的音乐,这是个很重要的功能,其实跟播放本地的差不多,只是用了异步准备,使用setOnPreparedListener()监听是否准备完成才去播放
private MediaPlayer player;
if (player == null){
//如果为空就new我一个
player = new MediaPlayer();
try {
player.setDataSource("http://www.w3school.com.cn/i/horse.mp3");
//异步准备
player.prepareAsync();
//添加准备好的监听
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
//如果准备好了,就会进行这个方法
mp.start();
}
});
} catch (IOException e) {
e.printStackTrace();
}
}else {
//判断是否处于播放状态
if (player.isPlaying()){
player.pause();
}else {
player.start();
}
}
要访问网络,就别忘了加权限
<uses-permission android:name="android.permission.INTERNET"/>