Android使用SurfaceView播放视频 简单介绍

原创 2016年05月30日 14:25:27

Android中播放视频,简单就直接用VideoView,这是系统集成的一个视频播放组件,使用起来还是比较方便的。

这里要写的是使用SurfaceView播放视频,SurfaceView的方便之处我不再多说,具体使用方法如下。

直接上代码:

布局文件长这样:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_black">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true">

        <SurfaceView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/video_surfaceview"
            android:layout_centerInParent="true">
        </SurfaceView>

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/layout_loading"
            android:gravity="center"
            android:visibility="visible"
            android:layout_centerInParent="true">

            <ProgressBar
                style="?android:attr/progressBarStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/progressBar3" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="正在加载..."
                android:id="@+id/tv_loading"
                android:textColor="@color/color_white"
                android:layout_marginLeft="5dp" />

        </LinearLayout>
    </RelativeLayout>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:background="#88000000"
        android:padding="5dp"
        android:gravity="center_vertical">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn_play"
            android:src="@mipmap/media_pause_ic" />

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="10dp"
            android:paddingRight="5dp"
            android:layout_marginLeft="10dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="00:00"
                android:id="@+id/tv_end_time"
                android:textColor="@color/color_white"
                android:layout_marginLeft="5dp"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true" />

            <SeekBar
                android:id="@+id/seekBar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                style="@style/Widget.SeekBar.Normal"
                android:layout_toLeftOf="@+id/tv_end_time"
                android:layout_centerVertical="true" />


        </RelativeLayout>


    </LinearLayout>

</RelativeLayout>

然后在Activity中使用,用SurfaceHolder.Callback,不多说,直接上代码:

大致内容是这样的:

public class MediaPlayActivity extends Activity implements SurfaceHolder.Callback{
public static final String NATIVE_MEDIA_URLS = "native_media";
private  MediaPlayer mMediaPlayer;
private SurfaceView mPreview;
private SurfaceHolder mHolder;
private boolean isShow = false;

private ImageView btnPlay;
private SeekBar mSeekBar;
private TextView tvEndTime;
private Timer mTimer;
private int surfaceWidth,surfaceHeight;

private View loadingView;
private TextView tvLoading;
private  String mediaUrl;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    this.setContentView(R.layout.screen_media_player);
    isShow = true;
    mediaUrl = getIntent().getStringExtra("mediaUrl");
    registerComponent();


}
private void registerComponent(){

    mPreview = (SurfaceView)findViewById(R.id.video_surfaceview);
    mPreview.setFocusable(true);

    mHolder = mPreview.getHolder();
    mHolder.addCallback(this);
    btnPlay = (ImageView)this.findViewById(R.id.btn_play);
    btnPlay.setImageResource(R.mipmap.media_pause_ic);
    btnPlay.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (isPlaying()) {
                pauseMedia();
            } else {
                replayMedia();
            }
            setMediaPlayerStatus(isPlaying());
        }
    });

    mSeekBar = (SeekBar)this.findViewById(R.id.seekBar);
    mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            if (mMediaPlayer != null) {
                mMediaPlayer.seekTo(seekBar.getProgress() * 1000);
            }
            setMediaPlayerStatus(isPlaying());
        }
    });
    tvEndTime = (TextView)this.findViewById(R.id.tv_end_time);


    loadingView = this.findViewById(R.id.layout_loading);
    loadingView.setVisibility(View.GONE);

    tvLoading = (TextView)this.findViewById(R.id.tv_loading);
}


private void setMediaPlayerStatus(boolean playing){
    if(playing){
        btnPlay.setImageResource(R.mipmap.media_pause_ic);
    }else{
        btnPlay.setImageResource(R.mipmap.media_play_ic);
    }
}
private void setProgress(int duration,int max){

    int time = (max-duration)/1000;
    mSeekBar.setMax(max / 1000);
    if(duration<50)
        mSeekBar.setProgress(0);
    else
    mSeekBar.setProgress((duration / 1000)+1);
    tvEndTime.setText(String.format("%02d", time / 60) + ":" + String.format("%02d", time));
}


private void startTimer(){

    if(mTimer == null){
        mTimer = new Timer();
    }
    setProgress(-1, mMediaPlayer.getDuration());
    mTimer.schedule(new TimerTask() {
        @Override
        public void run() {
            if (isPlaying()) {
                mHandler.sendEmptyMessage(0);
            }
        }
    }, 0, 1000);
}

private Handler mHandler = new Handler(){

    public void handleMessage(Message msg){
        setProgress(mMediaPlayer.getCurrentPosition(),mMediaPlayer.getDuration());
    }
};

