今天的球员趁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的进度条。

效果图例如以下:


布局非常easy,例如以下所看到的:

<?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;//多线程,后台更新UIThread 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;}                    }  };@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//定义一个新线程。用来发送消息。通知更新UImyThread = new Thread(new MyThread());//绑定service;Intent serviceIntent = new Intent(this , MusicService.class);//假设未绑定,则进行绑定if(!mBound){bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);}//初始化播放buttonButton playButton = (Button)findViewById(R.id.playButton);playButton.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stubif(mBound){mService.play();}}});//初始化暂停buttonButton pauseButton = (Button)findViewById(R.id.pauseButton);pauseButton.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stub//首先须要判定绑定情况if(mBound){mService.pause();}}});    seekBar = (SeekBar)findViewById(R.id.seekbar);seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {//手动调节进度// TODO Auto-generated method stub//seekbar的拖动位置int dest = seekBar.getProgress();//seekbar的最大值int max = seekBar.getMax();//调用service调节播放进度mService.setProgress(max, dest);}@Overridepublic void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {// TODO Auto-generated method stub}@Overridepublic 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;@Overridepublic 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;          }      };     @Overridepublic 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;}@Overridepublic 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();            }    @Overridepublic IBinder onBind(Intent arg0) {// TODO Auto-generated method stub    //当绑定后。返回一个musicBinderreturn musicBinder;}class MyBinder extends Binder{public Service getService(){return MusicService.this;}}//初始化音乐播放void init(){//进入IdlemediaPlayer = new MediaPlayer();try {//初始化mediaPlayer.setDataSource(path);    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);  // prepare 通过异步的方式装载媒体资源mediaPlayer.prepareAsync();} catch (Exception e) {// TODO Auto-generated catch blocke.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();     }}

版权声明:本文博客原创文章,博客,未经同意,不得转载。

更多相关文章

  1. android 多个Fragment切换时的注意事项
  2. Android(安卓)Studio 3.2 都有哪些更新?这些关键点不要错过
  3. 【Android(安卓)开发】:UI控件之 ProgressBar 进度条的使用
  4. Recyclview实现仿京东淘宝金刚位带滚动进度条
  5. 【持续更新】Android(安卓)源码下载地点
  6. 深入探究Android定位(一)
  7. 请求网络数据后更新视图
  8. Android应用开发之(你必须知道的“文件上传时显示进度的
  9. Android上传文件到服务端并显示进度条

随机推荐

  1. Android系统中自带的图标
  2. Android中查看网卡设备信息
  3. 键盘按钮效果
  4. Android(安卓)Wifi Hotspot Manager Clas
  5. [转]Android(安卓)源代码结构
  6. Android7.0中文文档(API)-- AlphabetIndexe
  7. Android(安卓)源代码结构
  8. Android(安卓)Init Language(android init
  9. 制作android/cordova splash screen
  10. Android(安卓)EditText 限制文本框输入的