java.lang.IllegalStateException in MediaPlayer.setDataSource, using Ringtone class

前提是你 提交于 2019-12-11 13:57:11

问题


I had a crash reported by an user (Samsung Galaxy S5, Android 4.4) and I do not understand what is happening. It seems imporbable but maybe some people have encountered the same problem, or similar.

Here is the trace:

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

Here is the part of my code that is in the error:

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() is one of my functions and returns a Ringtone object that was obtained with a RingtoneManager cursor in the activity's onResume, I do not think there is any problem there.

In the Android source, Ringtone.setStreamType calls Ringtone.setURI. Here is 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();
...

So, setURI creates a new MediaPlayer, then calls setDataSource on the MediaPlayer. The android doc tells us that using new MediaPlayer() sets it in "idle" state, and that "idle" state is the correct state for calling setDataSource. I really do no understand how, apparently one time in a thousand, I get this error. I cannot contact the user who had the error, never reproduced it on my end, so I find myself blocked. I'm thinking of catching the error in my code and when it happens, try again with my Ringtone.setStreamType, on the assumption that it happens because of a transient "state" of the system that may have changed a few milliseconds later. In short I am quite desperate :)

Any help or similar experiences would be appreciated :)


回答1:


In my case, i had to call reset() on the MediaPlayer instance, before i supplied it with a different url.

As far as the documentation goes, setDataSource is only valid in IDLE state.

You can also visit this answer , explained very nicely using diagram.



来源:https://stackoverflow.com/questions/26420837/java-lang-illegalstateexception-in-mediaplayer-setdatasource-using-ringtone-cla

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!