您的位置:首页 > 移动开发 > Android开发

android 利用 service 实现音乐播放

2014-06-22 21:51 573 查看
今天的播放器利用了service,播放音乐在service端,进度条在activity端,因此主要的工作就是activity和service的交互,本文将利用IBinder进行交互,主要是activity可以调用service的函数,可以参考我的这篇博客

本文关键点:利用利用IBinder实现activity 控制service

实现功能:

1 控制播放进度:

activity调用service的函数,对MediaPlayer进行控制。包括启动时的播放和滑动seekbar时,对MediaPlayer进行设置,达到控制播放进度的控制。

2 播放进度更新:

在activity开启多线程,后台每隔100ms就发送一次message,在UI线程中利用handler对message进行判定,之后activity调用service的函数,得到播放的进度(百分比),及时更新seekbar的进度条。

效果图如下:



布局很简单,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="play"/>

<Button
android:id="@+id/playButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="play"
/>

<Button
android:id="@+id/pauseButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="pause"
/>

<SeekBar
android:id="@+id/seekbar"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:max="100"
android:progress="10"
/>

</LinearLayout>
activity的代码如下:

<pre name="code" class="java">public class MainActivity extends Activity {

Boolean mBound = false;

MusicService mService;

SeekBar seekBar;

//多线程,后台更新UI
Thread myThread;

//控制后台线程退出
boolean playStatus = true;

//处理进度条更新
Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg){
switch (msg.what){
case 0:
//从bundle中获取进度,是double类型,播放的百分比
double progress = msg.getData().getDouble("progress");

//根据播放百分比,计算seekbar的实际位置
int max = seekBar.getMax();
int position = (int) (max*progress);

//设置seekbar的实际位置
seekBar.setProgress(position);
break;
default:
break;
}

}
};

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//定义一个新线程,用来发送消息,通知更新UI
myThread = new Thread(new MyThread());

//绑定service;
Intent serviceIntent = new Intent(this , MusicService.class);

//如果未绑定,则进行绑定
if(!mBound){
bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
}

//初始化播放按钮
Button playButton = (Button)findViewById(R.id.playButton);
playButton.setOnClickListener(new OnClickListener(){

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
if(mBound){
mService.play();
}
}

});

//初始化暂停按钮
Button pauseButton = (Button)findViewById(R.id.pauseButton);
pauseButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
//首先需要判定绑定情况
if(mBound){
mService.pause();
}
}
});

seekBar = (SeekBar)findViewById(R.id.seekbar);
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//手动调节进度
// TODO Auto-generated method stub
//seekbar的拖动位置
int dest = seekBar.getProgress();
//seekbar的最大值
int max = seekBar.getMax();
//调用service调节播放进度
mService.setProgress(max, dest);
}

@Override
public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
// TODO Auto-generated method stub

}

@Override
public void onStartTrackingTouch(SeekBar arg0) {
// TODO Auto-generated method stub

}

});

}

//实现runnable接口,多线程实时更新进度条
public class MyThread implements Runnable{

//通知UI更新的消息

//用来向UI线程传递进度的值
Bundle data = new Bundle();

//更新UI间隔时间
int milliseconds = 100;
double progress;
@Override
public void run() {
// TODO Auto-generated method stub

//用来标识是否还在播放状态,用来控制线程退出
while(playStatus){

try {
//绑定成功才能开始更新UI
if(mBound){

//发送消息,要求更新UI

Message msg = new Message();
data.clear();

progress = mService.getProgress();
msg.what = 0;

data.putDouble("progress", progress);
msg.setData(data);
mHandler.sendMessage(msg);
}
Thread.sleep(milliseconds);
//Thread.currentThread().sleep(milliseconds);
//每隔100ms更新一次UI

} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}
}

}

/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {

@Override
public void onServiceConnected(ComponentName className,
IBinder binder) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
MyBinder myBinder = (MyBinder) binder;

//获取service
mService = (MusicService) myBinder.getService();

//绑定成功
mBound = true;

//开启线程,更新UI
myThread.start();
}

@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
public void onDestroy(){
//销毁activity时,要记得销毁线程
playStatus = false;
super.onDestroy();
}

}



service的代码如下:

public class MusicService extends Service {

IBinder musicBinder  = new MyBinder();

//获取到activity的Handler,用来通知更新进度条
Handler mHandler;

//播放音乐的媒体类
MediaPlayer mediaPlayer;

//本地歌曲的路径
String path = "/storage/sdcard1/Music/浪漫满屋.mp3";

private String TAG = "MyService";

@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() executed");

init();

}

@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
//当绑定后,返回一个musicBinder
return musicBinder;
}

class MyBinder extends Binder{

public Service getService(){
return MusicService.this;
}
}

//初始化音乐播放
void init(){
//进入Idle
mediaPlayer = new MediaPlayer();
try {
//初始化
mediaPlayer.setDataSource(path);

mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

// prepare 通过异步的方式装载媒体资源
mediaPlayer.prepareAsync();

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

//返回当前的播放进度,是double类型,即播放的百分比
public double getProgress(){
int position = mediaPlayer.getCurrentPosition();

int time = mediaPlayer.getDuration();

double progress = (double)position / (double)time;

return progress;
}

//通过activity调节播放进度
public void setProgress(int max , int dest){
int time = mediaPlayer.getDuration();
mediaPlayer.seekTo(time*dest/max);
}

//测试播放音乐
public void play(){
if(mediaPlayer != null){
mediaPlayer.start();
}

}
//暂停音乐
public void pause() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.pause();
}
}

//service 销毁时,停止播放音乐,释放资源
@Override
public void onDestroy() {
// 在activity结束的时候回收资源
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
super.onDestroy();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: