安卓:JzvdStd——网络视频播放器

news2024/11/16 21:44:56

目录

一、JzvdStd介绍

JzvdStd的特点和功能:

 JzvdStd常用方法:

二、JzvdStd使用

1、补充知识:

例子:

MainActivity : 

VideoPageAdapter : 

activity_main: 

video_page: 

运行结果:

一、JzvdStd介绍

        JzvdStd是一个用于Android平台的开源视频播放器库,它提供了丰富的功能和易于使用的API,使开发者能够快速实现高质量的视频播放功能。

JzvdStd的特点和功能:

  • 支持常见的视频格式:JzvdStd支持播放各种常见的视频格式,包括MP4、FLV、MKV、AVI等。
  • 自定义界面:JzvdStd提供了丰富的界面定制选项,开发者可以根据自己的需求自定义播放器的外观和交互方式。
  • 全屏播放:JzvdStd支持全屏播放模式,用户可以轻松切换到全屏模式以获得更好的观看体验。
  • 手势操作:JzvdStd支持手势操作,用户可以通过滑动手势来调节音量、亮度和播放进度。
  • 弹幕功能:JzvdStd内置了弹幕功能,用户可以在视频播放过程中发送和接收弹幕信息。
  • 网络视频流支持:JzvdStd能够播放网络视频流,开发者可以通过URL链接直接播放在线视频。

 JzvdStd常用方法:

  • setVideoUrl(String url)设置要播放的视频源,可以是本地文件路径或网络视频地址。
  • startVideo()开始播放视频。
  • pauseVideo()暂停视频播放。
  • resumeVideo()恢复视频播放。
  • stopVideo()停止视频播放,并释放相关资源。
  • releaseAllVideos()释放所有正在播放的视频,可用于在切换页面或退出应用时释放资源。
  • enterFullScreen()进入全屏播放模式。
  • exitFullScreen()退出全屏播放模式。
  • setLoop(boolean loop)设置是否循环播放视频。
  • setScreenOnWhilePlaying(boolean screenOn)设置在视频播放期间是否保持屏幕亮起。
  • seekTo(int position)跳转到指定的播放位置。
  • getCurrentPosition()获取当前播放位置。
  • getDuration()获取视频总时长。
  • isPlaying()判断视频是否正在播放。
  • setOnJzvdStdListener(OnJzvdStdListener listener)设置JzvdStd的监听器,用于监听视频播放状态、全屏切换等事件。
  • setVideoImageDisplayType(JzvdStd.SCREEN_IMAGE_DISPLAY_TYPE type)设置视频封面图片的显示方式,包括填充、拉伸、原始比例等。
  • setVideoImage(String imageUrl):设置视频封面图片的URL地址。
  • setMediaInterface(JZMediaInterface mediaInterface)设置JzvdStd使用的媒体接口,可以自定义实现更多功能。

依赖包:

implementation 'cn.jzvd:jiaozivideoplayer:7.0.5'

二、JzvdStd使用

补充知识:

        PagerSnapHelper是一个辅助类,用于在 RecyclerView 中实现分页滚动效果。它可以与 RecyclerView 搭配使用,实现一次只显示一页内容,并在滚动停止时自动对齐到最近的一页。它可以提供更流畅、直观的滑动体验,并方便地实现横向或纵向的分页展示效果。

主要特点和用途如下:

  • 1. 分页滚动:PagerSnapHelper 可以使 RecyclerView 实现类似 ViewPager 的分页滚动效果,即一次只能滚动一页内容。当用户滚动 RecyclerView 时,它会自动将滚动停止的位置对齐到最近的一页。
  • 2. 对齐效果:PagerSnapHelper 可以确保 RecyclerView 停止滚动时,当前可见项完全对齐到 RecyclerView 的边界。这样可以让用户更清晰地看到每一页的内容,提供更好的视觉体验。
  • 3. 简单易用:PagerSnapHelper 是 Android Support Library 中提供的一个默认实现类,可以轻松地与 RecyclerView 集成使用。只需要创建一个 PagerSnapHelper 对象并调用attachToRecyclerView()方法来关联 RecyclerView,即可实现分页滚动效果。

使用 PagerSnapHelper 的步骤如下:

  • 1. 创建 PagerSnapHelper 对象:PagerSnapHelper pagerSnapHelper = new PagerSnapHelper();
  • 2. 关联 RecyclerView:pagerSnapHelper.attachToRecyclerView(recyclerView);,其中 recyclerView是你的 RecyclerView 对象。
  • 3. 根据需要设置 RecyclerView 的布局管理器(LinearLayoutManager、GridLayoutManager 等)和适配器,以及其他相应的配置。

