Android MediaPlayer AudioStream AudioFlinger passed away !, Fatal Signal 11

I have two fragments (left and right) and hit the left fragment of the list of radio sources. By clicking on one of these streams, the right fragment should change the name of the stream and start playing the stream with the given uri.

2 Problems:

  • Some of the radio streams are not updated, so many of them no longer work. The problem is that this causes my application to force close! I did error handling, but after calling such a stream, I get:

03-20 14: 23: 28.192: A / libc (1021): fatal signal 11 (SIGSEGV) at 0x00000000 (code = 1)

03-20 14: 23: 28.192: W / AudioSystem (1021): AudioFlinger server is dead!

03-20 14: 23: 28.192: W / IMediaDeathNotifier (1021): the message server has died.

03-20 14: 23: 28.192: E / MediaPlayer (1021): error (100, 0)

03-20 14: 23: 28.192: I / ServiceManager (1021): Waiting for service media.audio_flinger ...

03-20 14: 23: 28.752: I / dalvikvm (1021): threadid = 3: reaction to signal 3

03-20 14: 23: 28.782: I / dalvikvm (1021): Wrote the stack trace '/data/anr/traces.txt'

03-20 14: 23: 29.192: I / ServiceManager (1021): Waiting for service media.audio_flinger ...

I do not know why. Is there any other way to handle errors? Or is there a way to check all streams before calling mediaPlayer.setDataSource (uri) to avoid preparing defekt uris? (see my code at the end)

  • I control the left ListFragment using the remote control. When I try to switch very quickly from one channel to another, everything is very lag. It seems that the recovery of the media planner takes a very long time. When I don't relearn, I get a runtimeerror when I call mediaPlayer.setDataSource (..) again. Is there a way to call .setDataSource twice on the same MediaPlayer?

Here is my code: My MediaPlayer Wrapper class:

