今天的播放器利用了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(); } }
android 利用 service 实现音乐播放
时间: 2024-10-08 18:12:04