Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 当我尝试将Display设置为MediaPlayer时,曲面已释放_Android_Surfaceview_Android Mediaplayer - Fatal编程技术网

Android 当我尝试将Display设置为MediaPlayer时,曲面已释放

Android 当我尝试将Display设置为MediaPlayer时,曲面已释放,android,surfaceview,android-mediaplayer,Android,Surfaceview,Android Mediaplayer,我的xml文件: <SurfaceView android:id="@+id/surfaceView" android:layout_marginTop="50dp" android:layout_width="fill_parent" android:layout_height="300dp" /> 日志如下所示: 04-24 22:19:33.645: W/System.err(16106): java.lang.IllegalArgumentE

我的xml文件:

<SurfaceView
    android:id="@+id/surfaceView"
    android:layout_marginTop="50dp"
    android:layout_width="fill_parent"
    android:layout_height="300dp" />
日志如下所示:

04-24 22:19:33.645: W/System.err(16106): java.lang.IllegalArgumentException: The surface has been released
04-24 22:19:33.645: W/System.err(16106):    at android.media.MediaPlayer._setVideoSurface(Native Method)
04-24 22:19:33.645: W/System.err(16106):    at android.media.MediaPlayer.setDisplay(MediaPlayer.java:698)

我在这里发现了一些类似的问题,但这些都不适合我。等待你的回答。非常感谢。

表面可能会被破坏。这就是为什么需要将a
public void surfaceDestroyed(SurfaceHolder holder)
添加到SurfaceView的实现中,如下所示:

还应添加处理曲面创建的函数:

并通过以下方式修改您自己的函数:

    mp.setDataSource("sdcard/test/a.3gp");
    SurfaceHolder sh = sv.getHolder();
    synchronized (this) {
       while (!hasActiveHolder) {
              try {
                  this.wait();
              } catch (InterruptedException e) {
                //Print something
              }
        }
        mp.setDisplay(sh);
        mp.prepare();
    }

您还有另一个选择,即Google建议您使用SurfaceView的方式:在一个单独的线程中。

这与执行顺序有关,因为在设置MediaPlayer的显示之前,必须先创建曲面,因此,您必须将回调方法
surfaceCreated
重写为以下内容:

@Override
public void surfaceCreated(SurfaceHolder holder) {
    mp.setDisplay(sh); // now "mp" is defined as a class variable
}
现在不需要在播放方法中设置Display:

private MediaPlayer mp; // to use it inside surfaceCreated callback method
public void playVideo() {
    mp = new MediaPlayer();
    SurfaceView sv = (SurfaceView) this.findViewById(R.id.surfaceView);
    try {
        mp.setDataSource("sdcard/test/a.3gp");
        SurfaceHolder sh = sv.getHolder();
        mp.prepare();
        mp.start();
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

最简单的方法就是在
surfaceCreated
中调用
setDisplay

@Override
public void surfaceCreated(SurfaceHolder holder) {
    mp.setDisplay(holder)
}
不要忘记解开曲面的绑定:

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

注意:媒体播放器应该在之前的某个地方初始化,例如在
onCreate

中,对于仍然存在问题的用户,请尝试在活动/fragment/etc中实现SurfaceHolder.Callback,并在onCreate/onCreateView方法中调用addCallback(SurfaceHolder.Callback Callback)方法,使用活动/fragment/etc作为参数回调。

使用SurfaceHolder.Callback,如下所示

SurfaceView mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
SurfaceHolder holder = mSurfaceView.getHolder();
final MediaPlayer player = new MediaPlayer();

holder.addCallback(new SurfaceHolder.Callback() {
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        player.setDisplay(holder);
    }

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

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }
});

String UrlPath="android.resource://"+getActivity().getPackageName()+"/"+R.raw.your_file_name_without_extension;
try {
    player.setDataSource(getActivity(),Uri.parse(UrlPath));
    player.prepareAsync();
} catch (IOException e) {
    e.printStackTrace();
}
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

    @Override
    public void onPrepared(MediaPlayer mp) {
        mp.start();
    }
});

我们可以查看VideoView源代码:

SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback(){
...
    public void surfaceCreated(SurfaceHolder holder)
    {
        mSurfaceHolder = holder;
        openVideo();
    }
    private void openVideo() {
        ...
        mMediaPlayer = new MediaPlayer();
        mMediaPlayer.setDisplay(mSurfaceHolder);
    }
}

因此,我们可以了解应该使用
mediaplayer.setDisplay()
surfaceCreate
中调用方法。

我尝试了你所说的,但不起作用,保持屏幕变黑。等待你的更多信息。非常感谢你的回答。我刚刚注意到,在surfaceDestroyed中,我在同一对象的同步块中放置了一个synchronized。删除第二个。看起来it’好像你被困在等待中。我建议,如果这不起作用,你可以附加一个调试器并暂停所有看到的线程,以便找到哪个线程处于等待状态()我尝试了另一种方法来修复它。创建曲面(“surfaceCreated”)时,我将“setDisplay”移到回调中。完成了。非常感谢你的回答!
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    mp.setDisplay(null);
}
SurfaceView mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView);
SurfaceHolder holder = mSurfaceView.getHolder();
final MediaPlayer player = new MediaPlayer();

holder.addCallback(new SurfaceHolder.Callback() {
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        player.setDisplay(holder);
    }

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

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }
});

String UrlPath="android.resource://"+getActivity().getPackageName()+"/"+R.raw.your_file_name_without_extension;
try {
    player.setDataSource(getActivity(),Uri.parse(UrlPath));
    player.prepareAsync();
} catch (IOException e) {
    e.printStackTrace();
}
player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {

    @Override
    public void onPrepared(MediaPlayer mp) {
        mp.start();
    }
});
SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback(){
...
    public void surfaceCreated(SurfaceHolder holder)
    {
        mSurfaceHolder = holder;
        openVideo();
    }
    private void openVideo() {
        ...
        mMediaPlayer = new MediaPlayer();
        mMediaPlayer.setDisplay(mSurfaceHolder);
    }
}