private void initMedia(Uri uri){

    mMediaPlayer = new MediaPlayer();
    mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
        @Override
        public void onCompletion(MediaPlayer mediaPlayer) {

            setMediaPlayerStatus(false);
            setProgress(-1, mMediaPlayer.getDuration());
            //mMediaPlayer.seekTo(500);
        }
    });
    mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
        @Override
        public boolean onError(MediaPlayer mediaPlayer, int whatError, int extra) {

            Toast("播放失败");
            releaseMedia();
            return true;
        }
    });


    mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mediaPlayer) {

            resetDisplay(mWidth, mHeight);
            //setProgress(mMediaPlayer.getCurrentPosition()+1, mMediaPlayer.getDuration());


            loadingView.setVisibility(View.GONE);
            setMediaPlayerStatus(true);
        }
    });

    mMediaPlayer.setDisplay(mHolder);
}


private  void resetDisplay(int width,int height){

    int vWidth = mMediaPlayer.getVideoWidth();
    int vHeight = mMediaPlayer.getVideoHeight();

    float scale = 1.0f * width / vWidth;
    if (vWidth < vHeight) {
        scale = 1.0f * height / vHeight;
    }

    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams((int) (vWidth * scale), (int) (vHeight * scale));
    params.addRule(RelativeLayout.CENTER_HORIZONTAL);
    params.addRule(RelativeLayout.CENTER_VERTICAL);
    mPreview.setLayoutParams(params);

    mMediaPlayer.setDisplay(mHolder);
}



private void playMedia(Uri uri){
    if(mMediaPlayer == null){
        initMedia(uri);
    }
    mMediaPlayer.reset();
    try {
        mMediaPlayer.setDataSource(this, uri);
        mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        mMediaPlayer.prepare();
        startTimer();
        mMediaPlayer.start();


    }catch(Exception e){
        e.printStackTrace();
        Toast("播放失败");
    }
}


private void pauseMedia(){

    if (mMediaPlayer != null) {
        mMediaPlayer.pause();
    }
}

private void replayMedia(){

    if(mMediaPlayer != null){
        mMediaPlayer.start();
    }
}


private boolean isPlaying(){

    if(mMediaPlayer != null){
            return mMediaPlayer.isPlaying();
    }
    return false;
}


private void releaseMedia(){
    if(mTimer != null){
        mTimer.cancel();
        mTimer = null;
    }
    if (mMediaPlayer != null) {
        mMediaPlayer.release();
        mMediaPlayer = null;
    }
}
public void surfaceCreated(SurfaceHolder holder) {
    // TODO Auto-generated method stub
   //播放本地视频

       playMedia(Uri.fromFile(new File(mediaUrl)));
  //若是网络视频,可先下载,然后播放
}

public void surfaceChanged(SurfaceHolder arg0, int format, int width, int height) {
    // TODO Auto-generated method stub

    this.surfaceWidth = width;
    this.surfaceHeight = height;

}

public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    releaseMedia();
}
public void onPause(){
    isShow = false;
    super.onPause();
    pauseMedia();
    setMediaPlayerStatus(isPlaying());
}


public void onDestroy(){
    super.onDestroy();
    releaseMedia();
}
}

如此便可以使用surfaceview来播放视频了。其中细节不到位之处,只能自行补全。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

android系统裁剪方法

android系统裁剪优化一直是各个厂商定制产品的关键步骤,包括浅层次的去除不必要的apk(android apk裁剪定制 )和深层次的裁剪整个编译系统和框架层.   android作为开源系统,各个...

android原生系统裁剪

1, Andriod 4.0.4系统包 Andriod 4.1.1系统包 说明   ApplicationsProvider.apk ApplicationsPro...

PHP魔术常量:__LINE__ __FILE__ __CLASS__

PHP 向它运行的任何脚本提供了大量的预定义常量。不过很多常量都是由不同的扩展库定义的,只有在加载了这些扩展库时才会出现,或者动态加载后,或者在编译时已经包括进去了。有五个魔术常量根据它们使用的位置而...

Android调用系统相机拍照并存入相册

调用系统相机的方法如下: private void onTakeCamera(){ String path = fileHandler.getCameraPath()+"SM_"+Syst...

在代码中改变GridLayout的子控件的位置

近日项目需求,popupWindow弹出一个列表框,为方便起见我使用了GridLayout,但是坑逼的是里面的按钮排序要按照服务端的控制来指定,

关于自定义PopupWindow里面视图的控制

需求这里不再赘述,就是一个popupwindow,出来之后里面的视图要分情况控制。

android6.0 属性

http://blog.csdn.net/kc58236582/article/details/51939322 属性在Android中非常重要,我们基本的不多介绍了,主要说下其...

Android动画的使用点滴

这里要写的android动画是我的一个项目里用到的,几个属性动画都用到了,所以就来记录一下,贴代码:ObjectAnimator anim2 = null; PropertyValuesHol...

Android调用系统裁剪的方法

Android调用系统裁剪,这个已经使用的很熟悉了。但是近期项目里使用的时候遇到了一些小问题,所以在此整理一下,以作记录。首先看代码:Intent intent1 = new Intent("com....

Android内核开发:理解和掌握repo工具

Android内核开发:理解和掌握repo工具 2015-05-20 19:52:13 标签:repo 源码 Android 开发 下载 原创作品,允许转载,转载时请务必以超链接...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)