【问题标题】:SurfaceView goes black -- MediaPlayer AndroidSurfaceView 变黑——MediaPlayer Android
【发布时间】:2015-01-19 11:56:11
【问题描述】:

我正在使用 MediaPlayer 和 SurfaceView 从服务器流式传输视频。但是,如果活动处于“暂停”状态,则视频可以正常播放,例如。当用户点击主页按钮或最近按钮时,在恢复播放器活动时,SurfaceView 变为黑色。我知道当您离开活动时,surfaceView 被销毁并在恢复时再次创建,因此作为解决方法,我将玩家的当前位置保存在活动的 onPause() 中,当活动恢复时,我将玩家寻找到该位置。这也不起作用。

所以我的问题是,当用户退出活动时,如何让 surfaceView 保留它正在显示的框架/图片?

public class VideoPlayer extends Activity implements SurfaceHolder.Callback, OnPreparedListener {


    private long PREV_PLAYER_POS;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_videoplayer);

        mDecorView = getWindow().getDecorView();
        mediaController = new VideoControllerView(this, mDecorView);

        handler = new Handler();
        Intent intent = getIntent();
        usedURL = intent.getExtras().getString("vidURL");

        vidID = intent.getExtras().getString("id");
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar1);
        mProgressBar.setVisibility(ProgressBar.VISIBLE);

        mContext = this;

        surfView = (SurfaceView) findViewById(R.id.videoView4);

        SurfaceHolder holder = surfView.getHolder();
        holder.addCallback(this);

        mMediaPlayer = new MediaPlayer();

        mMediaPlayerControl = new VideoControllerView.MediaPlayerControl() {
            ……
           }


        mMediaPlayer.setOnPreparedListener(this);


        mediaController.setOnSeekStartListener(new onSeekStartListener() {

            @Override
            public void onSeekStarted() {

            }
        });

        mediaController.setMediaPlayer(mMediaPlayerControl);
        mediaController.setAnchorView((ViewGroup) findViewById(R.id.container4));
        mediaController.setEnabled(true);
        mediaController.show();


    }


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

        mMediaPlayer.setDisplay(holder);

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {

        mMediaPlayer.setDisplay(holder);


        try {

            mMediaPlayer.setDataSource(usedURL);

            mMediaPlayer.prepareAsync();

        } catch (IllegalArgumentException e) {

            e.printStackTrace();
        } catch (SecurityException e) {

            e.printStackTrace();
        } catch (IllegalStateException e) {

            e.printStackTrace();
        } catch (IOException e) {

            e.printStackTrace();
        }

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

    }

    @Override
    public void onPrepared(MediaPlayer mp) {


        surfView.requestLayout();
        surfView.invalidate();

        mMediaPlayer.start();


    }


    @Override
    public void onSurfaceViewSizeChanged(int width, int height) {


    }

    @Override
    protected void onResume() {
        super.onResume();

        mMediaPlayer.seekTo((int)PREV_PLAYER_POS);


    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();

        mMediaPlayer.stop();
    }

    @Override
    protected void onPause() {
        super.onPause();


        PREV_PLAYER_POS = mMediaPlayer.getCurrentPosition();

        mMediaPlayer.pause();

    }





    @Override
    protected void onDestroy() {
        super.onDestroy();

        mMediaPlayer.release();
        mMediaPlayer = null;
    }

}

最好的问候

【问题讨论】:

    标签: android media-player surfaceview


    【解决方案1】:

    onResume中开始您的视频,

     @Override
        protected void onResume() {
            super.onResume();
        mMediaPlayer.start();
            mMediaPlayer.seekTo(length);
    }
    

    希望它会起作用..

    【讨论】:

    • 它不起作用。 PS:我不想在用户恢复活动时开始播放视频。我希望播放器保持暂停状态
    【解决方案2】:

    当你在 Activity 前面提出一些东西时,SurfaceView 的表面可能会也可能不会被破坏。有关概述,请参阅图形架构文档中的 this section。如果它没有被销毁,则不会再次调用 surfaceCreated(),并且您的应用将永远不会调用 mMediaPlayer.setDisplay(holder) 将 MediaPlayer 连接到表面。

    我猜想,如果您提出“最近”然后旋转设备,那么当您返回时一切正常(因为设备旋转会强制重新创建表面)。您可能希望向各种回调添加一些日志记录,以查看它们何时触发。

    您将需要一个静态变量来跟踪表面是否已被破坏(例如static bool haveSurface = false,在surfaceCreated() 中设置为true,在surfaceDestroyed() 中设置为false。如果在onCreate() 中设置为true,请调用立即mMediaPlayer.setDisplay(holder)

    Grafika 提供了一些处理奇怪的 SurfaceView-vs-Activity 生命周期问题的示例,但我认为它们中的任何一个都不太适合您的用例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-09
      • 1970-01-01
      相关资源
      最近更新 更多