致命异常:java.lang.IllegalStateException 在 android.media.MediaPlayer

Fatal Exception: java.lang.IllegalStateException at android.media.MediaPlayer

我在调用 Mediaplayer 时在某些较新的 Android 模型上收到 IllegalStateException。它主要是 Android 6. 和 7 部手机。我似乎无法弄清楚如何解决这个问题,这里的其他 "Questions" 似乎不适用于我的问题。

正在获取此堆栈跟踪:

Fatal Exception: java.lang.IllegalStateException
   at android.media.MediaPlayer._prepare(MediaPlayer.java)
   at android.media.MediaPlayer.prepare(MediaPlayer.java:1369)
   at  org.my.app.IntroVideoSurfaceView.surfaceCreated(IntroVideoSurfaceView.java:51)
   at android.view.SurfaceView.updateWindow(SurfaceView.java:712)
   at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:316)
   at android.view.View.dispatchWindowVisibilityChanged(View.java:10434)
   at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1330)
   at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1330)
   at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1330)
   at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1330)
   at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1751)
   at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1438)
   at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7398)
   at android.view.Choreographer$CallbackRecord.run(Choreographer.java:920)
   at android.view.Choreographer.doCallbacks(Choreographer.java:695)
   at android.view.Choreographer.doFrame(Choreographer.java:631)
   at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:906)
   at android.os.Handler.handleCallback(Handler.java:739)
   at android.os.Handler.dispatchMessage(Handler.java:95)
   at android.os.Looper.loop(Looper.java:158)
   at android.app.ActivityThread.main(ActivityThread.java:7224)
   at java.lang.reflect.Method.invoke(Method.java)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

这是我的class:

public class IntroVideoSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

private MediaPlayer mp;
private boolean has_started = false;

@TargetApi(Build.VERSION_CODES.LOLLIPOP) public IntroVideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    init();
}

public IntroVideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
}

public IntroVideoSurfaceView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

public IntroVideoSurfaceView(Context context) {
    super(context);
    init();
}

private void init() {
    mp = new MediaPlayer();
    getHolder().addCallback(this);
}

@Override public void surfaceCreated(SurfaceHolder holder) {
    AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.onboarding);
    try {
        if (!has_started) {
            has_started = true;
            mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getDeclaredLength());
        }


      mp.prepare();


        android.view.ViewGroup.LayoutParams lp = getLayoutParams();
        lp.height = getHeight();
        lp.width = getWidth();

        setLayoutParams(lp);
        mp.setDisplay(getHolder());
        mp.setLooping(true);
        mp.start();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}

@Override public void surfaceDestroyed(SurfaceHolder holder) {
    mp.stop();
  }
}

这是我在 activity 中调用以显示视频的 xml 文件:

      <org.my.app.IntroVideoSurfaceView
       android:id="@+id/surface"
       android:layout_width="match_parent"
       android:layout_height="match_parent" />

在 try 循环结束时,您 start() 媒体播放器(Started 状态)。如果您稍后调用 prepare(),则会抛出 IllegalStateException,因为您只能从 Initialized 状态调用 prepare()(您放置的 Stopped 状态surfaceDestroyed() 中的媒体播放器 不是 调用 prepare() 的有效状态)。看到state diagram here, and note that according to the surface life-cyclesurfaceCreated()可能被调用了多次。因此,您至少应该将 mp.prepare() 放在 if 块中。