首页 > 代码库 > android 利用 service 实现音乐播放

android 利用 service 实现音乐播放

今天的播放器利用了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 = http://www.mamicode.com/new Bundle();>

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();
     }
}