zoukankan      html  css  js  c++  java
  • 6.1.3 控制服务中的MediaPlayer

       然而,当使用一个服务时,从而向用户的活动向MediaPlayer发出命令变得更为复杂。

       为了能够控制MediaPlayer,需要把该活动与服务绑定在一起。一旦这样做,由于活动和服务在相同的进程中运行,因此可以直接调用该服务中的方法。如果正在创建一个远程服务,那么必须采起更深入一步的步骤。

       我们在上述活动中添加一个按钮,其标签为“have fun”。当单击这个按钮时,会使得MediaPlayer倒回来几秒中,然后继续播放音频文件。

       首先把该按钮添加到布局XML:

     1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     android:layout_width="match_parent"
     3     android:layout_height="match_parent"
     4     android:orientation="vertical"
     5     >
     6  <TextView 
     7      android:text="Backgroung Audio Player"
     8      android:layout_width="fill_parent"
     9      android:layout_height="wrap_content"></TextView>
    10  <Button 
    11      android:layout_width="wrap_content"
    12      android:layout_height="wrap_content"
    13      android:id="@+id/StartPlayerbackButton"
    14      android:text="Start Playerback"/>
    15  <Button 
    16      android:layout_width="wrap_content"
    17      android:layout_height="wrap_content"
    18      android:id="@+id/StopPlayerbackButton"
    19      android:text="Stop Playerback"/>
    20  <Button 
    21      android:layout_width="wrap_content"
    22      android:layout_height="wrap_content"
    23      android:id="@+id/HaveFunButton"
    24      android:text="Have Fun"/>
    25 </LinearLayout>

         然而在活动中会得到该按钮的引用,并且把它的OnClickListener设置为活动本身,就像现有的按钮一样。

     1 package com.nthm.androidtestActivity;
     2 
     3 import com.nthm.androidtest.R;
     4 import com.nthm.androidtestService.BackgroundAudioService;
     5 import android.app.Activity;
     6 import android.content.Intent;
     7 import android.os.Bundle;
     8 import android.view.View;
     9 import android.view.View.OnClickListener;
    10 import android.widget.Button;
    11 
    12 public class BackgroundAudioActivity extends Activity implements
    13         OnClickListener {
    14     private Button startPlaybackButton;
    15     private Button stopPlaybackButton;
    16     private Button haveFunButton;
    17     private Intent playbackServiceIntent;
    18     @Override
    19     protected void onCreate(Bundle savedInstanceState) {
    20         super.onCreate(savedInstanceState);
    21         setContentView(R.layout.backgroundaudioactivity);
    22         startPlaybackButton=(Button) findViewById(R.id.StartPlayerbackButton);
    23         stopPlaybackButton=(Button) findViewById(R.id.StopPlayerbackButton);
    24         haveFunButton=(Button) findViewById(R.id.HaveFunButton);
    25         startPlaybackButton.setOnClickListener(this);
    26         stopPlaybackButton.setOnClickListener(this);
    27         haveFunButton.setOnClickListener(this);
    28         playbackServiceIntent=new Intent(this, BackgroundAudioService.class);
    29     }

        为了使此按钮与服务中运行的MediaPlayer进行交互,必须绑定到该服务。完成该操作的方式是采用bindService方法。该方法接受一个意图;事实上,可以重用启动该服务的playbackServiceIntent、一个ServiceConnection对象以及一些指明当该服务没有运行时应该做什么的标志。

        在活动的onClick方法中,当按下startPlaybackButton时,在启动服务之后就会立刻绑定他。当调用stopPlaybackButton时,将与服务解除绑定。

     1     @Override
     2     public void onClick(View v) {
     3       if(v==startPlaybackButton){
     4           //startService(playbackServiceIntent);
     5           //finish();
     6           bindService(playbackServiceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
     7       }else if(v==stopPlaybackButton){
     8           //stopService(playbackServiceIntent);
     9           //finish();
    10           unbindService(serviceConnection);
    11       }

         你可能会注意到其中使用了一个没有定义的新对象:serviceConnection。过一会儿将对该对象进行介绍。

         接下来还需要完成onClick方法。因为该活动也被设置为新按钮的OnClickListener。所以同样应该处理这种情况以完成onClick方法。

    1         else if(v==haveFunButton){
    2           baService.havaFun();
    3       }
    4     }

        在新的部分中使用了另一个新对象:baService。baService是BackgroundAudioService类型的对象。现在仅仅是声明它,在创建serviceConnection对象时再介绍如何创建它。

    1     private BackgroundAudioService baService;

        如前所述,我们仍然没有声明和实例化一个称为serviceConnection的对象。serviceConnection是一个ServiceConnection类型的对象,他是一个接口,用于监听所绑定服务的状态。

        现在开始介绍如何创建serviceConnection

    1     private ServiceConnection serviceConnection=new ServiceConnection() {

        当通过一条bindService命令建立了与服务的连接,且该bindService命令把这个对象命名为serviceConnection(如同在bindService调用中所做的一样)时,将调用如下所示的onServiceConnected方法。

        向该方法传递一个IBinder对象,其实际上是从服务本身创建和提交的。在当前情况下,这个IBinder对象将使BackgroundAudioServiceBinder类型,我们将在服务中创建它。它将有一个方法用于返回我们的服务本身,称为getService。可以对该方法返回的对象直接操作,正如我们在单击haveFunButton时所做的一样。

    1         @Override
    2         public void onServiceConnected(ComponentName name, IBinder service) {
    3             baService=((BackgroundAudioService.BackgroundAudioServiceBinder)service).getService();
    4         }

        还需要一恶搞onServiceDisconnected方法来处理与服务断开时的情况。

    1         @Override
    2         public void onServiceDisconnected(ComponentName name) {
    3             baService=null;
    4         }
    5     };
    6 }

        现在可以关注在服务本身中需要做出的更改。

     1 package com.nthm.androidtestService;
     2 
     3 import com.nthm.androidtest.R;
     4 import android.app.Service;
     5 import android.content.Intent;
     6 import android.media.MediaPlayer;
     7 import android.media.MediaPlayer.OnCompletionListener;
     8 import android.os.Binder;
     9 import android.os.IBinder;
    10 
    11 public class BackgroundAudioService extends Service implements
    12         OnCompletionListener {
    13     private MediaPlayer mediaPlayer;

         需要在服务中做出的第一个改动是创建一个内部类,其扩展Binder,在请求时可以返回服务本身。

    1 public class BackgroundAudioServiceBinder extends Binder{
    2         public    BackgroundAudioService getService(){
    3             return BackgroundAudioService.this;
    4         }
    5     }

       随后,将其实例化为一个对象,称为basBinder。

    1 private final IBinder basBinder=new BackgroundAudioServiceBinder();

        并且重写onBind的实现以返回它。

    1     @Override
    2     public IBinder onBind(Intent intent) {
    3         return basBinder;
    4     }

        以上就是实现绑定多需要完成的工作。现在只需要处理“Having Fun”按钮。

        如前所述,当单击haveFunButton时,我们希望MediaPlayer倒回来几秒钟,在当前实现中,它将倒回2500毫秒或2.5秒。

    1     public void havaFun(){
    2         if(mediaPlayer.isPlaying()){
    3             mediaPlayer.seekTo(mediaPlayer.getCurrentPosition()-2500);
    4         }                                                                             
    5     }

       以上就是服务中的更新。下面是除此之外的其他代码。

     1     @Override
     2     public void onCreate() {
     3         super.onCreate();
     4         mediaPlayer=MediaPlayer.create(this, R.raw.music);
     5         mediaPlayer.setOnCompletionListener(this);
     6     }
     7 
     8     @Override
     9     public int onStartCommand(Intent intent, int flags, int startId) {
    10         if(!mediaPlayer.isPlaying()){
    11             mediaPlayer.start();
    12         }
    13         return START_STICKY;
    14     }
    15 
    16     @Override
    17     public void onDestroy() {
    18         if(mediaPlayer.isPlaying()){
    19             mediaPlayer.stop();
    20         }
    21         mediaPlayer.release();
    22         super.onDestroy();
    23     }
    24     @Override
    25     public void onCompletion(MediaPlayer mp) {
    26          stopSelf();
    27     }
    28 }

        既然已经搭建好了基础,现在就可以向服务中添加任何喜欢的功能,同时通过绑定服务,可以直接从活动中调用havaFun等各种方法。如果没有绑定服务,那么除了启动和停止该服务之外,我们将不能做任何其他事情。

        上述示例提供了一个良好的起点。可用于搭建在后台播放音频文件的应用程序,即当音频持续播放时允许用户继续执行其他的任务。可以对第二个示例进行扩展,以构建一个具有完整功能的音频播放应用程序。

  • 相关阅读:
    010_STM32CubeMXADC
    009_STM32CubeMXPWM
    008_STM32CubeMX定时器中断
    007_STM32CubeMX外部中断
    006_STM32CubeMX按键输入
    005_STM32CubeMX串口
    004_STM32CubeMX官方例程
    003_STM32CubeMX点灯
    002_STM32CubeMX配置基础工程
    006_word发表博客到博客园中
  • 原文地址:https://www.cnblogs.com/ZSS-Android/p/3941992.html
Copyright © 2011-2022 走看看