Android视频播放器

本文介绍如何使用SurfaceView和MediaPlayer在Android应用中构建基本视频播放器。通过代码示例,详细讲解了播放、暂停、停止及重播等功能,并实现了进度条控制和时间显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

Android 入门视频播放器一般采用封装好的VideoView或MediaPlayer+SurfaceView两种类型,其中VideoView高度封装并不适合深入了解其中原理,下面利用SurfaceView+MediaPlay实现一个简单的视频播放器,视频播放器的效果如下所示:

效果图

项目代码

package com.example.mediaplayer_1;

import androidx.appcompat.app.AppCompatActivity;

import android.media.AudioAttributes;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Button;
import android.view.View;
import android.view.WindowManager;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {
    //定义控件与状态量
    private TextView tv_star, tv_end; //视频起始点、终点显示
    private SeekBar seekBar;
    private Button play, pause, stop, replay;
    private SurfaceView surfaceView;
    private SurfaceHolder surfaceHolder;
    private MediaPlayer mediaPlayer;

    private boolean noPlay=true;    //定义播放状态
    private Uri uri;                //播放链接 本地资源库
    private boolean isSeekbarChaning;



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

        //控件绑定与设置
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
                ,WindowManager.LayoutParams.FLAG_FULLSCREEN);   //全屏显示

        play = findViewById( R.id.button );     //绑定控件
        pause = findViewById( R.id.button2 );
        stop = findViewById( R.id.button3 );
        replay = findViewById( R.id.button4 );
        tv_star = findViewById( R.id.textView );
        tv_end = findViewById( R.id.textView2 );
        seekBar = findViewById( R.id.seekBar );

        surfaceView = findViewById( R.id.surfaceView );
        surfaceHolder = surfaceView.getHolder();    //surfaceHolder是surface监听器,感知创建,销毁,改变
        mediaPlayer = new MediaPlayer();            //创建MediaPlayer对象
        uri = Uri.parse( "android.resource://com.example.mediaplayer_1/" + R.raw.video );   //获取本地视频资源【模块名+资源名】
        AudioAttributes audioAttributes = new AudioAttributes.Builder()
                .setUsage(AudioAttributes.USAGE_MEDIA)
                .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                .build();
        mediaPlayer.setAudioAttributes( audioAttributes );  //设置多媒体类型
        mediaPlayer.setLooping( false );

        //控件功能设计
        //1.播放
        play.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) { //监听器分开写,被按下&初始状态为true,则播放
                if(noPlay){
                    play();
                    setSeekto(0);
                    noPlay=false;       //播放状态功能改为false
                }else{
                    mediaPlayer.start();//继续播放视频
                }
            }
        });
        //2.暂停
        pause.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mediaPlayer.isPlaying()){ //正在播放状态则暂停
                    mediaPlayer.pause();
                }
            }
        });
        //3.停止
        stop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mediaPlayer.isPlaying()){
                    mediaPlayer.stop();
                    noPlay=true;//更改视频状态为未播放状态

                }
            }
        });

        replay.setOnClickListener( new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(mediaPlayer != null && mediaPlayer.isPlaying()){
                    mediaPlayer.seekTo( 0 );
                    noPlay = false;
                }
            }
        } );

        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                Toast.makeText(MainActivity.this, "视频播放完毕", Toast.LENGTH_SHORT).show();
            }
        });

        //进度条
        seekBar.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int i, boolean b) { //拖动进度条进度改变时调用
                int time_end = mediaPlayer.getDuration() / 1000 ;   //获取视频时长
                tv_end.setText(calaculateTime( time_end ));
                int time_now = mediaPlayer.getCurrentPosition() / 1000;
                tv_star.setText( calaculateTime( time_now ) );
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) { //拖动进度条开始拖动的时候调用
                setSeekbarChaning(true);

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {  //拖动进度条停止拖动的时候调用
                setSeekbarChaning( false );
                setSeekto( seekBar.getProgress() );   //进度条跳转至拉伸位置,视频跳转
                tv_star.setText(formattime( mediaPlayer.getCurrentPosition() ));

            }
        } );
    }

    public void play() {
        mediaPlayer.reset();//重置MediaPlayer
        mediaPlayer.setDisplay( surfaceHolder );//把视频画面输出至SurfaceView中

        try {
            mediaPlayer.setDataSource( getApplicationContext(), uri ); //读取资源库指定文件
            mediaPlayer.prepare();//预加载

        } catch (Exception e) {
            e.printStackTrace(); //捕获异常
        }

        mediaPlayer.start();
        int duration = mediaPlayer.getDuration();   //获取视频总时间
        seekBar.setMax( duration );     //将音乐总时间设置为Seekbar的最大值

        Timer timer = new Timer();
        timer.schedule( new TimerTask() {
            @Override
            public void run() {
                if (!isSeekbarChaning) { //判断seekbar是否修改完毕
                    if (!noPlay) {       //判断视频是否暂停
                        seekBar.setProgress( mediaPlayer.getCurrentPosition() );
                    }

                }
            }
        }, 0, 50 );



    }

    //时间换算
    public String calaculateTime(int time){
        int minute, second;
        if(time > 60){
            minute = time / 60; //分钟取整
            second = time % 60; //秒钟取余
            //分钟再0~9
            if(minute >= 0 && minute < 10){ //0x:0x
                //判断秒
                if(second >= 0 && second < 10){
                    return "0"+minute+":"+"0"+second;
                }else {
                    return "0"+minute+":"+second;
                }
            }else {
                //分钟大于10再判断秒
                if(second >= 0 && second < 10){
                    return minute+":"+"0"+second;
                }else {
                    return minute+":"+second;
                }
            }
        }else if(time < 60){
            second = time;
            if(second >= 0 && second < 10){
                return "00:"+"0"+second;
            }else {
                return "00:"+ second;
            }
        }
        return null;
    }

    //改变进度条 bool状态
    public void setSeekbarChaning(boolean isSeekbar){
        isSeekbarChaning = isSeekbar;
    }

    public void setSeekto(int progress){
        mediaPlayer.seekTo( progress );
    }

    public  String formattime(long time){
        String min=  (time/(1000*60))+"";
        String second= (time%(1000*60)/1000)+"";
        if(min.length()<2){
            min = 0 + min;
        }
        if(second.length()<2){
            second = 0 + second;
        }
        return min +":"+ second;
    }


    @Override
    protected void onDestroy() {
        if(mediaPlayer!=null){
            if(mediaPlayer.isPlaying()){
                mediaPlayer.stop();
            }
            mediaPlayer.release();
        }
        super.onDestroy(); //释放资源
    }
}

布局比较简单,就不上传了,完整代码链接:https://download.youkuaiyun.com/download/Harrison509/12742083

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值