文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android 视频播放器dkplayer

2023-10-02 13:34

关注

gihub地址

https://github.com/Doikki/DKVideoPlayer

GitHub - Doikki/DKVideoPlayer: Android Video Player. 安卓视频播放器,封装MediaPlayer、ExoPlayer、IjkPlayer。模仿抖音并实现预加载,列表播放,悬浮播放,广告播放,弹幕,视频水印,视频滤镜

列表播放如图所示:

一、依赖

     //添加RecyclerView的依赖包    implementation 'androidx.recyclerview:recyclerview:1.2.1'    // 异步加载图片依赖    implementation 'com.squareup.picasso:picasso:2.5.2'    // 上拉刷新、下来加载依赖    implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.3'    // --  Android:视频播放器dkplayer    //# 必选,内部默认使用系统mediaplayer进行解码    implementation 'com.github.dueeeke.dkplayer:dkplayer-java:3.2.6'    //# 可选,包含StandardVideoController的实现    implementation 'com.github.dueeeke.dkplayer:dkplayer-ui:3.2.6'    //# 可选,使用exoplayer进行解码    implementation 'com.github.dueeeke.dkplayer:player-exo:3.2.6'    //# 可选,使用ijkplayer进行解码    implementation 'com.github.dueeeke.dkplayer:player-ijk:3.2.6'    //# 可选,如需要缓存或者抖音预加载功能请引入此库    implementation 'com.github.dueeeke.dkplayer:videocache:3.2.6'

二、工具类

Tag.java

