1

У меня был сбой, сообщенный пользователем (Samsung Galaxy S5, Android 4.4), и я не понимаю, что происходит. Это кажется неоспоримым, но, возможно, некоторые люди столкнулись с одной и той же проблемой или похожими.java.lang.IllegalStateException в MediaPlayer.setDataSource, используя класс Ringtone

Вот след:

java.lang.RuntimeException: An error occured while executing doInBackground() 
at android.os.AsyncTask$3.done(AsyncTask.java:300) 
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355) 
at java.util.concurrent.FutureTask.setException(FutureTask.java:222) 
at java.util.concurrent.FutureTask.run(FutureTask.java:242) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
at java.lang.Thread.run(Thread.java:841) 
Caused by: java.lang.IllegalStateException 
at android.media.MediaPlayer._setDataSource(Native Method) 
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1383) 
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1367) 
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1302) 
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:1240) 
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:986) 
at android.media.MediaPlayer.setDataSource(MediaPlayer.java:951) 
at android.media.Ringtone.setUri(Ringtone.java:219) 
at android.media.Ringtone.setStreamType(Ringtone.java:89) 
at com.aasfet.clocklight.WakeActivity$RingAsyncTask.doInBackground(WakeActivity.java:510) 
at com.aasfet.clocklight.WakeActivity$RingAsyncTask.doInBackground(WakeActivity.java:1) 
at android.os.AsyncTask$2.call(AsyncTask.java:288) 
at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
... 3 more 

Вот часть моего кода, который находится в ошибке:

private class RingAsyncTask extends AsyncTask<Integer, Integer, Integer> { 

     @Override 
     protected Integer doInBackground(Integer... params) { 
      int previousVolume = audioManager.getStreamVolume(AudioManager.STREAM_ALARM); 
      int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM); 
      int newVolume = (int)(volume * (float)maxVolume); 
      if(newVolume < 1){ 
       newVolume = 1; 
      } 
      if(progressive){ 
       audioManager.setStreamVolume(AudioManager.STREAM_ALARM, 1, 0); 
      }else{ 
       audioManager.setStreamVolume(AudioManager.STREAM_ALARM, newVolume, 0); 
      } 
      getRingtone().setStreamType(AudioManager.STREAM_ALARM); 
      getRingtone().play(); 
... 

getRingtone() является одним из моих функций и возвращает объект Ringtone, что был получен с помощью курсора RingtoneManager в onResume активности, я не думаю, что там есть какая-то проблема.

В Android-устройстве Ringtone.setStreamType вызывает Ringtone.setURI. Вот setURI:

public void setUri(Uri uri) { 
168  destroyLocalPlayer(); 
169 
170  mUri = uri; 
171  if (mUri == null) { 
172   return; 
173  } 
174 
175  // TODO: detect READ_EXTERNAL and specific content provider case, instead of relying on throwing 
176 
177  // try opening uri locally before delegating to remote player 
178  mLocalPlayer = new MediaPlayer(); 
179  try { 
180   mLocalPlayer.setDataSource(mContext, mUri); 
181   mLocalPlayer.setAudioStreamType(mStreamType); 
182   mLocalPlayer.prepare(); 
... 

Так, setURI создает новый MediaPlayer, а затем вызывает setDataSource на MediaPlayer. Документ android сообщает нам, что использование нового MediaPlayer() устанавливает его в состояние «бездействия» и что «незанятое» состояние является правильным состоянием для вызова setDataSource. Я действительно не понимаю, как, по-видимому, один раз в тысячу, я получаю эту ошибку. Я не могу связаться с пользователем, у которого была ошибка, и никогда не воспроизводила его на моем конце, поэтому я нахожу себя заблокированным. Я собираюсь поймать ошибку в своем коде, и когда это произойдет, повторите попытку с моим Ringtone.setStreamType, исходя из предположения, что это происходит из-за переходного «состояния» системы, которое может измениться через несколько миллисекунд позже. Короче я совсем отчаянным :)

Любая помощь или подобный опыт был бы оценен :)

+1

Ошибка со стороны, где медиаплеер не получает источник надлежащего формата. Поддерживаете ли вы весь формат вашего кода. – therealprashant

+0

что разрушаетLocalPlayer() ;? комментарий выше может быть прав, проверьте поддерживаемые форматы из-за вашей версии ОС.http: //developer.android.com/guide/appendix/media-formats.html Попробуйте также отладить свой URL-адрес, скопировать его и попробовать с ним – Hunkeone

+0

Спасибо, там, и Хункеоне, я попытаюсь в этом направлении, но мне не кажется логичным, что проблема с форматом источника данных приводит к ошибке IllegalStateException, а не, скажем, IOException. – jtag

ответ

9

В моем случае, я должен был назвать reset() на экземпляре MediaPlayer, прежде чем я снабдив его по другому адресу.

Что касается documentation, то setDataSource действителен только в состоянии IDLE.

Вы также можете посетить this answer, объяснил очень красиво, используя диаграмму.