例子:

MainActivity : 

package com.example.jzvdstddemo;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.PagerSnapHelper;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SnapHelper;

import android.os.Bundle;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import cn.jzvd.JzvdStd;

public class MainActivity extends AppCompatActivity {
    @BindView(R.id.main_recycler_view)
    RecyclerView mVideoRecyclerView;
    private List<String> mUrlList;
    private PagerSnapHelper mSnapHelper;
    private VideoPageAdapter mVideoPageAdapter;
    private LinearLayoutManager mLinearLayoutManager;
    private int currentPosition = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        init();
        mVideoRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                switch (newState) {
                    case RecyclerView.SCROLL_STATE_IDLE://停止滚动
                        playVideoInSnapPosition(recyclerView, mSnapHelper, mLinearLayoutManager);
                        break;
                    case RecyclerView.SCROLL_STATE_DRAGGING://拖动
                        break;
                    case RecyclerView.SCROLL_STATE_SETTLING://惯性滑动
                        // 发生惯性滑动时停止播放任何正在播放的视频,并释放相关的资源。这可以防止在快速滑动过程中出现视频播放错乱或冲突的情况。
                        JzvdStd.releaseAllVideos();
                        break;
                }

            }
        });
    }

    private void init() {
        // 添加网络视频的url
        mUrlList = new ArrayList<>();
        mUrlList.add("https://poss-videocloud.cns.com.cn/oss/2021/05/08/chinanews/MEIZI_YUNSHI/onair/25AFA3CA2F394DB38420CC0A44483E82.mp4");
        mUrlList.add("https://poss-videocloud.cns.com.cn/oss/2021/05/08/chinanews/MEIZI_YUNSHI/onair/25AFA3CA2F394DB38420CC0A44483E82.mp4");
        mUrlList.add("https://poss-videocloud.cns.com.cn/oss/2021/05/08/chinanews/MEIZI_YUNSHI/onair/25AFA3CA2F394DB38420CC0A44483E82.mp4");
        // HORIZONTAL横着滑动,VERTICAL竖着滑动
        mLinearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
        mVideoRecyclerView.setLayoutManager(mLinearLayoutManager);
        mSnapHelper = new PagerSnapHelper();
        mSnapHelper.attachToRecyclerView(mVideoRecyclerView);
        mVideoPageAdapter = new VideoPageAdapter(this, mUrlList);
        mVideoRecyclerView.setAdapter(mVideoPageAdapter);
    }




    private void playVideoInSnapPosition(RecyclerView recyclerView, SnapHelper snapHelper, LinearLayoutManager linearLayoutManager) {
        // 获取当前固定的视图
        View view = snapHelper.findSnapView(linearLayoutManager);
        if (view != null) {
            // 获取当前位置
            int position = recyclerView.getChildAdapterPosition(view);
            if (currentPosition != position) {
                // 如果切换到了新的固定视图
                JzvdStd.releaseAllVideos(); // 释放之前的资源(停止播放上一个视频)
                RecyclerView.ViewHolder viewHolder = recyclerView.getChildViewHolder(view);
                if (viewHolder instanceof VideoPageAdapter.VideoViewHolder) {
                    // 开始播放视频
                    ((VideoPageAdapter.VideoViewHolder) viewHolder).jzVideo.startVideo();
                }
            }
            currentPosition = position;
        }
    }


    @Override
    protected void onPause() {
        super.onPause();
        JzvdStd.releaseAllVideos();
    }
}

VideoPageAdapter : 

package com.example.jzvdstddemo;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.Glide;

import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import cn.jzvd.JzvdStd;

public class VideoPageAdapter extends RecyclerView.Adapter<VideoPageAdapter.VideoViewHolder> {
    private Context context;
    private List<String> mUrlList;

    public VideoPageAdapter(Context context, List<String> urlList) {
        this.context = context;
        this.mUrlList = urlList;
    }

