首页 > 其他分享 >安卓实战演练——Surfaceview视频播放器

安卓实战演练——Surfaceview视频播放器

时间:2024-06-09 13:33:08浏览次数:12  
标签:播放器 mediaplayer 安卓 public Surfaceview Override import android void

代码来源《Android移动开发基础案例教程》

gradle4.6

package name:cn.itcast.surfaceview

先在res中建一个raw包,包中导入vedio.mp4

Androidmanifest代码:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="cn.itcast.surfaceview">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:screenOrientation="landscape">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

MainActivity代码:

package cn.itcast.surfaceview;

import android.os.CountDownTimer;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.widget.SeekBar;
import android.view.SurfaceHolder;
import android.widget.RelativeLayout;
import android.media.MediaPlayer;
import android.media.AudioManager;
import android.widget.ImageView;
import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;
import android.view.Window;
import android.widget.Toast;
import android.content.ContentResolver;
import android.net.Uri;

public class MainActivity extends AppCompatActivity implements
                SeekBar.OnSeekBarChangeListener, SurfaceHolder.Callback {
    private SurfaceView sv;
    private SurfaceHolder holder;
    private MediaPlayer mediaplayer;
    private RelativeLayout rl;
    private Timer timer;
    private TimerTask task;
    private SeekBar sbar;
    private ImageView play;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉默认标题栏
        setContentView(R.layout.activity_main);
        sv = findViewById(R.id.sv);

        //获取 SurfaceView控件的容器,界面内容显示在容器中
        holder = sv.getHolder();
        //setType ()为过时的方法,Android 4.0版本以上的系统不写没问题,否则必须要写
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        holder.addCallback(this);
        rl=findViewById(R.id.rl);
        play=findViewById(R.id.play);
        sbar =findViewById(R.id.sbar);
        sbar.setOnSeekBarChangeListener (this);
        timer = new Timer (); //初始化计时器
        task = new TimerTask() {
            @Override
            public void run() {
                if (mediaplayer != null && mediaplayer.isPlaying()) {
                    int total = mediaplayer.getDuration();//获取视频总时长
                    sbar.setMax(total);    //设置视频进度条总时长
                    //获取视频当前进度
                    int progress = mediaplayer.getCurrentPosition();
                    sbar.setProgress(progress);    //将当前进度设置给进度条
                } else {
                    play.setImageResource(android.R.drawable.ic_media_play);
                }
            }
        };
            //设置 tast任务延迟500毫秒执行,每隔500毫秒执行一次 
            //timer.schedule(task,500,500);
    }
    @Override
    public void surfaceCreated (SurfaceHolder holder){    //Surface 创建时触发
            try {
                mediaplayer = new MediaPlayer();
                mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);    //音频类型
                Uri uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
                        getPackageName() + "/" + R.raw.video); //视频路径
                try {
                    //设置视频文件路径
                    mediaplayer.setDataSource(MainActivity.this, uri);
                } catch (IOException e) {
                    Toast.makeText(MainActivity.this, "播放失败",
                            Toast.LENGTH_SHORT).show();
                    e.printStackTrace();
                }
                //SurfaceView控件与MediaPlayer类进行关联
                mediaplayer.setDisplay(holder);
                mediaplayer.prepareAsync();//将视频文件解析到内存中
                mediaplayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                    @Override
                    public void onPrepared(MediaPlayer mp) {
                        mediaplayer.start(); //播放视频
                    }
                });
            } catch (Exception e) {
                Toast.makeText(MainActivity.this, "播放失败",
                        Toast.LENGTH_SHORT).show();
                e.printStackTrace();
            }
    }
    @Override
    public void surfaceChanged (SurfaceHolder holder, int format, int width,int height){    //Surface 大小发生变化时触发
    }
    @Override
    public void surfaceDestroyed (SurfaceHolder holder){    //Surface 注销时触发
            if (mediaplayer.isPlaying()) { //判断视频是否正在播放
                mediaplayer.stop();    //停止视频
            }
    }
    //播放(暂停)按钮的点击事件
    public void click (View view){
        if (mediaplayer != null && mediaplayer.isPlaying()) { //视频正在播放
            mediaplayer.pause ();  //暂停视频播放
            play.setImageResource(android.R.drawable.ic_media_play);
        } else{
        mediaplayer.start();    //开始视频播放
        play.setImageResource(android.R.drawable.ic_media_pause);
        }
    }
    @Override
    public void onProgressChanged (SeekBar seekBar, int progress, boolean fromUser){}//进度发生变化时触发
    @Override
    public void onStartTrackingTouch (SeekBar seekBar) {    //进度条开始拖动时触发
    }

    @Override
    public void onStopTrackingTouch (SeekBar seekBar) {//进度条停止拖动时触发
        int position = seekBar.getProgress();    //获取进度条当前的拖动位置
        if (mediaplayer != null) {
            mediaplayer.seekTo(position);    //将进度条的拖动位置设置给MediaPlayer对象
        }
    }
    @Override
    public boolean onTouchEvent (MotionEvent event) {  //屏幕触摸事件
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                if (rl.getVisibility() == View.INVISIBLE){ //不显示进度条和播放按钮
                    rl.setVisibility (View.VISIBLE);   //显示进度条和播放按钮
                    //倒计时3秒,3秒后继续隐藏进度条和播放按钮
                    CountDownTimer cdt = new CountDownTimer(3000,1000) {
                        @Override
                        public void onTick(long millisUntilFinished) {
                            System.out.println(millisUntilFinished);
                        }

                        @Override
                        public void onFinish() {
                            //隐藏进度条和播放按钮
                            rl.setVisibility(View.INVISIBLE);
                        }
                    };
                    cdt.start();   //开启倒计时
                } else if (rl.getVisibility() ==View.VISIBLE){//显示进度条和播放按钮
                    rl.setVisibility(View.INVISIBLE);  //隐藏进度条和播放按钮
                }
                break;
        }
        return super.onTouchEvent(event);
    }
    @Override
    protected void onDestroy(){
        task.cancel();    //将TimerTask从任务队列中清除
        timer.cancel();    //将任务队列中的全部任务清除
        task=null;
        timer=null;    //设置对象 task为null    //设置对象timer为null
        mediaplayer.release();    //释放MediaPlayer对象占用的资源
        mediaplayer=null;    //将对象mediaplayer 设置为null
        super.onDestroy();
    }
}

