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; 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); } 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; } public State getState() { Log.d(tag, "getState()"); return currentState; } public void release() { Log.d(tag, "release()"); mPlayer.release(); } 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; } }; 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) {
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;
Pluses, could you help me with one or both questions?