Поведение службы привязки, MP по-прежнему воспроизводит несколько файлов

#android #service #bind

#Android #Обслуживание #привязка

Вопрос:

У меня есть служба, привязанная к действию. Действие представляет собой ListView набор воспроизводимых файлов. Служба воспроизводит определенный аудиофайл, переданный из Activty . В предыдущей версии у меня не было привязки службы, поэтому при многократном нажатии на элемент воспроизведения возникало несколько экземпляров звуков. Я думал, что смогу решить эту проблему, привязав службу, поэтому я бы каждый раз связывался с одним и тем же экземпляром, однако он по-прежнему воспроизводит несколько файлов, если на них щелкнуть. Возможно, я неправильно понял концепцию привязки, я не уверен, документация Android иногда немного расплывчата и вводит в заблуждение. Вот мой код, спасибо за любой ввод.

Активность:

 public class ViewSounds extends ListActivity {

  private PlayService myService;

  @Override
  public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setVolumeControlStream(AudioManager.STREAM_MUSIC);

  // Bind Service
  Intent intent = new Intent(ViewSounds.this, PlayService.class);       
  getApplicationContext().bindService(intent, serviceConncetion, BIND_AUTO_CREATE); 

  // Get list vars
  String[] lex_names = getResources().getStringArray(R.array.lex_names);
  //final String[] lex_files = getResources().getStringArray(R.array.lex_files);

  setListAdapter(new ArrayAdapter<String>(this, R.layout.list_sounds, lex_names));  
  final ListView lv = getListView();
  lv.setTextFilterEnabled(true);

  lv.setOnItemClickListener(new OnItemClickListener() {
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                   

    //int playFile = getResources().getIdentifier(lex_files[position], "raw", getPackageName());   
     myService.playAudio();

    }
  });   
  }  

  private ServiceConnection serviceConncetion = new ServiceConnection() { 

   @Override
   public void onServiceConnected(ComponentName name, IBinder service) { 
         // TODO Auto-generated method stub 
         myService = ((PlayService.MyBinder)service).getService();                   
         } 

         @Override
         public void onServiceDisconnected(ComponentName name) {
         // TODO Auto-generated method stub 
         myService = null; 
         } 
        }; 

         @Override
         public void onDestroy(){ 
         super.onDestroy(); 
         unbindService(serviceConncetion);    
         }
 }
  

Обслуживание:

 public class PlayService extends Service {

MediaPlayer player;

private final IBinder binder = new MyBinder();

@Override
public IBinder onBind(Intent intent) {
    return binder;
}       

public class MyBinder extends Binder {
     PlayService getService() {
        return PlayService.this;
    }
}

@Override
public void onCreate() {
    super.onCreate();
}

public void playAudio(){   
            // I hardcoded the file name for this preview

    player = MediaPlayer.create(this, R.raw.no_harm);
    player.setLooping(false); // Set looping
    if (!player.isPlaying()) {      
    player.start(); 
    }
 }

public void onStart(Intent intent, int startId){
    super.onStart(intent, startId);
    Toast.makeText(this,"Service created ...", Toast.LENGTH_LONG).show();

    // Get veriable from Activity
    // int extras; 
    // extras = intent.getExtras().getInt("playFile");          

}
@Override
public void onDestroy() {
    super.onDestroy();
}
}
  

Ответ №1:

Вы должны остановить воспроизведение предыдущего файла перед воспроизведением другого файла. В вашем коде вы фактически создаете новый MediaPlayer для каждого нового медиафайла.

Вот как должен выглядеть ваш playAudio :

 public void playAudio(){   
   // I hardcoded the file name for this preview

   if(player != null){
       player.release();
   }

   player = MediaPlayer.create(this, R.raw.no_harm);
   player.setLooping(false); // Set looping
   if (!player.isPlaying()) {      
      player.start(); 
   }
}
  

Но вам следует избегать создания новых медиаплееров для каждого нового воспроизведения. Вы могли бы сделать это следующим образом:

 public void playAudio(){   
   // I hardcoded the file name for this preview

   if(player == null){
        player = new MediaPlayer();
   }

   if(player.isPlaying()){  
        player.stop();
   }

   player.reset();
   player.setLooping(false);

   player.setOnPreparedListener(new MediaPlayer.OnPreparedListener(){
        @Override
        void onPrepared(MediaPlayer mp){
            mp.play();
        }
   });       
   player.prepareAsync(); 
}
  

Вам также следует использовать onSetErrorListener(...) и onSetComlpletionListener(...) для большего контроля над плеером. Чтобы ваша активность могла реагировать на изменения состояния в MediaPlayer .