Service MediaPlayer

Ответить
Анатолий
Сообщения: 8
Зарегистрирован: 11 ноя 2012, 16:32
Откуда: Санкт-Петербург

Service MediaPlayer

Сообщение Анатолий » 22 ноя 2012, 18:13

Добрый вечер.Не подскажите как исправить ошибку? В сервисе запускаются последовательно два музыкальных файла при создании Activity. При нажатии на ImageButton воспроизведение их должно быть прекращено и затем заново должны запуститься те же самые файлы (или другие). Но у меня почему-то при нажатии на ImageButton воспроизведение не останавливается, а просто запускается тот же самый файл и я слышу одновременно два файла.Вот код Activity:

Код: Выделить всё

 protected void onCreate(Bundle savedInstanceState) {
	    super.onCreate(savedInstanceState);
	    setContentView(R.layout.oneanimal);ser=isServiceRunning(this);
	    intent= new Intent(this, MyService.class);
    	if (ser) 
    		stopService(intent);
    	else;
    	startService(new Intent(this, MyService.class).putExtra("sound", 4));
    	startService(new Intent(this, MyService.class).putExtra("sound", 3));
	} 
public static boolean isServiceRunning(Context context) {
        final ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        final List<ActivityManager.RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);
        for (ActivityManager.RunningServiceInfo service : services) {
            if (".MyService".equals(service.service.getShortClassName())) {
                return true;
            }
        }
        return false;
    }
protected void onDestroy() {
	    super.onDestroy();
	    Log.d(LOG_TAG, "MainActivity: onDestroy()");
	    ser=isServiceRunning(this);
    	if (ser) stopService(intent);
	  }
	@Override
public boolean onTouch(View v, MotionEvent event) {
		// TODO Auto-generated method stub
		float x1;
		float y1;
		x = event.getX();
	    y = event.getY();
	    switch (event.getAction()) {
	    case MotionEvent.ACTION_DOWN: // нажатие
	      x1 = x;
	      y1 = y;
	    ser=isServiceRunning(this);
      	if (ser) 
      		stopService(intent);
      	else;
      	startService(new Intent(this, MyService.class).putExtra("sound", 4));
      	startService(new Intent(this, MyService.class).putExtra("sound", 3));
	      break;
	    case MotionEvent.ACTION_MOVE: // движение
	      break;
	    case MotionEvent.ACTION_UP: // отпускание
	    case MotionEvent.ACTION_CANCEL:     
	      break;
	    }
	    return true;
	}
} 
И код Service:

Код: Выделить всё

 public void onCreate() {
		    super.onCreate();
		    Log.d(LOG_TAG, "MyService onCreate");
		    es = Executors.newFixedThreadPool(1);
		    stopselfyes=false;
		  }
		  
public void onDestroy() {
		    super.onDestroy();
		    Log.d(LOG_TAG, "MyService onDestroy"+" stopselfyes= " + stopselfyes);
		    if (!stopselfyes) 
		    {
		    	mPlayer.stop();
		    	mPlayer.release();
		    }
		  }

public int onStartCommand(Intent intent, int flags, int startId) {
		    Log.d(LOG_TAG, "MyService onStartCommand");
		    int sound = intent.getIntExtra("sound", 0);
		    switch (sound) {
	        case 1:
	        	mPlayer= MediaPlayer.create(this, R.raw.skillet);
				mPlayer.setLooping(false);
	         	break;
	        case 2:
	        	mPlayer= MediaPlayer.create(this, R.raw.skillet2);
				mPlayer.setLooping(false);
	        	break;
	        case 3:
	        	mPlayer= MediaPlayer.create(this, R.raw.s1);
				mPlayer.setLooping(false);
	        	break;	
	        case 4:
	        	mPlayer= MediaPlayer.create(this, R.raw.s2);
				mPlayer.setLooping(false);
	        	break;	
	        default:
	            break;
	          }

		    MyRun mr = new MyRun(sound, startId);
		    es.execute(mr);
		    return super.onStartCommand(intent, flags, startId);
		  }

                  public IBinder onBind(Intent arg0) {
		    return null;
		  }
		  
