現在搜索幾天,無法找出mediaPlayer爲什麼隨着設備的方向改變隨機觸發onCompletion。看起來像更強大的平板電腦更多的內存設備崩潰不是很頻繁,但有時他們也會這樣做。Android隨機調用mediaPlayer onCompletion,改變流媒體rtsp視頻的方向變化
我的MediaPlayer運行在Fragment中,我嘗試使用持久的MediaPlayer技術調用setRetainInstance(true)。
作爲一個提示,有些設備有時在LogCat中表示,在發生這種情況時,主線程中正在做太多工作。
這裏是我的代碼片段:
final public class MediaPlayerFragment extends Fragment implements OnCompletionListener, OnPreparedListener, OnBufferingUpdateListener, OnInfoListener, OnErrorListener, SurfaceHolder.Callback {
/**
*
*/
public final static String TAG = "MediaPlayerFragment";
private MediaPlayer mp = null;
private SurfaceView surfaceView = null;
private String path;
// create an handler
private final Handler myHandler = new Handler();
private static final double ASPECT_RATIO = 4.0/3.0;
/**
* Update the ui, so that background tasks can call this update on ui thread
*/
final Runnable updateUIRunnable = new Runnable() {
@Override
public void run() {
MediaPlayerFragment.this.updateSurfaceSizeToLayout();
}
};
@Override
public void onCreate(final Bundle savedInstanceState) {
Log.v(MediaPlayerFragment.TAG, "INFO: onCreate");
super.onCreate(savedInstanceState);
// Control whether a fragment instance is retained across Activity
// re-creation
this.setRetainInstance(true);
// get the extra data from the Intent (Container)
this.path = this.getArguments().getString("path");
if (this.path == null)
throw new RuntimeException("No path where passed to the mediaplayerFragment");
}
/**
* onCreateView
*
* Setup the view of the media player with a surface to show the mediaPlayer
*/
@Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState) {
Log.v(MediaPlayerFragment.TAG, "INFO: onCreateView");
this.surfaceView = new SurfaceView(this.getActivity());
// Push surfaceView to maximum available space
final android.widget.FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
this.surfaceView.setLayoutParams(layoutParams);
// Placeholder for the area of the video, region to display
final SurfaceHolder surfaceHolder = this.surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setSizeFromLayout();
return this.surfaceView;
}
@Override
public void onPause() {
Log.v(MediaPlayerFragment.TAG, "onPause()");
if (this.mp != null) {
this.mp.pause();
this.mp.setDisplay(null);
}
super.onPause();
}
/**
* Prepare the media player for playback. This sets the filepath and start
* the buffering for the player
*/
private void preparePlayer() {
Log.v(MediaPlayerFragment.TAG, "preparePlayer");
try {
this.mp.setLooping(false);
this.mp.setDataSource(this.path);
this.mp.prepareAsync();
}
catch (final IOException e) {
Log.e(MediaPlayerFragment.TAG, "ERROR: Caught ioExeption" + e.getMessage(), e);
}
catch (final Exception e) {
// IllegalStateException if it is called in an invalid state
Log.e(MediaPlayerFragment.TAG, "ERROR: " + e.getMessage(), e);
}
}
@Override
public void onCompletion(final MediaPlayer arg0) {
Log.d(MediaPlayerFragment.TAG, "onCompletion called");
this.releaseMediaPlayer();
}
@Override
public void onPrepared(final MediaPlayer mediaplayer) {
Log.d(MediaPlayerFragment.TAG, "onPrepared called");
if (!this.mp.isPlaying()) {
this.mp.start();
}
}
@Override
public boolean onError(final MediaPlayer arg0, final int arg1, final int arg2) {
Log.v(MediaPlayerFragment.TAG, "onError MediaPlayer");
return false;
}
/**
* Release the media player object and set its variable to null.
*/
private void releaseMediaPlayer() {
if (this.mp != null) {
this.mp.reset();
this.mp.release();
this.mp = null;
}
}
/**
* display is turned
*/
@Override
public void surfaceCreated(final SurfaceHolder holder) {
if (this.mp == null) {
// get a MediaPlayer to display the video
// store the MediaPlayer in the Application, so it does not get
this.mp = new MediaPlayer();
this.mp.setOnCompletionListener(this);
this.mp.setOnPreparedListener(this);
this.mp.setOnBufferingUpdateListener(this);
this.mp.setOnInfoListener(this);
this.mp.setOnErrorListener(this);
this.mp.setScreenOnWhilePlaying(true);
this.mp.setDisplay(holder);
this.preparePlayer();
} else {
// re-establish connection to given surfaceHolder
this.mp.setDisplay(holder);
}
}
@Override
public void surfaceDestroyed(final SurfaceHolder surfaceHolder1) {
Log.v(MediaPlayerFragment.TAG, "surfaceDestroyed called");
// disengage old surface holder
if (this.mp != null) {
this.mp.setDisplay(null);
}
}
/**
* This is called immediately after any structural changes (format or size)
* have been made to the surface. You should at this point update the
* imagery in the surface. This method is always called at least once, after
* surfaceCreated(SurfaceHolder).
*
* @param holder
* The SurfaceHolder whose surface has changed.
* @param format
* The new PixelFormat of the surface.
* @param width
* The new width of the surface.
* @param height
* The new height of the surface.
*/
@Override
public void surfaceChanged(final SurfaceHolder holder, final int format, final int width, final int height) {
Log.v(MediaPlayerFragment.TAG, "surfaceChanged called");
// disengage old surface holder
if (this.mp != null) {
this.myHandler.post(this.updateUIRunnable);
this.mp.setDisplay(holder);
}
}
/**
* The looks at the dimensions of the surfaceView that holds the MediaPlayer
* (Video) and update the size of it to fit that dimension. This is
* necessary because of orientation changes that alters the possible height
* and width of the surface on that the video is drawn.
*/
@SuppressWarnings("boxing")
public void updateSurfaceSizeToLayout() {
// Surface.ROTATION_0 (no rotation), Surface.ROTATION_90,
// Surface.ROTATION_180, or Surface.ROTATION_270
final int orientation = this.getResources().getConfiguration().orientation;
Log.d(MediaPlayerFragment.TAG, "Orientation :" + orientation);
// Get the SurfaceView layout parameters
final android.view.ViewGroup.LayoutParams lp = this.surfaceView.getLayoutParams();
final FrameLayout frameLayout = (FrameLayout) this.surfaceView.getParent();
final int width = frameLayout.getWidth();
final int height = frameLayout.getHeight();
if (orientation == android.content.res.Configuration.ORIENTATION_PORTRAIT) {
// Display in portrait
lp.width = LayoutParams.MATCH_PARENT;
lp.height = (int) (width/MediaPlayerFragment.ASPECT_RATIO);
Log.d(MediaPlayerFragment.TAG, String.format("New surfaceView size: width:max ,height:%d", lp.height));
} else {
lp.width = (int) (height * MediaPlayerFragment.ASPECT_RATIO);
lp.height = LayoutParams.MATCH_PARENT;
Log.d(MediaPlayerFragment.TAG, String.format("New surfaceView size: width:%d , height: max", lp.width));
}
// Commit the layout parameters
this.surfaceView.setLayoutParams(lp);
this.surfaceView.getHolder().setSizeFromLayout();
}
}
任何人都可以看到我是如何處理MediaPlayer的surfaceView或別的東西,使應用程序崩潰一個極大的錯誤。
這裏是logcat的日誌後,將其旋轉兩次,在第二取向變化墜毀:
09-02 18:59:05.796: W/MediaPlayer(19521): info/warning (702, 0)
09-02 18:59:05.806: D/MediaPlayerFragment(19521): MediaPlayer.OnInfoListener: what:702, extra:0
09-02 18:59:05.836: W/MediaPlayer(19521): info/warning (701, 0)
09-02 18:59:05.836: D/MediaPlayerFragment(19521): MediaPlayer.OnInfoListener: what:701, extra:0
09-02 18:59:06.356: V/MediaPlayerFragment(19521): DEBUG: onPause
09-02 18:59:06.436: V/MediaPlayerFragment(19521): surfaceDestroyed called
09-02 18:59:06.466: V/MediaPlayerFragment(19521): onDetach
09-02 18:59:06.546: D/MPActivity(19521): onCreate
09-02 18:59:06.546: V/MediaPlayerFragment(19521): DEBUG: onAttach
09-02 18:59:06.596: D/MPActivity(19521): addVideoFragment
09-02 18:59:06.596: V/MediaPlayerFragment(19521): INFO: onCreateView
09-02 18:59:06.606: V/MediaPlayerFragment(19521): DEBUG: onResume
09-02 18:59:06.696: D/MediaPlayerFragment(19521): surfaceCreated called
09-02 18:59:06.726: V/MediaPlayerFragment(19521): surfaceChanged called
09-02 18:59:06.796: D/MediaPlayerFragment(19521): Orientation :2
09-02 18:59:06.796: D/MediaPlayerFragment(19521): width:810 ,height:-1
09-02 18:59:06.826: V/MediaPlayerFragment(19521): surfaceChanged called
09-02 18:59:06.906: D/MediaPlayerFragment(19521): Orientation :2
09-02 18:59:06.916: D/MediaPlayerFragment(19521): width:810 ,height:-1
09-02 18:59:07.886: W/MediaPlayer(19521): info/warning (702, 0)
09-02 18:59:07.886: D/MediaPlayerFragment(19521): MediaPlayer.OnInfoListener: what:702, extra:0
09-02 18:59:08.186: W/MediaPlayer(19521): info/warning (701, 0)
09-02 18:59:08.186: D/MediaPlayerFragment(19521): MediaPlayer.OnInfoListener: what:701, extra:0
09-02 18:59:09.036: V/MediaPlayerFragment(19521): DEBUG: onPause
09-02 18:59:09.056: V/MediaPlayerFragment(19521): surfaceDestroyed called
09-02 18:59:09.066: V/MediaPlayerFragment(19521): onDetach
09-02 18:59:09.086: E/MediaPlayer(19521): error (1, -2147483648)
09-02 18:59:09.086: D/MPActivity(19521): onCreate
09-02 18:59:09.086: V/MediaPlayerFragment(19521): DEBUG: onAttach
09-02 18:59:09.116: D/MPActivity(19521): addVideoFragment
09-02 18:59:09.116: V/MediaPlayerFragment(19521): INFO: onCreateView
09-02 18:59:09.126: V/MediaPlayerFragment(19521): DEBUG: onResume
09-02 18:59:09.176: D/MediaPlayerFragment(19521): surfaceCreated called
09-02 18:59:09.196: V/MediaPlayerFragment(19521): surfaceChanged called
09-02 18:59:09.196: E/MediaPlayer(19521): Error (1,-2147483648)
09-02 18:59:09.196: V/MediaPlayerFragment(19521): onError MediaPlayer
09-02 18:59:09.196: D/MediaPlayerFragment(19521): onCompletion called
09-02 18:59:09.366: V/MediaPlayerFragment(19521): surfaceDestroyed called
09-02 18:59:09.376: D/MediaPlayerFragment(19521): Orientation :1
09-02 18:59:09.376: D/MediaPlayerFragment(19521): width:-1 ,height:600
09-02 18:59:09.376: V/MediaPlayerFragment(19521): DEBUG: onPause
09-02 18:59:09.396: D/VideoListActivity(19521): onResume()
09-02 18:59:09.496: V/MediaPlayerFragment(19521): INFO: onDestroy
09-02 18:59:09.496: V/MediaPlayerFragment(19521): onDetach
請發表您的logcat – MrEngineer13 2014-09-02 16:51:39