package net.smart4life.tvplay.model; import java.io.IOException; import java.lang.reflect.Method; import java.util.AbstractCollection; import java.util.ArrayList; import java.util.EnumSet; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaPlayer.OnBufferingUpdateListener; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; import android.media.MediaPlayer.OnInfoListener; import android.media.MediaPlayer.OnPreparedListener; import android.util.Log; /** * A wrapper class for {@link android.media.MediaPlayer}. * <p> * Encapsulates an instance of MediaPlayer, and makes a record of its internal * state accessible via a {@link MediaPlayerWrapper#getState()} accessor. */ public class MediaPlayerStateWrapper { private static String tag = "MediaPlayerWrapper"; private MediaPlayer mPlayer; private State currentState; private MediaPlayerStateWrapper mWrapper; public MediaPlayerStateWrapper() { mWrapper = this; mPlayer = new MediaPlayer(); currentState = State.IDLE; mPlayer.setOnPreparedListener(mOnPreparedListener); mPlayer.setOnCompletionListener(mOnCompletionListener); mPlayer.setOnBufferingUpdateListener(mOnBufferingUpdateListener); mPlayer.setOnErrorListener(mOnErrorListener); mPlayer.setOnInfoListener(mOnInfoListener); } /* METHOD WRAPPING FOR STATE CHANGES */ public static enum State { IDLE, ERROR, INITIALIZED, PREPARING, PREPARED, STARTED, STOPPED, PLAYBACK_COMPLETE, PAUSED; } public void setDataSource(String path) { if (currentState == State.IDLE) { try { mPlayer.setDataSource(path); currentState = State.INITIALIZED; } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } else throw new RuntimeException(); } public void prepareAsync() { Log.d(tag, "prepareAsync()"); if (EnumSet.of(State.INITIALIZED, State.STOPPED).contains(currentState)) { mPlayer.prepareAsync(); currentState = State.PREPARING; } else throw new RuntimeException(); } public boolean isPlaying() { Log.d(tag, "isPlaying()"); if (currentState != State.ERROR) { return mPlayer.isPlaying(); } else throw new RuntimeException(); } public void seekTo(int msec) { Log.d(tag, "seekTo()"); if (EnumSet.of(State.PREPARED, State.STARTED, State.PAUSED, State.PLAYBACK_COMPLETE).contains(currentState)) { mPlayer.seekTo(msec); } else throw new RuntimeException(); } public void pause() { Log.d(tag, "pause()"); if (EnumSet.of(State.STARTED, State.PAUSED).contains(currentState)) { mPlayer.pause(); currentState = State.PAUSED; } else throw new RuntimeException(); } public void start() { Log.d(tag, "start()"); if (EnumSet.of(State.PREPARED, State.STARTED, State.PAUSED, State.PLAYBACK_COMPLETE).contains(currentState)) { mPlayer.start(); currentState = State.STARTED; } else throw new RuntimeException(); } public void stop() { Log.d(tag, "stop()"); if (EnumSet.of(State.PREPARED, State.STARTED, State.STOPPED, State.PAUSED, State.PLAYBACK_COMPLETE).contains(currentState)) { mPlayer.stop(); currentState = State.STOPPED; } else throw new RuntimeException(); } public void reset() { Log.d(tag, "reset()"); mPlayer.reset(); currentState = State.IDLE; } /** * @return The current state of the mediaplayer state machine. */ public State getState() { Log.d(tag, "getState()"); return currentState; } public void release() { Log.d(tag, "release()"); mPlayer.release(); } /* INTERNAL LISTENERS */ private OnPreparedListener mOnPreparedListener = new OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { Log.d(tag, "on prepared"); currentState = State.PREPARED; mWrapper.onPrepared(mp); mPlayer.start(); currentState = State.STARTED; } }; private OnCompletionListener mOnCompletionListener = new OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { Log.d(tag, "on completion"); currentState = State.PLAYBACK_COMPLETE; mWrapper.onCompletion(mp); } }; private OnBufferingUpdateListener mOnBufferingUpdateListener = new OnBufferingUpdateListener() { @Override public void onBufferingUpdate(MediaPlayer mp, int percent) { Log.d(tag, "on buffering update"); mWrapper.onBufferingUpdate(mp, percent); } }; private OnErrorListener mOnErrorListener = new OnErrorListener() { @Override public boolean onError(MediaPlayer mp, int what, int extra) { Log.d(tag, "on error"); currentState = State.ERROR; mWrapper.onError(mp, what, extra); return false; } }; private OnInfoListener mOnInfoListener = new OnInfoListener() { @Override public boolean onInfo(MediaPlayer mp, int what, int extra) { Log.d(tag, "on info"); mWrapper.onInfo(mp, what, extra); return false; } }; /* EXTERNAL STUBS TO OVERRIDE */ public void onPrepared(MediaPlayer mp) { } public void onCompletion(MediaPlayer mp) { } public void onBufferingUpdate(MediaPlayer mp, int percent) { } boolean onError(MediaPlayer mp, int what, int extra) { // Error Handling of type: "MEdiaPlayer error(100,0) mp.stop(); mp.release(); return false; } public boolean onInfo(MediaPlayer mp, int what, int extra) { return false; } /* OTHER STUFF */ public int getCurrentPosition() { if (currentState != State.ERROR) { return mPlayer.getCurrentPosition(); } else { return 0; } } public int getDuration() { // Prepared, Started, Paused, Stopped, PlaybackCompleted if (EnumSet.of(State.PREPARED, State.STARTED, State.PAUSED, State.STOPPED, State.PLAYBACK_COMPLETE).contains(currentState)) { return mPlayer.getDuration(); } else { return 100; } } } 

Here is my test snippet (right snippet). Note: the left fragment calls the "newChannel (radioChannel)" method from TestFragment, each time the listitem is clicked.

 package net.smart4life.tvplay.fragment; import java.io.IOException; import net.smart4life.tvplay.R; import net.smart4life.tvplay.model.MediaPlayerStateWrapper; import net.smart4life.tvplay.model.RadioChannel; import android.app.Fragment; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaPlayer.OnErrorListener; import android.media.MediaPlayer.OnPreparedListener; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import android.widget.Toast; public class TestFragment extends Fragment { private RadioChannel radioCh; private TextView tv_RadioCh; private MediaPlayerStateWrapper mediaWrapper; private View view; // firstcall public TestFragment(RadioChannel radioChannel) { this.radioCh = radioChannel; } @Override public void onActivityCreated(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onActivityCreated(savedInstanceState); setRetainInstance(true); tv_RadioCh = (TextView) view.findViewById(R.id.radioText); mediaWrapper = new MediaPlayerStateWrapper(); newChannel(radioCh); } public void newChannel (RadioChannel radioChannel) { this.radioCh = radioChannel; Log.e("RadioChannel", radioCh.getName()); tv_RadioCh.setText(radioCh.getName()); if(mediaWrapper.isPlaying()) { mediaWrapper.stop(); mediaWrapper.reset(); } else if(mediaWrapper.getState() == MediaPlayerStateWrapper.State.PREPARING) { mediaWrapper.release(); mediaWrapper = new MediaPlayerStateWrapper(); } mediaWrapper.setDataSource(radioCh.getUrl().toString()); mediaWrapper.prepareAsync(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_radio_player, container, false); return view; } @Override public void onDetach() { super.onDetach(); mediaWrapper.release(); } } 

Pluses, could you help me with one or both questions?

+4
source share
2 answers

If the stream cannot load, you often get stuck in a preparation state, you can try this here when mediaWrapper.getState() == MediaPlayerStateWrapper.State.ERROR :

 mediaWrapper.reset(); mediaWrapper.release(); System.gc(); mediaWrapper = new MediaPlayerStateWrapper(); mediaWrapper.setDataSource(radioCh.getUrl().toString()); mediaWrapper.prepareAsync(); 

It is better to put it in AsyncTask to avoid the AsyncTask error . Or, when you receive an error message, you need to create a new MediaPlayer because Media Server has died :

 if(mediaWrapper.getState() == MediaPlayerStateWrapper.State.ERROR){ mediaWrapper = new MediaPlayerStateWrapper(); mediaWrapper.setDataSource(radioCh.getUrl().toString()); mediaWrapper.prepareAsync(); } 

If MediaPlayer plays the stream, you should stop and reset first:

 mediaWrapper.stop(); mediaWrapper.reset(); mediaWrapper.setDataSource(radioCh.getUrl().toString()); mediaWrapper.prepareAsync(); 

This works for me, but I think this is not the best way. Hopefully someone can find a better solution for what to do when you are stuck in a state of preparation.

0
source

As for the sound interface service error, as you noticed, it is marked with "what == 100" or an error (100.0).

What can you do to avoid the audioflinger error from my humble experience:

  • Avoid quick service calls (I can add a delay of 500 milliseconds after creating the player)
  • Limit the number of simultaneous active media planners at a time.

What can you do to deal with audioflinger error:

  • Detect the audio fragment error 100, set the flag that occurred, and disable the graphical user interface (it is recommended only to release the player, since stopping it when it is already in the error state is unsafe and will raise an IllegalStateException and an error (38.0)
  • Start another thread that checks that the service has returned (maybe by creating a new media player without exceptions) with a timeout of 5-10 seconds.
  • When the Service returns the reset flag and turns on the GUI again

So referring to your code:

 boolean onError(MediaPlayer mp, int what, int extra) { // Error Handling of type: "MEdiaPlayer error(100,0) mp.release(); // here you add logic communicating the wrapper or main UI thread // to disable GUI and set a flag return false; } 

Then you add a method to handle this in a wrapper.

I would be very grateful when you do this and publish the solution. I also encounter a very similar problem.

0
source

All Articles