Activity_main代码

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <SurfaceView
        android:id="@+id/sv"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />
    <RelativeLayout
        android:id="@+id/rl"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <SeekBar
            android:id="@+id/sbar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:max="100"
            android:progress="0" />
        <ImageView
            android:id="@+id/play"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:onClick="click"
            android:src="@android:drawable/ic_media_pause" />
    </RelativeLayout>
</FrameLayout>

运行结果截图:

标签:播放器,mediaplayer,安卓,public,Surfaceview,Override,import,android,void
From: https://blog.csdn.net/kongrunmin/article/details/139560791

相关文章

  • 【编译安卓ROM常见错误和注意事项】
    编译AndroidROM是一项复杂的任务,涉及众多代码和工具链。在这个过程中,有很多地方容易出错。以下是一些常见的错误及需要注意的地方:环境准备正确的操作系统和依赖:确保使用支持的Linux发行版(通常是Ubuntu或Debian)。安装所有必要的依赖包,如openjdk-8-jdk、git、g++-multili......
  • 安卓ROM中META-INF目录的主要组成和制作方法
    META-INF目录是Android应用和ROM包中的一个重要目录,主要用于存放包的元数据和签名信息。它在ROM包中的作用尤为重要,因为它包含用于安装和更新系统的脚本和签名文件。下面是META-INF目录的主要组成部分和制作方法的详细介绍。META-INF目录的组成部分META-INF目录通常包......
  • 再见安卓,鸿蒙操作系统时代已经来临!
    在今年4月份的华为鸿蒙新品生态春季沟通会上,余承东宣布,今年的华为开发者大会将于6月在东莞举行,届时将开启HarmonyOSNEXT鸿蒙星河版Beta测试。自此,鸿蒙将彻底脱离安卓,正式进入“纯血鸿蒙”时代。鸿蒙生态的迅速崛起,为广大开发者带来了前所未有的机遇和挑战。1.市......
  • 安卓ROM包的主要结构和组成部分介绍
    AndroidROM包(ROMpackage)是Android操作系统的固件包,通常用于安装或更新Android设备的操作系统。它的结构包含多个关键组件,每个组件都有特定的功能。以下是AndroidROM包的主要结构和组成部分:1.**boot.img**:  -包含引导内核和ramdisk。引导内核负责启动操作系统,而ramdis......
  • 使用ADB查看安卓调试日志
    使用ADB查看安卓调试日志安装ADB工具‍官网下载地址:http://adbdownload.com/根据自己的操作系统选择下载对应的安装包,本文以Windows为例‍连接安卓设备将设备(如手机/平板)的USB调试打开,不同设备和不同版本的开启方式不同,根据实际情况处理.USB调试打开之后,将设备(如......
  • 使用ADB查看安卓调试日志
    使用ADB查看安卓调试日志安装ADB工具‍官网下载地址:http://adbdownload.com/根据自己的操作系统选择下载对应的安装包,本文以Windows为例‍连接安卓设备将设备(如手机/平板)的USB调试打开,不同设备和不同版本的开启方式不同,根据实际情况处理.USB调试打开之后,将设备(如......
  • 安卓架构组件-依赖注入
    安卓依赖注入什么是依赖注入依赖注入(DI,DependencyInjection)是一种广泛的编程技术。把依赖(所需对象)传递给其它对象创建,好处是类的耦合更加松散,遵循依赖倒置的原则。类获取所需对象classEngine{funstart(){println("enginestart")}}class......
  • 微信小程序:实现音乐播放器的功能
    在编写微信小程序时,也许会用到播放背景音乐的功能,那么如果是自动播放背景音乐,可以在加载页面时就运行播放音乐的函数,若是希望简单实现音乐播放器的功能,那么设计几个按钮,并且设计按钮点击的事件。接下来我说明按钮实现音乐播放的功能。wxss文件就不讲了,如果需要设置按钮格式,可......
  • 安卓中的一些问题
    https://www.jianshu.com/p/878c80f66dc3安卓的三种架构安卓中的最开始基本架构和java是一致的,都是MVC架构。Modelviewcontroller层模型层视图层控制层在安卓中呢,其Activity就是控制层(controller),其res资源目录下的layout下的xml文件就是视图层(view),但是layout定义的是......
  • Android课程设计课题题目推荐(安卓期末大作业,毕业设计,Androidstudio)
    博主介绍:本人专注于Android/java/数据库/微信小程序技术领域的开发,以及有好几年的计算机毕业设计方面的实战开发经验和技术积累;尤其是在安卓(Android)的app的开发和微信小程序的开发,很是熟悉和了解;本人也是多年的Android开发人员;希望我发布的此篇文件可以帮助到您;......