在Android中返回视频播放活动时出现黑屏

Wil*_*ann 13 video android screen playback media-player

我正在开发Android应用程序ServeStream,我遇到了我无法修复的问题.我的应用程序将使用android MediaPlayer类流式传输音乐和视频.我在以下示例中找到了我的课程模型:

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/media/MediaPlayerDemo_Video.html

这个例子和我自己的代码之间的区别是我的MediaPlayer在一个服务中运行,允许它在后台继续播放.示例android代码的问题是如果我正在观看视频并且我离开当前窗口/活动(即按下菜单按钮等)并返回到回放活动我得到黑屏但仍然从视频接收音频那是在玩.

最初创建回放活动时,将执行下面显示的代码.此代码实际上创建了用于播放的视图,然后将其绑定到媒体播放器:

        setContentView(R.layout.mediaplayer_2);
        mPreview = (SurfaceView) findViewById(R.id.surface);
        holder = mPreview.getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
...
        mMediaPlayer.setDisplay(holder);
Run Code Online (Sandbox Code Playgroud)

重要的一行是mMediaPlayer.setDisplay(holder),因为它将当前视图/显示绑定到媒体播放器.离开活动时,视图("持有者")将被销毁.返回活动并重新创建视图后,再次执行mMediaPlayer.setDisplay(holder)似乎不会重新附加新创建的视图.显示黑屏而不是视频.

有没有人有解决此问题的解决方法或解决方案.我将不胜感激任何帮助或建议.

Pur*_*war 8

很多周围的Googling和头刮了之后状态图MediaPlayer,我终于设法避免这种所谓的黑屏.我已经在OP的评论部分发布了这个问题似乎已经解决了最新的Android版本(大于4.x),因此我选择在Gingerbread设备上也有类似的行为.

不用说,SurfaceHolder回调方法在有限的生命周期中起到非常关键的作用MediaPlayer- SurfaceView执行.对于我摆脱这种情况,这些非常回调的方法对我来说很方便.

第一:

onCreate()里面: - 基本初始化的东西..

    mVideoSurface = (SurfaceView) findViewById(R.id.videoSurface);
    videoHolder = mVideoSurface.getHolder();
    videoHolder.addCallback(this);

    // For Android 2.2

    videoHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    // Media Player and Controller

    player = new MediaPlayer();
    controller = new VideoControllerView(this);
Run Code Online (Sandbox Code Playgroud)

然后, SurfaceView回调:

别忘了设置Display你的MediaPlayer和恕我直言,surfaceCreated()是最好的地方.

@Override
 public void surfaceCreated(SurfaceHolder holder) {
    player.setDisplay(holder);
    try {
    player.prepareAsync();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

这是最重要的事情.当用户通过按Home键离开当前活动或打开一个期望任何结果的不同活动时,我们SurfaceView将被摧毁.我想要实现的是从上下文切换时正在播放的位置恢复正在播放的视频.所以,为了做到这一点,

将当前播放位置保存在变量中,以便我们稍后可以使用它来寻找我们回放到该特定位置.还有一个.释放该死的MediaPlayer实例.我试图避免释放MediaPlayer实例并重新创建,但我一直都在失败.所以......点了.

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    if (player != null) {
        mCurrentVideoPosition = player.getCurrentPosition();
        player.release();
        player = null;
    }

}
Run Code Online (Sandbox Code Playgroud)

现在,onPrepared()MediaController如果您感兴趣,请在此处 初始化任何内容.检查视频是否已播放,因此请将视频搜索到该位置.

     @Override
 public void onPrepared(MediaPlayer mp) {
    controller.setMediaPlayer(this);
    controller.setAnchorView((FrameLayout) findViewById(R.id.videoSurfaceContainer));
    player.start();

    if (mCurrentVideoPosition != 0) {
        player.seekTo(mCurrentVideoPosition);
        player.start();
    }

}
Run Code Online (Sandbox Code Playgroud)

最后,播放视频:

 void playVideo(){  

   try {
        if (player == null) 
            player = new MediaPlayer();
        player.setAudioStreamType(AudioManager.STREAM_MUSIC);
        player.setDataSource("SOME_VIDEO_FILE.3gp");
        player.setOnPreparedListener(this);
        player.setOnErrorListener(new OnErrorListener() {

            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                mp.reset();
                return false;
            }
        });

    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (IllegalStateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
     }
Run Code Online (Sandbox Code Playgroud)

这就是全部.我知道问题不在于新版本,而且一切都很好但是......很多GB还在那里.


I40*_*004 1

我想我知道问题的原因。看来媒体播放器仅在调用prepare/Async()时才初始化其表面。如果之后你改变表面,你就会得到你所拥有的。因此,解决方案是通过 android:configChanges="orientation|keyboardHidden" 禁用活动的标准生命周期。这将妨碍您的娱乐活动。否则,您应该在每次重新创建持有人时要求准备。