2013-03-20 129 views
4

我有两个片段(左和右),并在左边的片段获取Radiostreams列表。通过点击其中一个流,正确的片段应该改变流的名称并开始播放与给定的URI的流。Android MediaPlayer AudioStream AudioFlinger服务器死亡,致命信号11

2个问题:

  1. 一些广播流的是不是最新的,所以很多人都没有工作了。问题是,这导致我的应用程序执行forceclose!我做了错误处理,但弄不好流之后,我得到:

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 died!

03-20 14:23:28.192: W/IMediaDeathNotifier(1021): media server 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: reacting to signal 3

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

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

我不知道为什么。有没有其他的方式来做错误处理?或者有没有办法在调用mediaPlayer.setDataSource(uri)之前检查所有流,以避免准备好uris? (看我的代码在最后)

  1. 我用遥控器控制左边的ListFragment。当我试图从一个频道切换到另一个频道时,一切都非常缓慢。看起来Mediaplayer的重组时间很长。当我不重新实现时,当我再次调用mediaPlayer.setDataSource(..)时,我得到一个运行时错误。有没有办法在一个MediaPlayer对象上调用两次.setDataSource?

这里是我的代码: 我的MediaPlayer的包装类:

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; 
     } 
    } 
} 

这里是我的TestFragment(右片段)。注意:左边的Fragment从TestFragment调用方法“newChannel(radioChannel)”,每次点击一个listitem。

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(); 
    } 

} 

优点,请你帮我解决一个或两个问题吗?

+0

我的修复https://stackoverflow.com/a/47992111/4592448 – Fortran 2017-12-27 12:26:10

回答

0

如果流无法加载你在准备状态往往stucked,你可以在这里试试这个,当mediaWrapper.getState() == MediaPlayerStateWrapper.State.ERROR

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

最好把它放在一个AsyncTask,避免未响应错误。或者当你得到一个错误,你必须创建一个新的MediaPlayer,因为媒体服务器死亡

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

如果MediaPlayer正在播放的流,你必须停下来先复位:

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

它为我工作,但我认为这不是最好的方法。希望当你处于准备状态时,有人可以找到一个更好的解决方案来做什么。

0

关于audioflinger服务错误,正如您已经注意到的那样,它被标记为“what == 100”或错误(100,0)。

,你能做些什么来避免我卑微的经验audioflinger错误:

  1. 避免快速呼叫服务
  2. 限制的并发数(我创建播放后添加像500米利斯延迟)媒体播放器同时处于活动状态。

,你能做些什么来处理audioflinger错误:

  1. 检测的audioflinger错误100,将其设置发生了国旗和禁用GUI(仅释放玩家建议,例如停止它时,它已经处于错误状态是不安全的,将抛出IllegalStateException &错误(38,0)
  2. 开始另一个线程,不断测试服务回来(可以通过创建一个新的mediaplayer没有例外)与超时的让我们说5-10秒
  3. 当服务被重置回的标志,并重新启用GUI

所以指你的代码:

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; 
} 

然后添加在包装上,以处理这个方法。

当您解决问题并发布解决方案时,我将非常感激。我也面临着一个非常类似的问题。