    @NonNull
    @Override
    public VideoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new VideoViewHolder(LayoutInflater.from(context).inflate(R.layout.video_page,
                parent, false));
    }



    @Override
    public void onBindViewHolder(@NonNull VideoViewHolder holder, int position) {
        // 设置视频url和视频标题
        holder.jzVideo.setUp(mUrlList.get(position), "第"+ (position + 1)+"视频",
                JzvdStd.STATE_NORMAL);
        // 如果是第一个视频,就设置自动播放
        if (position==0){
            holder.jzVideo.startVideo();
        }
        // 添加视频封面
        Glide.with(context).load(mUrlList.get(position)).into(holder.jzVideo.thumbImageView);
    }

    @Override
    public int getItemCount() {
        return mUrlList.size();
    }


    public static class VideoViewHolder extends RecyclerView.ViewHolder {
        @BindView(R.id.jzVideo)
        public JzvdStd jzVideo;

        public VideoViewHolder(@NonNull View itemView) {
            super(itemView);
            // 视图绑定
            ButterKnife.bind(this,itemView);

        }
    }

}

activity_main: 

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/main_recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            />
    </RelativeLayout>


</androidx.constraintlayout.widget.ConstraintLayout>

video_page: 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <cn.jzvd.JzvdStd
        android:id="@+id/jzVideo"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

依赖: 

 implementation 'com.jakewharton:butterknife:10.2.3' // 添加此依赖
    annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3' // 添加此规则
    implementation 'cn.jzvd:jiaozivideoplayer:7.0.5'
    implementation 'com.github.bumptech.glide:glide:4.8.0'

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/814688.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在C#中处理空值

在任何编程语言中开发应用程序时&#xff0c;经常会遇到空异常或空引用异常。空指针或空引用是指不引用有效的内存位置或对象的指针。这是一个困扰程序员已经很久的问题&#xff0c;自从程序员开始编写程序以来。空值是一个特殊的值&#xff0c;表示没有有效值可用。当将空值赋…

hbuilderx主题色分享-github风格

效果 步骤 hbuilderx总共有三种主题&#xff0c;绿柔主题Default,酷黑主题Monokai,雅黑主题Atom One Dark,修改主题色是基于三种主题之一的&#xff0c;不能直接创建一个新主题&#xff0c;比如下方配置是基于Atom One Dark(对象名为[Atom One Dark])&#xff0c;则当前hbuild…

【Sortable】前端拖拽库 | 简洁 | 实用 | 强大

前言 官网 - http://www.sortablejs.com/index.html中文文档 - https://www.itxst.com/sortablejs/neuinffi.htmlnpm - https://www.npmjs.com/package/sortablejs npm下载 npm i sortablejsumd <script src"https://www.itxst.com/package/sortable/sortable.min.js…

达梦数据库食用说明

环境准备 达梦数据库支持Windows、Linux和Unix操作系统&#xff0c;达梦正式版需要授权&#xff0c;我们学习的话选择试用即可&#xff0c;在本机使用VM安装一个Centos&#xff0c;然后去达梦官网下载适用自己平台的安装包。 本教程使用的是VM安装的centos7.9。所以选择X86架…

伯俊ERP与金蝶云星空对接集成表头表体组合查询连通应付单新增(应付单(伯俊)(KD 应付单)ok)

