zoukankan      html  css  js  c++  java
  • Android SurfaceView的生命周期

    本文利用SurfaceView来实现视频的播放

    本文地址:http://www.cnblogs.com/wuyudong/p/5851156.html,转载请注明源地址。

    在main.xml布局文件添加用于视频画面绘制的SurfaceView 控件:

    <SurfaceView android:layout_width="fill_parent" android:layout_height="240dip" android:id="@+id/surfaceView" />

    项目布局设计:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity" >
    
        <EditText
            android:id="@+id/et_path"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="请输入视频文件的路径" />
    
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >
    
            <Button
                android:id="@+id/bt_play"
                android:layout_width="0dip"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="播放" />
    
            <Button
                android:id="@+id/bt_pause"
                android:layout_width="0dip"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="暂停" />
    
            <Button
                android:id="@+id/bt_replay"
                android:layout_width="0dip"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="重播" />
    
            <Button
                android:id="@+id/bt_stop"
                android:layout_width="0dip"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="停止" />
        </LinearLayout>
        
        <SurfaceView 
            android:id="@+id/sv"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            />
    
    </LinearLayout>

    大部分代码和《Android 多媒体播放API简介》中的完全一样,修改一点点代码即可:

    public class MainActivity extends Activity implements OnClickListener {
    
        private EditText et_path;
        private Button bt_play, bt_replay, bt_pause, bt_stop;
        private SurfaceView sv;
    
        private MediaPlayer mediaPlayer;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            
            sv = (SurfaceView)findViewById(R.id.sv);
            et_path = (EditText) findViewById(R.id.et_path);
            bt_play = (Button) findViewById(R.id.bt_play);
            bt_replay = (Button) findViewById(R.id.bt_replay);
            bt_pause = (Button) findViewById(R.id.bt_pause);
            bt_stop = (Button) findViewById(R.id.bt_stop);
    
            bt_pause.setOnClickListener(this);
            bt_play.setOnClickListener(this);
            bt_replay.setOnClickListener(this);
            bt_stop.setOnClickListener(this);
    
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.bt_play:
                play();
                break;
            case R.id.bt_replay:
                replay();
                break;
            case R.id.bt_stop:
                stop();
                break;
            case R.id.bt_pause:
                pause();
                break;
            default:
                break;
            }
        }
    
        /**
         * 暂停音乐
         */
        private void pause() {
            if ("继续".equals(bt_pause.getText().toString().trim())) {
                mediaPlayer.start();
                bt_pause.setText("暂停");
                return;
            }
            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                mediaPlayer.pause();
                bt_pause.setText("继续");
                return;
            }
        }
    
        /**
         * 重新播放
         */
        private void replay() {
            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                mediaPlayer.seekTo(0);
                return;
            }
            play();
        }
    
        /**
         * 停止播放音乐
         */
        private void stop() {
            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
                mediaPlayer.release(); // 记得释放资源
                mediaPlayer = null;
                bt_play.setEnabled(true);
            }
        }
    
        /**
         * 播放音乐
         */
        private void play() {
            String path = et_path.getText().toString().trim();
            File file = new File(path);
            if (file.exists() && file.length() > 0) {
                try {
                    mediaPlayer = new MediaPlayer();
                    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                    
                    /* 设置Video影片以SurfaceHolder播放 */
                    mediaPlayer.setDisplay(sv.getHolder());
                    
                    mediaPlayer.setDataSource(path);
                    mediaPlayer.prepare(); // might take long! (for buffering, etc)
                    mediaPlayer.start();
                    mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
                        @Override
                        public void onCompletion(MediaPlayer mp) {
                            bt_play.setEnabled(true);
                        }
                    } );
                    
                    bt_play.setEnabled(false);
                } catch (Exception e) {
                    Toast.makeText(this, "播放失败", 0).show();
                    e.printStackTrace();
                }
            } else {
                Toast.makeText(this, "文件不存在", 0).show();
            }
    
        }
    
    }

    运行项目效果如下:

    但是上面的代码有点问题,那就是当点击home或返回屏幕主界面后,在回到播放页面,视频黑屏

    原因:

    SurfaceView内部维护双缓冲,消耗内存资源

    如果发现当前SurfaceView 用户可见的时候,创建SurfaceView的holder

    如果SurfaceView变成用户不可见的时候  销毁SurfaceView的holder

    为了观察SurfaceView的生命周期,可以添加下面的代码进行打印追踪:

        sv.getHolder().addCallback(new Callback() {
                
                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                    System.out.println("holder被销毁了");
                }
                
                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    System.out.println("holder被创建了");
                    
                }
                
                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width,
                        int height) {
                    System.out.println("holder的大小变化了");
                }
            });
    
        }

    logcat中打印下面的信息:

    09-07 11:36:34.613: I/System.out(28858): holder被创建了
    09-07 11:36:34.623: I/System.out(28858): holder的大小变化了

    返回主界面

    09-07 11:39:08.245: I/System.out(28858): holder被销毁了

    再次回到视频界面

    09-07 11:39:39.405: I/System.out(28858): holder被创建了
    09-07 11:39:39.405: I/System.out(28858): holder的大小变化了

    可以看到,每次回到视频界面,holder都会被重新创建

    修改后的代码如下:

    public class MainActivity extends Activity implements OnClickListener {
    
        private EditText et_path;
        private Button bt_play, bt_replay, bt_pause, bt_stop;
        private SurfaceView sv;
    
        private MediaPlayer mediaPlayer;
        private int currentPosition;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            sv = (SurfaceView) findViewById(R.id.sv);
            et_path = (EditText) findViewById(R.id.et_path);
            bt_play = (Button) findViewById(R.id.bt_play);
            bt_replay = (Button) findViewById(R.id.bt_replay);
            bt_pause = (Button) findViewById(R.id.bt_pause);
            bt_stop = (Button) findViewById(R.id.bt_stop);
    
            bt_pause.setOnClickListener(this);
            bt_play.setOnClickListener(this);
            bt_replay.setOnClickListener(this);
            bt_stop.setOnClickListener(this);
    
            sv.getHolder().addCallback(new Callback() {
    
                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                    System.out.println("holder被销毁了");
    
                    if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                        currentPosition = mediaPlayer.getCurrentPosition();
                        stop();
                    }
                }
    
                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    System.out.println("holder被创建了");
                    if (currentPosition > 0) {
                        play(currentPosition);
                    }
    
                }
    
                @Override
                public void surfaceChanged(SurfaceHolder holder, int format,
                        int width, int height) {
                    System.out.println("holder的大小变化了");
                }
            });
    
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.bt_play:
                play(0);
                break;
            case R.id.bt_replay:
                replay();
                break;
            case R.id.bt_stop:
                stop();
                break;
            case R.id.bt_pause:
                pause();
                break;
            default:
                break;
            }
        }
    
        /**
         * 暂停音乐
         */
        private void pause() {
            if ("继续".equals(bt_pause.getText().toString().trim())) {
                mediaPlayer.start();
                bt_pause.setText("暂停");
                return;
            }
            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                mediaPlayer.pause();
                bt_pause.setText("继续");
                return;
            }
        }
    
        /**
         * 重新播放
         */
        private void replay() {
            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                mediaPlayer.seekTo(0);
                return;
            }
            play(0);
        }
    
        /**
         * 停止播放音乐
         */
        private void stop() {
            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
                mediaPlayer.release(); // 记得释放资源
                mediaPlayer = null;
                bt_play.setEnabled(true);
            }
        }
    
        /**
         * 播放音乐
         */
        private void play(final int currentPosition) {
            String path = et_path.getText().toString().trim();
            File file = new File(path);
            if (file.exists() && file.length() > 0) {
                try {
                    mediaPlayer = new MediaPlayer();
                    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    
                    /* 设置Video影片以SurfaceHolder播放 */
                    mediaPlayer.setDisplay(sv.getHolder());
    
                    mediaPlayer.setDataSource(path);
                    mediaPlayer.prepare(); // might take long! (for buffering, etc)
                    mediaPlayer.start();
                    mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
                        
                        @Override
                        public void onPrepared(MediaPlayer mp) {
                            mediaPlayer.seekTo(currentPosition);
                            
                        }
                    });
                    mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
                        @Override
                        public void onCompletion(MediaPlayer mp) {
                            bt_play.setEnabled(true);
                        }
                    });
    
                    bt_play.setEnabled(false);
                } catch (Exception e) {
                    Toast.makeText(this, "播放失败", 0).show();
                    e.printStackTrace();
                }
            } else {
                Toast.makeText(this, "文件不存在", 0).show();
            }
    
        }
    
    }

     

  • 相关阅读:
    MouseArea重叠导致按键没响应
    【技术贴】VS2005不能新建项目不能新建网站。提示Microsoft visual studio
    【技术贴】解决虚拟机xp安装雨林木风ylmf os的linux鼠标失效鼠标不准确鼠标定位不正常的根本
    【转】不错的黑客和编程教程资源下载
    【技术贴】网页部分图片显示x红叉,网页图片不显示,网页图片显示异常,网页图片打不开。
    【转】极品免费网站空间申请:000webhost.com免费1.5G美国空间PHP+MySQL
    【转】虚拟机VMware安装ubuntu以及安装vmtools
    技术贴】QQ空间打开缓慢,无法编辑日志,由于您当前网络不稳定导致QQ空间打开异常的解决办法。
    【技术贴】看网页时把图片设为桌面背景后的背景图片存放在那里啊存放路径。
    【技术贴】解决虚拟机xp安装雨林木风ylmf os的linux鼠标失效鼠标不准确鼠标定位不正常的根本
  • 原文地址:https://www.cnblogs.com/wuyudong/p/5851156.html
Copyright © 2011-2022 走看看