class MyRun implements Runnable {
		    int sound;
		    int startId;
		    public MyRun(int sound, int startId) {
		      this.sound = sound;
		      this.startId = startId;
		      Log.d(LOG_TAG, "MyRun#" + startId + " create");
		    }
public void run() {
Log.d(LOG_TAG, "MyRun#" + startId + " start");
		    	play=true;
		    	mPlayer.setOnCompletionListener(new OnCompletionListener() { 	  
		    	    public void onCompletion(MediaPlayer mPlayer) {
		    	    	mPlayer.stop();
		    	    	mPlayer.release();
		    	    	play=false;
		    	    	Log.d(LOG_TAG, "MyRun#" + startId + " end, stopSelf(" + startId + ")");
		    	    	if (startId==2) stopselfyes=true; 
		    	    	stopSelf(startId);
		    	    }
		    	});
		      mPlayer.start();
		      while(play) {
		    	  try {
		    		  Thread.sleep(1);
		    	  } catch (InterruptedException e) {}
		    	}
}

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Service MediaPlayer

Сообщение AndreyI » 22 ноя 2012, 20:31

Ну так по коду так и должно происходить
startService(new Intent(this, MyService.class).putExtra("sound", 4));
startService(new Intent(this, MyService.class).putExtra("sound", 3));

Каждый вызов создаст и запустит свой поток в котором будет свой экземпляр MediaPlayer и они будут проигрываться одновременно.

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Service MediaPlayer

Сообщение AndreyI » 22 ноя 2012, 20:56

У MediaPlayer здесь просто нужно в onCompletion запускать следующий проигрыватель с другим треком, а предыдущий очищать.
В 16-й API сделали удобный метод для этого setNextMediaPlayer (MediaPlayer next) можно по цепочке добавлять проигрыватели т.е.
mediaPlayer1.setNextMediaPlayer (mediaPlayer2);
mediaPlayer2.setNextMediaPlayer (mediaPlayer3); и т.д.

но пользоваться этим методом пока рановато, 16-я API не так давно вышла, основная масса юзеров сидят на старых.
Так что только onCompletion с помощью его можно реализовать тоже самое, только код будет более громоздким.

А вообще смотри какая цель для тебя воспроизведения звука, у Андроид есть по крайней мере три варианта вывода звука.
1. MediaPlayer это как бы общий вариант, можно из файла выводить или из Интернета. Его основной недостаток - медленно запрягает ;) , т.е. для вывода звука в играх он мало подходит. Для игр есть другой вариант:
2. SoundPool в него можно загрузить сразу несколько треков, они там подготовятся, декодируются и всегда будут готовы к мгновенному выводу, для игр самое оно. Только нельзя забывать, что треки там будут хранится в не сжатом виде, поэтому не желательно много треков загружать сразу, в гайдах рекомендуют загружать звуки только текущего уровня игры, для следующего уровня загружать свои звуки и т.д. чтобы сэкономить память.
3. AudioTrack этот проигрыватель предназначен для воспроизведения несжатого (PCM) звука, который можно грузить прямо в буфер и подгружать по мере необходимости. Очень удобен при воспроизведения звукового потока, а не из файла, мы просто пополняем буфер, а он выводит его непрерывно прямо на устройство. Этого другие проигрыватели не умеют (MediaPlayer роботает только с управляемым потоком типа RTP в связке с RTCP).

Анатолий
Сообщения: 8
Зарегистрирован: 11 ноя 2012, 16:32
Откуда: Санкт-Петербург

Re: Service MediaPlayer

Сообщение Анатолий » 23 ноя 2012, 10:35

Поток, то один насколько я понимаю: es = Executors.newFixedThreadPool(1) и файлы воспроизводятся последовательно, так по задумке и должно быть. Проблема в том, что при нажатии на ImageButton воспроизведение не останавливается, а просто запускается тот же самый файл и я слышу одновременно два одинаковый файла. Т.е. по моей задумке из Activity: (

Код: Выделить всё

ser=isServiceRunning(this);
        if (ser)
                stopService(intent);
        else;
        
)
сервис останавливается,останавливая mPlayer:

Код: Выделить всё

public void onDestroy() {
                    super.onDestroy();
                    Log.d(LOG_TAG, "MyService onDestroy"+" stopselfyes= " + stopselfyes);
                    if (!stopselfyes)
                    {
                        mPlayer.stop();
                        mPlayer.release();
                    }

                  }
И снова запускается,запуская файлы вновь через:

Код: Выделить всё

startService(new Intent(this, MyService.class).putExtra("sound", 4));
startService(new Intent(this, MyService.class).putExtra("sound", 3));
.
Но почему-то это не получается.И не могу понять как это исправить
Звук выводиться из файла.
Файлы не большие(10-20 секунд).

AndreyI
Сообщения: 372
Зарегистрирован: 14 май 2012, 16:18

Re: Service MediaPlayer

Сообщение AndreyI » 23 ноя 2012, 11:14

Но вы же сами проверяете запущен ли сервис и если запущен, то останавливаете его в результате создается новый сервис,
ser=isServiceRunning(this);
if (ser)
stopService(intent);

он по-новой инициализируется создается новый Executors, а все старые потоки запущенные предыдущим будут продолжать выполнятся пока не закончат, но связи с ними у вас уже не будет.

Плеер вы останавливаете только один, тот что был запущен последним:
mPlayer.stop();
mPlayer.release();

А на тот что был первым запущен, ссылку вы потеряли (переприсвоили новому плееру) и он будет продолжать воспроизводить файл. То что Executors еще не запустил его, ничего не значит, плеер вы уже создали , ссылку переприсвоили.

Т.е. если вы нажмете на кнопку когда воспроизводится первый файл, вы убъете только второй медиплеер, а на первый (который играет) у вас уже ссылки нет.

А если нажмете, когда будет играть второй, то все нормально будет, так как вы хотите, остановится именно второй плеер, который в данный момент будет играть (первый уже на тот момент отыграл и убил свой поток самостоятельно)

Анатолий
Сообщения: 8
Зарегистрирован: 11 ноя 2012, 16:32
Откуда: Санкт-Петербург

Re: Service MediaPlayer

Сообщение Анатолий » 23 ноя 2012, 13:22

Большое спасибо!!! Теперь мне понятно стало,в чем была проблема, попробую дома переделать.Если что вернусь)

Ответить