此小案例是一个服务播放音乐的案例,吧服务的相关知识以及音频的相关知识串了一下。代码中有详细解析。
注 :播放的为指定位置的歌("mnt/sdcard/1.mp3")
1 主activity中:
package com.example.administrator.bindservicedemo;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.SeekBar;
public class MainActivity extends AppCompatActivity {
public static Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 获得数据
Bundle bundle = msg.getData();
during = bundle.getInt("during");
currentPosition = bundle.getInt("currentPosition");
sbSeekBar.setMax(during);
sbSeekBar.setProgress(currentPosition);
}
};
private Iinterface iinterface;
private MyServiceConnection conn;
private static SeekBar sbSeekBar;
private static int during;
private static int currentPosition;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initService(); // 加载页面直接开启服务
initUI();// 初始化控件
}
private void initUI() {
sbSeekBar = (SeekBar) findViewById(R.id.sb_seekbar);
// 事件的监听
sbSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// 当进度改变时调用
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
//开始拖动调用
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//拖动停止调用
iinterface.callSeekTo(seekBar.getProgress());
}
});
}
private void initService() {
// 混合方式开启服务
Intent in = new Intent(this, MusicService.class);
// 1 先start方式开启服务 保证服务长期后台运行
startService(in);
// 绑定服务 操纵通过中间人对象操纵服务内部的方法
conn = new MyServiceConnection();
bindService(in, conn, BIND_AUTO_CREATE);
}
public void startMusic(View view) {
//点击按钮播放音乐
iinterface.callpalyMusic();
}
public void PauseMusic(View view) {
//点击按钮暂停音乐
iinterface.callpauseMusic();
}
public void replayMusic(View view) {
//点击按钮继续音乐
iinterface.callreplayMusic();
}
@Override
protected void onDestroy() {
/*解绑服务(为了不报红色日志)
MainActivity has leaked ServiceConnection
com.example.administrator.bindservicedemo.MainActivity$MyServiceConnection@4a7a4710 that was originally bound here
android.app.ServiceConnectionLeaked: Activity com.example.administrator.bindservicedemo.MainActivity has leaked ServiceConnection com.example.administrator.bindservicedemo.
MainActivity$MyServiceConnection@4a7a4710 that was originally bound here*/
unbindService(conn);
super.onDestroy();
}
class MyServiceConnection implements ServiceConnection {
// 绑定成功时
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获取中间人对象
iinterface = (Iinterface) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
2 服务中
package com.example.administrator.bindservicedemo;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.Nullable;
import android.widget.Toast;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by Administrator on 2017/12/7.
* 此处先模拟音乐播放 等多媒体学完再完善
* "mnt/sdcard/1.mp3"
*/
public class MusicService extends Service {
private MediaPlayer mediaPlayer;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new MyBind();// 返回一个Ibind类的子类对象
}
@Override
public void onCreate() {
// 初始化mediaPlayer
mediaPlayer = new MediaPlayer();
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
public void PalyMusic() {
try {
mediaPlayer.reset();//
mediaPlayer.setDataSource("mnt/sdcard/1.mp3");
mediaPlayer.prepare();
mediaPlayer.start();//开启之前必须执行 准备函数
updateSeekBar();// 播放的时候跟新进度条
} catch (IOException e) {
e.printStackTrace();
}
}
public void pauseMusic() {
mediaPlayer.pause();
}
public void replayMusic() {
mediaPlayer.start();// 再次调用 重新播放
}
private void updateSeekBar() {
// 获得当前播放的总长度
final int during= mediaPlayer.getDuration();
// 获得对当前的长度(总不能拿一次 必须进行实时更新 使用timer定时器实时更新)
final Timer timer = new Timer();
final TimerTask task = new TimerTask() {
@Override
public void run() {
int currentPosition = mediaPlayer.getCurrentPosition();//当前播放位置
// 问题? 当前的两个值 怎样传到主activity ---- 使用handler
Message msg= Message.obtain();
// 使用msg发送多条数据
Bundle bundle = new Bundle();// bundle 封装了map
bundle.putInt("during",during);
bundle.putInt("currentPosition",currentPosition);
msg.setData(bundle);
MainActivity.handler.sendMessage(msg);
}
};
// 100毫秒后 每个1秒执行run方法
timer.schedule(task, 100, 1000);
//播放完成 timer 终止 不不执行 播放完成的监听
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
// timer timertask 取消
timer.cancel();
task.cancel();
}
});
}
//实现制定位置的播放
public void seekToPo(int position){
mediaPlayer.seekTo(position);
}
// 继承Ibind的子类实现接口中想暴露的方法
public class MyBind extends Binder implements Iinterface {
@Override
public void callpalyMusic() {
// 播放音乐
PalyMusic();
}
@Override
public void callpauseMusic() {
// 暂停音乐
pauseMusic();
}
@Override
public void callreplayMusic() {
// 继续播放
replayMusic();
}
@Override
public void callSeekTo(int po) {
seekToPo(po);
}
}
}
3 接口
package com.example.administrator.bindservicedemo;
/**
* Created by Administrator on 2017/12/8.
*/
public interface Iinterface {
public void callpalyMusic();
public void callpauseMusic();
public void callreplayMusic();
public void callSeekTo(int po);
}
4 main 的xml
实现了背景播放 ,拖动播放 以及简单 功能