伯俊ERP与金蝶云星空对接集成表头表体组合查询连通应付单新增(应付单(伯俊)&#xff08;KD 应付单&#xff09;ok) 数据源系统:伯俊ERP 伯俊科技&#xff0c;依托在企业信息化建设方面的领先技术与实践积累&#xff0c;致力于帮助企业实现全渠道一盘货。伯俊提供数字经营的咨询…

经典文献阅读之--NoPe-NeRF(优化无位姿先验的神经辐射场)

0. 简介 在没有预先计算相机姿态的情况下训练神经辐射场&#xff08;NeRF&#xff09;是具有挑战性的。最近在这个方向上的进展表明&#xff0c;在前向场景中可以联合优化NeRF和相机姿态。然而&#xff0c;这些方法在剧烈相机运动时仍然面临困难。我们通过引入无畸变单目深度先…

SZMMSZ5246BT1G 稳压二极管(齐纳Zener二极管)的特性和应用详解

关于齐纳二极管&#xff1a;是一种特殊的二极管&#xff0c;也被称为肖特基二极管&#xff08;Schottky Diode&#xff09;。它是由金属与半导体材料的结合构成的。与普通的PN结二极管不同&#xff0c;齐纳二极管的结由金属与半导体材料组成&#xff0c;而不是两个不同的半导体…

菜单 vue3 h函数创建组件

目录 index/.vue <template><div class"menu_table"><divclass"table_row"v-for"(item, index) in menuList"click"item.disabled ! true && itemClick(item)"><!-- :style"{border-top:item.line…

一文了解DMX512透明屏的工作原理

DMX512透明屏是一种新型的显示屏技术&#xff0c;它采用了DMX512控制协议&#xff0c;可以实现透明显示效果。 DMX512是一种数字控制协议&#xff0c;常用于舞台灯光和音响设备的控制&#xff0c;通过DMX512控制器可以实现对透明屏的亮度、颜色、动画等参数的调节。 DMX512透明…

泛微最新漏洞汇总

泛微 e-cology 前台SQL注入漏洞 app.name"泛微 e-cology 9.0 OA" 验证poc: POST /weaver/weaver.file.FileDownloadForOutDoc HTTP/1.1 Host: {{Hostname}} Accept: */* Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q0.9 Connection: close …

探索前端图片如何携带token进行验证

前言 图片在前端开发中扮演了重要的角色&#xff0c;它们不仅仅是美观的元素&#xff0c;还可以传递信息和激发用户的兴趣。随着应用场景的增多&#xff0c;前端开发人员就需要在图片加载过程中携带验证的信息。如 token&#xff0c;用于身份验证、权限控制等方面。通过在图片的…

揭示C语言中CPU对register变量分配的决策过程

揭示C语言中CPU对register变量分配的决策过程 博主简介一、引言1.1、register变量的定义和用途1.2、CPU对register变量分配的重要性 二、CPU寄存器分配的概述2.1、CPU寄存器的作用和程序执行过程中的角色2.2、不同类型的CPU寄存器&#xff08;通用寄存器、特殊寄存器等&#xf…

redis基础总结(数据类型)

Redis十大数据类型 String String 是redis最基本数据类型,一个key对应一个value. String类型是二进制安全的,意思是Redis的string类型可以包含任何数据,比如jpg图片或者序列化的对象; String类型是最基本的数据类型,一个redis中字符串value最多是512M; String类型在redis底层…

【已解决】span的宽度与高度如何设置

本博文源于笔者基础不扎实的情况下遇到的一个问题&#xff0c;问题是我有三个span&#xff0c;想让它们宽度与高度再大点&#xff0c;结果发现怎样设置都设置不了。最后不经意间解决问题 文章目录 1、问题再现2、解决方案3、解决效果 1、问题再现 <span>1</span>…

邪恶版ChatGPT来了!

「邪恶版」ChatGPT 出现&#xff1a;每月 60 欧元&#xff0c;毫无道德限制&#xff0c;专为“网络罪犯”而生。 WormGPT 并不是一个人工智能聊天机器人&#xff0c;它的开发目的不是为了有趣地提供无脊椎动物的人工智能帮助&#xff0c;就像专注于猫科动物的CatGPT一样。相反&…

一份热乎乎的字节面试真题

一份热乎乎的字节面试真题 说说Redis为什么快 基于内存存储实现 内存读写是比在磁盘快很多的&#xff0c;Redis基于内存存储实现的数据库&#xff0c;相对于数据存在磁盘的MySQL数据库&#xff0c;省去磁盘I/O的消耗。 高效的数据结构 Mysql索引为了提高效率&#xff0c;选…

【unity】Pico VR 开发笔记(基础篇)

Pico VR 开发笔记(基础篇) XR Interaction Tooikit 版本 2.3.2 一、环境搭建 其实官方文档已经写的很详细了&#xff0c;这里只是不废话快速搭建&#xff0c;另外有一项官方说明有误的&#xff0c;补充说明一下&#xff0c;在开发工具部分说明 插件安装——安装pico的sdk和XR…

为什么定时器,串口这些东西被称之为外设

前言 &#xff08;1&#xff09;我们常常说定时器&#xff0c;串口是外设&#xff0c;但是很多人肯定有疑惑。定时器&#xff0c;串口不明明是存储在芯片里面的吗&#xff1f; &#xff08;2&#xff09;为了弄明白这个&#xff0c;就需要追溯到上个世纪了。 上个世纪的CPU与串…

【玩转Python系列【小白必看】Python多线程爬虫:下载表情包网站的图片

文章目录 前言1. 导入模块和库2. 定义函数 download_image(url, filepath)3. 定义函数 get_page()4. 主程序入口 完整代码运行效果 结束语 前言 本文主要介绍了使用Python编写的多线程爬虫程序&#xff0c;用于下载表情包网站上的图片。通过解析网页内容和使用XPath定位&#x…

Spring优雅的在事务提交/回滚前后插入业务逻辑

业务背景 业务那边想要统计下我们这边每天注册商户成功和失败的数量&#xff0c;你看看怎么给他弄下这个功能 功能实现 TransactionSynchronizationManager.registerSynchronization&#xff0c;发现这是spring事务提供的注册回调接口的方法。 在事务注解方法中&#xff0c…