package com.chy.permission;public final class Tag {    //列表播放    public static final String LIST = "list";    //无缝播放    public static final String SEAMLESS = "seamless";    //画中画    public static final String PIP = "pip";}
Utils.java
package com.chy.permission;import android.view.View;import android.view.ViewParent;import android.widget.FrameLayout;import com.dueeeke.videoplayer.player.VideoView;import com.dueeeke.videoplayer.player.VideoViewConfig;import com.dueeeke.videoplayer.player.VideoViewManager;import java.lang.reflect.Field;public final class Utils {    private Utils() {    }        public static Object getCurrentPlayerFactory() {        VideoViewConfig config = VideoViewManager.getConfig();        Object playerFactory = null;        try {            Field mPlayerFactoryField = config.getClass().getDeclaredField("mPlayerFactory");            mPlayerFactoryField.setAccessible(true);            playerFactory = mPlayerFactoryField.get(config);        } catch (Exception e) {            e.printStackTrace();        }        return playerFactory;    }        public static void removeViewFormParent(View v) {        if (v == null) return;        ViewParent parent = v.getParent();        if (parent instanceof FrameLayout) {            ((FrameLayout) parent).removeView(v);        }    }        public static String playState2str(int state) {        String playStateString;        switch (state) {            default:            case VideoView.STATE_IDLE:                playStateString = "idle";                break;            case VideoView.STATE_PREPARING:                playStateString = "preparing";                break;            case VideoView.STATE_PREPARED:                playStateString = "prepared";                break;            case VideoView.STATE_PLAYING:                playStateString = "playing";                break;            case VideoView.STATE_PAUSED:                playStateString = "pause";                break;            case VideoView.STATE_BUFFERING:                playStateString = "buffering";                break;            case VideoView.STATE_BUFFERED:                playStateString = "buffered";                break;            case VideoView.STATE_PLAYBACK_COMPLETED:                playStateString = "playback completed";                break;            case VideoView.STATE_ERROR:                playStateString = "error";                break;        }        return String.format("playState: %s", playStateString);    }        public static String playerState2str(int state) {        String playerStateString;        switch (state) {            default:            case VideoView.PLAYER_NORMAL:                playerStateString = "normal";                break;            case VideoView.PLAYER_FULL_SCREEN:                playerStateString = "full screen";                break;            case VideoView.PLAYER_TINY_SCREEN:                playerStateString = "tiny screen";                break;        }        return String.format("playerState: %s", playerStateString);    }}

VideoAdapter.java

package com.chy.demoprj.adapter;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.FrameLayout;import android.widget.ImageView;import android.widget.TextView;import androidx.annotation.NonNull;import androidx.recyclerview.widget.RecyclerView;import com.chy.demoprj.R;import com.dueeeke.videocontroller.component.PrepareView;import com.squareup.picasso.Picasso;import java.util.HashMap;import java.util.List;public class VideoAdapter extends RecyclerView.Adapter {    private Context context;    private List> datas;    private OnItemChildClickListener mOnItemChildClickListener;// 播放控件点击事件        public VideoAdapter(Context context,List> datas){        this.context = context;        this.datas = datas;    }    @NonNull    @Override    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent,int viewType) {        View view = LayoutInflater.from(context).inflate(R.layout.item_video_layout,parent,false);         ViewHolder viewHolder = new ViewHolder(view);        return viewHolder;    }    @Override    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder,int position) {        ViewHolder vh = (ViewHolder) holder;        HashMap entity = datas.get(position);        // 设置播放占位图(不设置默认黑色)        Picasso.with(context)                .load(entity.get("thumbUrl"))                .into(vh.mThumb);        vh.mPosition = position;    }    @Override    public int getItemCount() {        return datas.size();    }    public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{        public FrameLayout mPlayerContainer;// 容器        public PrepareView mPrepareView;// 播放视图        public ImageView mThumb;// 缩略图        public int mPosition;// 当前视图index        public ViewHolder(@NonNull View itemView) {            super(itemView);            mPlayerContainer = itemView.findViewById(R.id.player_container);            mPrepareView = itemView.findViewById(R.id.prepare_view);            mThumb = mPrepareView.findViewById(R.id.thumb);                        if (mOnItemChildClickListener != null) {                mPlayerContainer.setOnClickListener(this);            }            //通过tag将ViewHolder和itemView绑定            itemView.setTag(this);        }        @Override        public void onClick(View v) {            if (v.getId() == R.id.player_container){                if (mOnItemChildClickListener != null){                    mOnItemChildClickListener.onItemChildClick(mPosition);                }            }        }    }        public interface OnItemChildClickListener{        void onItemChildClick(int position);    }        public void setOnItemChildClickListener(OnItemChildClickListener onItemChildClickListener) {        mOnItemChildClickListener = onItemChildClickListener;    }}

三、布局

activity_main.xml

    

item_video_layout.xml

                

四、实现

package com.chy.demoprj;import androidx.annotation.NonNull;import androidx.appcompat.app.AppCompatActivity;import androidx.recyclerview.widget.LinearLayoutManager;import androidx.recyclerview.widget.RecyclerView;import android.Manifest;import android.content.pm.ActivityInfo;import android.os.Bundle;import android.view.View;import android.widget.FrameLayout;import android.widget.Toast;import com.chy.demoprj.adapter.VideoAdapter;import com.chy.permission.PermissionUtils;import com.chy.permission.Tag;import com.chy.permission.Utils;import com.dueeeke.videocontroller.StandardVideoController;import com.dueeeke.videocontroller.component.CompleteView;import com.dueeeke.videocontroller.component.ErrorView;import com.dueeeke.videocontroller.component.GestureView;import com.dueeeke.videocontroller.component.TitleView;import com.dueeeke.videocontroller.component.VodControlView;import com.dueeeke.videoplayer.player.VideoView;import com.dueeeke.videoplayer.player.VideoViewManager;import com.scwang.smartrefresh.layout.api.RefreshLayout;import com.scwang.smartrefresh.layout.listener.OnLoadMoreListener;import com.scwang.smartrefresh.layout.listener.OnRefreshListener;import java.util.ArrayList;import java.util.HashMap;import java.util.List;public class MainActivity extends AppCompatActivity {    private static final int REQUEST_PERMISSION_CODE = 0;// 权限所用    // 动态申请权限    private String[] permissions = {            Manifest.permission.INTERNET,// 网络权限            Manifest.permission.WRITE_EXTERNAL_STORAGE,// 写入数据权限            Manifest.permission.READ_EXTERNAL_STORAGE,// 读取数据权限            Manifest.permission.ACCESS_FINE_LOCATION,// 定位权限            Manifest.permission.ACCESS_COARSE_LOCATION // 获取基站的服务信号权限,以便获取位置信息    };    private RefreshLayout refreshLayout;    private RecyclerView recyclerView;// 列表    private LinearLayoutManager layoutManager;    private List> datas = new ArrayList<>();    // 视频播放-控件    protected VideoView mVideoView;    protected StandardVideoController mController;    protected ErrorView mErrorView;    protected CompleteView mCompleteView;    protected TitleView mTitleView;        protected int mCurPos = -1;        protected int mLastPos = mCurPos;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        getPermission();        initData();        initControls();        initVideoView();    }        private void getPermission(){        boolean flage = PermissionUtils.hasPermissions(MainActivity.this,permissions);        if (flage) {            System.out.println("权限获取成功!");        } else {            PermissionUtils.requestPermissions(MainActivity.this, REQUEST_PERMISSION_CODE, permissions);        }    }        private void initData(){        HashMap hashMap = null;        // 占位图        String thumbUrl = "https://p1-xg.byteimg.com/img/tos-cn-p-0000/527b08d0f31d4705a4d8f4a72120948c~tplv-crop-center:1041:582.jpg";        // 视频播放地址        String playerUrl = "https://vd4.bdstatic.com/mda-pdhb52ikamv3bdb7/sc/cae_h264/1681819063478400576/mda-pdhb52ikamv3bdb7.mp4";        // 循环添加数据        for (int i=0,len=8;i<=len;i++){            hashMap = new HashMap<>();            hashMap.put("thumbUrl",thumbUrl);            hashMap.put("playerUrl",playerUrl);            hashMap.put("vtitle","播放"+i);            datas.add(hashMap);        }    }        private void initControls(){        refreshLayout = findViewById(R.id.refreshLayout);        // 下拉刷新事件        refreshLayout.setOnRefreshListener(new OnRefreshListener() {            @Override            public void onRefresh(@NonNull RefreshLayout refreshLayout) {                refreshLayout.finishRefresh(2000);// 传入false表示刷新失败            }        });        // 上拉加载事件        refreshLayout.setOnLoadMoreListener(new OnLoadMoreListener() {            @Override            public void onLoadMore(@NonNull RefreshLayout refreshLayout) {                refreshLayout.finishLoadMore(2000);// 传入false表示加载失败                runOnUiThread(new Runnable() {                    @Override                    public void run() {                        Toast.makeText(getApplication(),"没有更多数据",Toast.LENGTH_SHORT).show();                    }                });            }        });        recyclerView = findViewById(R.id.recyclerView);        // 设置布局        layoutManager = new LinearLayoutManager(this);        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);        recyclerView.setLayoutManager(layoutManager);        // 配置器        VideoAdapter videoAdapter = new VideoAdapter(this,datas);        // 设置点击事件        videoAdapter.setOnItemChildClickListener(new VideoAdapter.OnItemChildClickListener() {            @Override            public void onItemChildClick(int position) {                                startPlay(position);            }        });        recyclerView.setAdapter(videoAdapter);        // RecyclerView监听事件        recyclerView.addOnChildAttachStateChangeListener(new RecyclerView.OnChildAttachStateChangeListener() {            @Override            public void onChildViewAttachedToWindow(@NonNull View view) {            }            @Override            public void onChildViewDetachedFromWindow(@NonNull View view) {                FrameLayout playerContainer = view.findViewById(R.id.player_container);                View v = playerContainer.getChildAt(0);                if (v != null && v == mVideoView && !mVideoView.isFullScreen()){                    releaseVideoView();                }            }        });    }        protected void initVideoView() {        mVideoView = new VideoView(this);        mVideoView.setOnStateChangeListener(new VideoView.SimpleOnStateChangeListener() {            @Override            public void onPlayStateChanged(int playState) {                //监听VideoViewManager释放,重置状态                if (playState == com.dueeeke.videoplayer.player.VideoView.STATE_IDLE) {                    Utils.removeViewFormParent(mVideoView);                    mLastPos = mCurPos;                    mCurPos = -1;                }            }        });        mController = new StandardVideoController(this);        mErrorView = new ErrorView(this);        mController.addControlComponent(mErrorView);        mCompleteView = new CompleteView(this);        mController.addControlComponent(mCompleteView);        mTitleView = new TitleView(this);        mController.addControlComponent(mTitleView);        mController.addControlComponent(new VodControlView(this));        mController.addControlComponent(new GestureView(this));        mController.setEnableOrientation(true);        mVideoView.setVideoController(mController);    }    @Override    public void onPause() {        super.onPause();        pause();    }        protected void pause() {        releaseVideoView();    }    @Override    public void onResume() {        super.onResume();        resume();    }        protected void resume() {        if (mLastPos == -1)            return;        //恢复上次播放的位置        startPlay(mLastPos);    }        protected void startPlay(int position) {        if (mCurPos == position) return;        if (mCurPos != -1) {            releaseVideoView();        }        HashMap entity = datas.get(position);        //边播边存//        String proxyUrl = ProxyVideoCacheManager.getProxy(getActivity()).getProxyUrl(videoBean.getUrl());//        mVideoView.setUrl(proxyUrl);        String playurl = entity.get("playerUrl");        mVideoView.setUrl(playurl);        mTitleView.setTitle(entity.get("vtitle"));        View itemView = layoutManager.findViewByPosition(position);        if (itemView == null) return;        VideoAdapter.ViewHolder viewHolder = (VideoAdapter.ViewHolder) itemView.getTag();        //把列表中预置的PrepareView添加到控制器中,注意isPrivate此处只能为true。        mController.addControlComponent(viewHolder.mPrepareView, true);        Utils.removeViewFormParent(mVideoView);        viewHolder.mPlayerContainer.addView(mVideoView, 0);        //播放之前将VideoView添加到VideoViewManager以便在别的页面也能操作它        getVideoViewManager().add(mVideoView, Tag.LIST);        mVideoView.start();        mCurPos = position;    }        private void releaseVideoView() {        mVideoView.release();        if (mVideoView.isFullScreen()) {            mVideoView.stopFullScreen();        }        if (this.getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {            this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);        }        mCurPos = -1;    }        protected VideoViewManager getVideoViewManager(){        return VideoViewManager.instance();    }}

来源地址:https://blog.csdn.net/qq_19688207/article/details/132186213

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