代码编织梦想

jjdxm_ijkplayer

项目地址: jjdxm_ijkplayer
简介:基于 ijkplayer 简单的 UI 界面 当前项目是基于 ijkplayer 项目进行的播放器界面 UI 封装。 是一个适用于 Android 的 RTMP 直播推流 SDK,可高度定制化和二次开发。特色是同时支持 H.264 软编/硬编和 AAC 软编/硬编。主要是支持 RIMP、HLS、MP4、M4A 等视频格式的播放。

Copyright notice

我在网上写的文章、项目都可以转载,但请注明出处,这是我唯一的要求。当然纯我个人原创的成果被转载了,不注明出处也是没有关系的,但是由我转载或者借鉴了别人的成果的请注明他人的出处,算是对前辈们的一种尊重吧!

虽然我支持写禁止转载的作者,这是他们的成果,他们有这个权利,但我不觉得强行扭转用户习惯会有一个很好的结果。纯属个人的观点,没有特别的意思。可能我是一个版权意识很差的人吧,所以以前用了前辈们的文章、项目有很多都没有注明出处,实在是抱歉!有想起或看到的我都会逐一补回去。

从一开始,就没指望从我写的文章、项目上获得什么回报,一方面是为了自己以后能够快速的回忆起曾经做过的事情,避免重复造轮子做无意义的事,另一方面是为了锻炼下写文档、文字组织的能力和经验。如果在方便自己的同时,对你们也有很大帮助,自然是求之不得的事了。要是有人转载或使用了我的东西觉得有帮助想要打赏给我,多少都行哈,心里却很开心,被人认可总归是件令人愉悦的事情。

站在了前辈们的肩膀上,才能走得更远视野更广。前辈们写的文章、项目给我带来了很多知识和帮助,我没有理由不去努力,没有理由不让自己成长的更好。写出好的东西于人于己都是好的,但是由于本人自身视野和能力水平有限,错误或者不好的望多多指点交流。

项目中如有不同程度的参考借鉴前辈们的文章、项目会在下面注明出处的,纯属为了个人以后开发工作或者文档能力的方便。如有侵犯到您的合法权益,对您造成了困惑,请联系协商解决,望多多谅解哈!若您也有共同的兴趣交流技术上的问题加入交流群 QQ: 548545202

感谢作者tckingBilibili,本项目借鉴了GiraffePlayer项目,项目一开始的灵感来源于GiraffePlayer项目,后期做纯粹做了视频播放器的界面的定制,基于ijkplayer项目进行的播放器界面 UI 封装。

Introduction

当前项目是基于ijkplayer项目进行的播放器界面 UI 封装。 是一个适用于 Android 的 RTMP 直播推流 SDK,可高度定制化和二次开发。特色是同时支持 H.264 软编/硬编和 AAC 软编/硬编。主要是支持 RIMP、HLS、MP4、M4A 等视频格式的播放。

Features

  1. 基于 ijkplayer 封装的视频播放器界面,支持 RTMP , HLS (http & https) , MP4,M4A 等;
  2. 可根据需求去定制部分界面样式;
  3. 常用的手势操作左边上下亮度,右边上下声音,左右滑动播放进度调整;
  4. 支持多种分辨率流的切换播放;
  5. 播放出错尝试重连;
  6. 界面裁剪显示样式;

Screenshots




Download

demo apk 下载

Download or grab via Maven:

<dependency>
  <groupId>com.dou361.ijkplayer</groupId>
  <artifactId>jjdxm-ijkplayer</artifactId>
  <version>x.x.x</version>
</dependency>

or Gradle:

compile 'com.dou361.ijkplayer:jjdxm-ijkplayer:x.x.x'

历史版本:

compile 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.6'
compile 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.5'
compile 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.4'
compile 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.3'
compile 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.2'
compile 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.1'
compile 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.0'

jjdxm-ijkplayer requires at minimum Java 9 or Android 2.3.

架包的打包引用以及冲突解决

Proguard

根据你的混淆器配置和使用,您可能需要在你的 proguard 文件内配置以下内容:

-keep com.dou361.ijkplayer.** {
*;
}

AndroidStudio 代码混淆注意的问题

Get Started

step1:

依赖本项目类库

该项目是基于 ijkplayer 项目进行的视频 UI 的二次封装,目前只是默认在:

compile 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.5' 

中加入了以下依赖:

compile 'tv.danmaku.ijk.media:ijkplayer-java:0.6.0'
compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.6.0'

如果你的项目中已经有依赖了 v4 或者 v7 包并且使用的版本不一样可能会造成冲突,可以类似下面的方式进行引入依赖

compile('com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.5') {
    exclude group: 'com.android.support', module: 'appcompat-v7'
}

如果要支持多种 ABI 类型的机型,可以根据需要添加以下依赖:

# required, enough for most devices.
compile 'tv.danmaku.ijk.media:ijkplayer-java:0.6.0'
compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.6.0'

# Other ABIs: optional
compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.6.0'
compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.6.0'  //最小版本 21
compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.6.0'
compile 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.6.0'  //最小版本 21

ijkplayer 打包不同的 ABI 后,应该是对 EXO 支持才把部分 ABI 的最小版本设置为 21,考虑到部分机型需要 64 的支持,然而项目最小版本又不行改到 21,当前在项目中加入 x86、x86_64、arm64 文件,以下是提供最小版本为 9 的 compile 依赖出来

//对应 ijkplayer 的  compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.6.0'
compile 'com.dou361.ijkplayer-armv7a:jjdxm-ijkplayer-armv7a:1.0.0'  
//对应 ijkplayer 的  compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.6.0'
compile 'com.dou361.ijkplayer-armv5:jjdxm-ijkplayer-armv5:1.0.0' 
//对应 ijkplayer 的  compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.6.0'
compile 'com.dou361.ijkplayer-arm64:jjdxm-ijkplayer-arm64:1.0.0' 
//对应 ijkplayer 的  compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.6.0'
compile 'com.dou361.ijkplayer-x86:jjdxm-ijkplayer-x86:1.0.0' 
//对应 ijkplayer 的  compile 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.6.0'
compile 'com.dou361.ijkplayer-x86_64:jjdxm-ijkplayer-x86_64:1.0.0'

demo 中原来的 jniLibs 目录下的文件,已经移除,都是使用上面的依赖方式,如果网络环境差 compile 不下来,可以到项目的 release 目录中去下载

step2:

多种分辨率流切换的案例,例如播放器的标清、高清、超清、720P 等。

1.简单的播放器实现

rootView = getLayoutInflater().from(this).inflate(R.layout.simple_player_view_player, null);
setContentView(rootView);
String url = "http://9890.vod.myqcloud.com/9890_9c1fa3e2aea011e59fc841df10c92278.f20.mp4";
player = new PlayerView(this,rootView)
        .setTitle("什么")
        .setScaleType(PlayStateParams.fitparent)
        .hideMenu(true)
        .forbidTouch(false)
        .showThumbnail(new OnShowThumbnailListener() {
            @Override
            public void onShowThumbnail(ImageView ivThumbnail) {
                Glide.with(mContext)
                        .load("http://pic2.nipic.com/20090413/406638_125424003_2.jpg")
                        .placeholder(R.color.cl_default)
                        .error(R.color.cl_error)
                        .into(ivThumbnail);
            }
        })
        .setPlaySource(url)
        .startPlay();

2.多种不同的分辨率流的播放器实现

在布局中使用 simple_player_view_player.xml 布局

<include
    layout="@layout/simple_player_view_player"
    android:layout_width="match_parent"
    android:layout_height="180dp"/>

代码中创建一个播放器对象

/**播放资源*/
ist<VideoijkBean> list = new ArrayList<VideoijkBean>();
String url1 = "http://9890.vod.myqcloud.com/9890_4e292f9a3dd011e6b4078980237cc3d3.f20.mp4";
String url2 = "http://9890.vod.myqcloud.com/9890_4e292f9a3dd011e6b4078980237cc3d3.f30.mp4";
VideoijkBean m1 = new VideoijkBean();
m1.setStream("标清");
m1.setUrl(url1);
VideoijkBean m2 = new VideoijkBean();
m2.setStream("高清");
m2.setUrl(url2);
list.add(m1);
list.add(m2);
/**播放器*/
rootView = getLayoutInflater().from(this).inflate(你的布局, null);
setContentView(rootView);
player = new PlayerView(this,rootView)
            .setTitle("什么")
            .setScaleType(PlayStateParams.fitparent)
            .hideMenu(true)
            .forbidTouch(false)
            .showThumbnail(new OnShowThumbnailListener() {
                @Override
                public void onShowThumbnail(ImageView ivThumbnail) {
                    /**加载前显示的缩略图*/
                    Glide.with(mContext)
                            .load("http://pic2.nipic.com/20090413/406638_125424003_2.jpg")
                            .placeholder(R.color.cl_default)
                            .error(R.color.cl_error)
                            .into(ivThumbnail);
                }
            })
            .setPlaySource(list)
            .startPlay();

step3:

配置生命周期方法,为了让播放器同步 Activity 生命周期,建议以下方法都去配置,注释的代码,主要作用是播放时屏幕常亮和暂停其它媒体的播放。

 @Override
protected void onPause() {
    super.onPause();
    if (player != null) {
        player.onPause();
    }
    /**demo 的内容,恢复系统其它媒体的状态*/
    //MediaUtils.muteAudioFocus(mContext, true);
}

@Override
protected void onResume() {
    super.onResume();
    if (player != null) {
        player.onResume();
    }
    /**demo 的内容,暂停系统其它媒体的状态*/
    MediaUtils.muteAudioFocus(mContext, false);
    /**demo 的内容,激活设备常亮状态*/
    //if (wakeLock != null) {
    //    wakeLock.acquire();
    //}
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (player != null) {
        player.onDestroy();
    }
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (player != null) {
        player.onConfigurationChanged(newConfig);
    }
}

@Override
public void onBackPressed() {
    if (player != null && player.onBackPressed()) {
        return;
    }
    super.onBackPressed();
    /**demo 的内容,恢复设备亮度状态*/
    //if (wakeLock != null) {
    //    wakeLock.release();
    //}
}

More Actions

1.视频界面裁剪设置,可通过方法 setScaleType(int type)去设置

1. PlayStateParams.fitParent:可能会剪裁,保持原视频的大小,显示在中心,当原视频的大小超过 view 的大小超过部分裁剪处理
2. PlayStateParams.fillParent:可能会剪裁,等比例放大视频,直到填满 View 为止,超过 View 的部分作裁剪处理
3. PlayStateParams.wrapcontent:将视频的内容完整居中显示,如果视频大于 view,则按比例缩视频直到完全显示在 view 中
4. PlayStateParams.fitXY:不剪裁,非等比例拉伸画面填满整个 View
5. PlayStateParams.f16_9:不剪裁,非等比例拉伸画面到 16:9,并完全显示在 View 中
6. PlayStateParams.f4_3:不剪裁,非等比例拉伸画面到 4:3,并完全显示在 View 中

2.自定义视频界面,可以复制以下布局内容到自己的项目中,注意已有的 id 不能修改或删除,可以增加 view,可以对以下布局内容调整显示位置或者自行隐藏

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


    <com.dou361.ijkplayer.widget.IjkVideoView
        android:id="@+id/video_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <LinearLayout
        android:id="@+id/ll_bg"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/black"
        android:orientation="vertical">

        <!-- 封面显示-->
        <ImageView
            android:id="@+id/iv_trumb"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="fitXY"
            android:visibility="visible"/>
    </LinearLayout>

    <!--重新播放-->
    <LinearLayout
        android:id="@+id/app_video_replay"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#33000000"
        android:gravity="center"
        android:orientation="vertical"
        android:visibility="gone">
        <!-- 播放状态-->
        <TextView
            android:id="@+id/app_video_status_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/small_problem"
            android:textColor="@android:color/white"
            android:textSize="14dp"/>

        <ImageView
            android:id="@+id/app_video_replay_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="8dp"
            android:src="@drawable/simple_player_circle_outline_white_36dp"/>
    </LinearLayout>
    <!-- 网络提示-->
    <LinearLayout
        android:id="@+id/app_video_netTie"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#33000000"
        android:gravity="center"
        android:orientation="vertical"
        android:visibility="gone">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:gravity="center"
            android:paddingLeft="8dp"
            android:paddingRight="8dp"
            android:text="您正在使用移动网络播放视频\n 可能产生较高流量费用"
            android:textColor="@android:color/white"/>

        <TextView
            android:id="@+id/app_video_netTie_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/simple_player_btn"
            android:gravity="center"
            android:paddingLeft="8dp"
            android:paddingRight="8dp"
            android:text="继续"
            android:textColor="@android:color/white"/>
    </LinearLayout>

    <!--加载中-->
    <LinearLayout
        android:id="@+id/app_video_loading"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        android:visibility="gone">

        <ProgressBar
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:indeterminateBehavior="repeat"
            android:indeterminateOnly="true"/>
        <TextView
            android:id="@+id/app_video_speed"
            android:layout_width="wrap_content"
            android:layout_marginTop="4dp"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:visibility="gone"
            android:text="188Kb/s"
            android:textColor="@android:color/white"/>
    </LinearLayout>

    <!-- 中间触摸提示-->
    <include
        layout="@layout/simple_player_touch_gestures"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"/>

    <!-- 顶部栏-->
    <include layout="@layout/simple_player_topbar"/>
    <!-- 底部栏-->
    <include
        layout="@layout/simple_player_controlbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"/>

    <!--声音亮度控制-->
    <LinearLayout
        android:id="@+id/simple_player_settings_container"
        android:layout_width="250dp"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:background="#80000000"
        android:gravity="center_vertical"
        android:orientation="vertical"
        android:visibility="visible">

        <LinearLayout
            android:id="@+id/simple_player_volume_controller_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:orientation="horizontal">

            <ImageView
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:src="@drawable/qcloud_player_icon_audio_vol_mute"/>

            <SeekBar
                android:id="@+id/simple_player_volume_controller"
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="150dp"
                android:layout_height="wrap_content"/>

            <ImageView
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:src="@drawable/qcloud_player_icon_audio_vol"/>
        </LinearLayout>

        <LinearLayout
            android:id="@+id/simple_player_brightness_controller_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:gravity="center"
            android:orientation="horizontal">

            <ImageView
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:padding="5dp"
                android:src="@drawable/qcloud_player_icon_brightness"/>

            <SeekBar
                android:id="@+id/simple_player_brightness_controller"
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="150dp"
                android:layout_height="wrap_content"/>

            <ImageView
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:src="@drawable/qcloud_player_icon_brightness"/>
        </LinearLayout>

    </LinearLayout>


    <!--分辨率选择-->
    <LinearLayout
        android:id="@+id/simple_player_select_stream_container"
        android:layout_width="150dp"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:background="#80000000"
        android:gravity="center_vertical"
        android:visibility="gone">

        <ListView
            android:id="@+id/simple_player_select_streams_list"
            android:layout_width="150dp"
            android:layout_height="wrap_content"/>
    </LinearLayout>


    <ImageView
        android:id="@+id/play_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginTop="8dp"
        android:src="@drawable/simple_player_center_play"/>

</RelativeLayout>

3.播放器 PlayerView 对象的方法如下:

PlayerView(Activity activity)

//生命周期方法回调
PlayerView onPause()
PlayerView onResume()
PlayerView onDestroy()
PlayerView onConfigurationChanged(final Configuration newConfig)
boolean onBackPressed()
//显示缩略图
PlayerView showThumbnail(OnShowThumbnailListener onShowThumbnailListener)
//设置播放信息监听回调
PlayerView setOnInfoListener(IMediaPlayer.OnInfoListener onInfoListener)
//设置播放器中的返回键监听
PlayerView setPlayerBackListener(OnPlayerBackListener listener)
//设置控制面板显示隐藏监听
PlayerView setOnControlPanelVisibilityChangListenter(OnControlPanelVisibilityChangeListener listener)
//百分比显示切换
PlayerView toggleAspectRatio()
//设置播放区域拉伸类型
PlayerView setScaleType(int showType)
//旋转角度
PlayerView setPlayerRotation()
//旋转指定角度
PlayerView setPlayerRotation(int rotation)
//设置播放地址包括视频清晰度列表对应地址列表
PlayerView setPlaySource(List<VideoijkBean> list)
//设置播放地址单个视频 VideoijkBean
PlayerView setPlaySource(VideoijkBean videoijkBean)
//设置播放地址单个视频地址时带流名称
PlayerView setPlaySource(String stream, String url)
//设置播放地址单个视频地址时
PlayerView setPlaySource(String url)
//自动播放
PlayerView autoPlay(String path)
//开始播放
PlayerView startPlay()
//设置视频名称
PlayerView setTitle(String title)
//选择要播放的流
PlayerView switchStream(int index)
//暂停播放
PlayerView pausePlay()
//停止播放
PlayerView stopPlay()
//设置播放位置
PlayerView seekTo(int playtime)
//获取当前播放位置
int getCurrentPosition()
//获取视频播放总时长
long getDuration()
//设置 2/3/4/5G 和 WiFi 网络类型提示 true 为进行 2/3/4/5G 网络类型提示 false 不进行网络类型提示
PlayerView setNetWorkTypeTie(boolean isGNetWork)
//是否仅仅为全屏
PlayerView setOnlyFullScreen(boolean isFull)
//设置是否禁止双击
PlayerView setForbidDoulbeUp(boolean flag)
//当前播放的是否是直播
boolean isLive()
//是否禁止触摸
PlayerView forbidTouch(boolean forbidTouch)
//隐藏所有状态界面
PlayerView hideAllUI()
获取顶部控制 barview
View getTopBarView()
//获取底部控制 barview
View getBottonBarView()
//获取旋转 view
ImageView getRationView()
//获取返回 view
ImageView getBackView()
//获取菜单 view
ImageView getMenuView()
//获取全屏按钮 view
ImageView getFullScreenView()
//获取底部 bar 的播放 view
ImageView getBarPlayerView()
//获取中间的播放 view
ImageView getPlayerView()
//隐藏返回键,true 隐藏,false 为显示
PlayerView hideBack(boolean isHide)
//隐藏菜单键,true 隐藏,false 为显示
PlayerView hideMenu(boolean isHide)
//隐藏分辨率按钮,true 隐藏,false 为显示
PlayerView hideSteam(boolean isHide)
//隐藏旋转按钮,true 隐藏,false 为显示
PlayerView hideRotation(boolean isHide)
//隐藏全屏按钮,true 隐藏,false 为显示
PlayerView hideFullscreen(boolean isHide)
//隐藏中间播放按钮,ture 为隐藏,false 为不做隐藏处理,但不是显示
PlayerView hideCenterPlayer(boolean isHide)
//显示或隐藏操作面板
PlayerView operatorPanl()
//全屏切换
PlayerView toggleFullScreen()
//设置自动重连的模式或者重连时间,isAuto true 出错重连,false 出错不重连,connectTime 重连的时间
setAutoReConnect(boolean isAuto, int connectTime)
//进度条和时长显示的方向切换
PlayerView toggleProcessDurationOrientation()
//设置进度条和时长显示的方向,默认为上下显示,PlayStateParams.PROCESS_PORTRAIT 为上下显示 PlayStateParams.PROCESS_LANDSCAPE 为左右显示 PlayStateParams.PROCESS_CENTER 为中间两边样式
setProcessDurationOrientation(int portrait)
//显示菜单设置
showMenu()
//获取界面方向
int getScreenOrientation()
//显示加载网速
PlayerView setShowSpeed(boolean isShow)
//是否隐藏 topbar,true 为隐藏,false 为不隐藏,但不一定是显示
PlayerView hideHideTopBar(boolean isHide)
//是否隐藏 bottonbar,true 为隐藏,false 为不隐藏,但不一定是显示
PlayerView hideBottonBar(boolean isHide)
//是否隐藏上下 bar,true 为隐藏,false 为不隐藏,但不一定是显示
PlayerView hideControlPanl(boolean isHide)
//设置是否禁止隐藏 bar,优先级低于 hideControlPanl
PlayerView setForbidHideControlPanl(boolean flag)

4.全屏隐藏虚拟按键方法

参考 HPlayerActivity 类,获取 Activity 的根目录

main = getLayoutInflater().from(this).inflate(R.layout.activity_h, null);

然在在 oncreate()方法中设置监听

    /**虚拟按键的隐藏方法*/
    main.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        @Override
        public void onGlobalLayout() {

            //比较 Activity 根布局与当前布局的大小
            int heightDiff = main.getRootView().getHeight() - main.getHeight();
            if (heightDiff > 100) {
                //大小超过 100 时,一般为显示虚拟键盘事件
                main.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
            } else {
                //大小小于 100 时,为不显示虚拟键盘或虚拟键盘隐藏
                main.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);

            }
        }
    });

5.半屏视频,横竖屏切换时不填满问题

1.确保 Activity 中调用生命周期方法

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    if (player != null) {
        player.onConfigurationChanged(newConfig);
    }
}

2.确保清单文件中配置属性

android:configChanges="orientation|keyboardHidden|screenSize"
        android:screenOrientation="portrait"

例如

<activity
        android:name="com.dou361.jjdxm_ijkplayer.HPlayerActivity"
        android:configChanges="orientation|keyboardHidden|screenSize"
        android:screenOrientation="portrait"
        android:theme="@style/AppTheme"/>

关于定制

隐藏部分不想要的界面

//隐藏返回键,true 隐藏,false 为显示
PlayerView hideBack(boolean isHide)
//隐藏菜单键,true 隐藏,false 为显示
PlayerView hideMenu(boolean isHide)
//隐藏分辨率按钮,true 隐藏,false 为显示
PlayerView hideSteam(boolean isHide)
//隐藏旋转按钮,true 隐藏,false 为显示
PlayerView hideRotation(boolean isHide)
//隐藏全屏按钮,true 隐藏,false 为显示
PlayerView hideFullscreen(boolean isHide)
//隐藏中间播放按钮,ture 为隐藏,false 为不做隐藏处理,但不是显示
PlayerView hideCenterPlayer(boolean isHide)

加载时显示网速

默认加载时不显示网速,可以通过 setShowSpeed(boolean isShow)设置加载时是否需要显示,true 为显示,false 为不显示

播放器底部 bar 播放进度条样式定制

默认的进度样式是竖屏为上下样式,即进度条在播放时长的上面,横屏为左右样式,即进度条在播放时长的中间。样式定制主要是两个方法搭配使用 toggleProcessDurationOrientation 方法和 setProcessDurationOrientation 方法,横竖屏切换 2 中情况,和 3 种进度条样式

/**上下样式*/
PlayStateParams.PROCESS_PORTRAIT
/**左右样式*/
PlayStateParams.PROCESS_LANDSCAPE
/**中间两边样式*/
PlayStateParams.PROCESS_CENTER

总共有 2 的 3 次方中样式,下面只罗列几种样式

1.横竖屏都为上下样式

rootView = getLayoutInflater().from(this).inflate(你的布局, null);
setContentView(rootView);
player = new PlayerView(this,rootView) {
        @Override
        public PlayerView toggleProcessDurationOrientation() {
            return setProcessDurationOrientation(PlayStateParams.PROCESS_PORTRAIT);
        }
    }
            .setTitle("什么")
            .setProcessDurationOrientation(PlayStateParams.PROCESS_PORTRAIT)
            .setScaleType(PlayStateParams.fitparent)
            .forbidTouch(false)
            .hideCenterPlayer(true)
            .setPlaySource(list)
            .startPlay();

2.横竖屏都为左右样式

rootView = getLayoutInflater().from(this).inflate(你的布局, null);
setContentView(rootView);
player = new PlayerView(this,rootView) {
        @Override
        public PlayerView toggleProcessDurationOrientation() {
            return setProcessDurationOrientation(PlayStateParams.PROCESS_LANDSCAPE);
        }
    }
            .setTitle("什么")
            .setProcessDurationOrientation(PlayStateParams.PROCESS_LANDSCAPE)
            .setScaleType(PlayStateParams.fitparent)
            .forbidTouch(false)
            .hideCenterPlayer(true)
            .setPlaySource(list)
            .startPlay();

3.横屏为上下样式竖屏为左右样式

rootView = getLayoutInflater().from(this).inflate(你的布局, null);
setContentView(rootView);
player = new PlayerView(this,rootView) {
        @Override
        public PlayerView toggleProcessDurationOrientation() {
            return setProcessDurationOrientation(getScreenOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE?PlayStateParams.PROCESS_LANDSCAPE:PlayStateParams.PROCESS_PORTRAIT);
        }
    }
            .setTitle("什么")
            .setProcessDurationOrientation(PlayStateParams.PROCESS_LANDSCAPE)
            .setScaleType(PlayStateParams.fitparent)
            .forbidTouch(false)
            .hideCenterPlayer(true)
            .setPlaySource(list)
            .startPlay();

4.横屏为左右样式竖屏为上下样式

rootView = getLayoutInflater().from(this).inflate(你的布局, null);
setContentView(rootView);
player = new PlayerView(this,rootView) {
        @Override
        public PlayerView toggleProcessDurationOrientation() {
            return setProcessDurationOrientation(getScreenOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT?PlayStateParams.PROCESS_PORTRAIT:PlayStateParams.PROCESS_LANDSCAPE);
        }
    }
            .setTitle("什么")
            .setProcessDurationOrientation(PlayStateParams.PROCESS_CENTER)
            .setScaleType(PlayStateParams.fitparent)
            .forbidTouch(false)
            .hideCenterPlayer(true)
            .setPlaySource(list)
            .startPlay();

5.横屏为左右样式竖屏为中间两边样式

rootView = getLayoutInflater().from(this).inflate(你的布局, null);
setContentView(rootView);
player = new PlayerView(this,rootView) {
        @Override
        public PlayerView toggleProcessDurationOrientation() {
            return setProcessDurationOrientation(getScreenOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT?PlayStateParams.PROCESS_CENTER:PlayStateParams.PROCESS_LANDSCAPE);
        }
    }
            .setTitle("什么")
            .setProcessDurationOrientation(PlayStateParams.PROCESS_CENTER)
            .setScaleType(PlayStateParams.fitparent)
            .forbidTouch(false)
            .hideCenterPlayer(true)
            .setPlaySource(list)
            .startPlay();

3.ijkplayer 封装的视频播放信息返回码监听,可以通过 setOnInfoListener 去监听

/*
 * Do not change these values without updating their counterparts in native
 */
int MEDIA_INFO_UNKNOWN = 1;//未知信息
int MEDIA_INFO_STARTED_AS_NEXT = 2;//播放下一条
int MEDIA_INFO_VIDEO_RENDERING_START = 3;//视频开始整备中
int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700;//视频日志跟踪
int MEDIA_INFO_BUFFERING_START = 701;//开始缓冲中
int MEDIA_INFO_BUFFERING_END = 702;//缓冲结束
int MEDIA_INFO_NETWORK_BANDWIDTH = 703;//网络带宽,网速方面
int MEDIA_INFO_BAD_INTERLEAVING = 800;//
int MEDIA_INFO_NOT_SEEKABLE = 801;//不可设置播放位置,直播方面
int MEDIA_INFO_METADATA_UPDATE = 802;//
int MEDIA_INFO_TIMED_TEXT_ERROR = 900;
int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901;//不支持字幕
int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902;//字幕超时

int MEDIA_INFO_VIDEO_INTERRUPT= -10000;//数据连接中断
int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;//视频方向改变
int MEDIA_INFO_AUDIO_RENDERING_START = 10002;//音频开始整备中

int MEDIA_ERROR_UNKNOWN = 1;//未知错误
int MEDIA_ERROR_SERVER_DIED = 100;//服务挂掉
int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;//数据错误没有有效的回收
int MEDIA_ERROR_IO = -1004;//IO 错误
int MEDIA_ERROR_MALFORMED = -1007;
int MEDIA_ERROR_UNSUPPORTED = -1010;//数据不支持
int MEDIA_ERROR_TIMED_OUT = -110;//数据超时

ChangeLog

2016.09.05 修改支持非 Activity 中使用当前播放器 view,例如 fragment、holder 之类使用,添加直播地址获取,提供可观看案例(如直播地址有不妥的地方可联系删除,多有得罪啦) 遗留问题: 触摸时,隐藏动作取消 触摸时,进度条面会有点共用 直播停止开始卡帧 手动换源卡帧 直播判断问题 进度条隐藏提取方法出来 修改初始化方法 本地视频播放问题 播放加载状态的监听问题比如说链接失效,请求超时,断流了,断网了之类的 缓冲好内容使用 seekto 之后还是需要重新缓冲 乐视手机 点开亮度为 0

2016.08.30 修复播放时长为零问题;修复使用拉伸方法横屏方向不起效问题;修改最小支持版本为 9;添加了 SO 文件的最小版本为 9 的类库;添加 VideoijkBean 比较方法,可以比对视频对象是不是同一个;添加横竖屏配置说明;添加隐藏虚拟按键的方法。

2016.08.26 1.0.5 添加上下操作工具栏的隐藏定制,主要是 hideControlPanl,hideHideTopBar 和 hideBottonBar 方法控制

2016.08.26 1.0.4 打包修复播放进度样式点击返回键不起效

2016.08.25 1.0.3 添加视频播放进度条样式,添加菜单设置

2016.08.24 1.0.2 修复播放出错点击没有反应,这是修改旋转视频方向是造成的 bug,当前默认为 5 秒无操作自动重试,修改加载进度条的显示时间,之前是加载回调整备中才显示,改为点击加载立即显示,新增修改自动重试的方式和重试的时间

2016.08.20 修复视频进入后台继续播放,切换视频源是画面卡住等问题

2016.08.20 1.0.1 修复点击播放、点击暂停、再点击播放时,加载进度条一直显示问题;修复第一次打开播放器,触摸视频界面,视频重新播放问题;恢复视频拖动条默认样式,修复显示不完整问题;添加对外操作的 view,可通过 getxxxView()方法获得;添加了 PlayerView 对象的方法及说明,可链式开发。

About Author

个人网站:http://www.dou361.com

GitHub:jjdxmashl

QQ:316988670

交流 QQ 群:548545202


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u014608640/article/details/52607577

jjdxm-ijkplayer开源视频框架简单的日常使用_changechances的博客-爱代码爱编程_jjdxm_ijkplayer

jjdxm-ijkPlayer开源视频框架简单的日常使用 一.前提申明: 1.转自开源贡献者jjdxmashl 点击这里查看github源地址 2.开发环境:as 3.jjdxm-ijkPlayer版本1.0.6(这里请注

android基础学习总结(十六)——基于ijkplayer封装支持简单界面ui定制的视频播放器_万般滋味皆生活的博客-爱代码爱编程

前言 项目开发中遇到需要解析播放m3u8视频流的情况,但是原生的PlayerView非常慢,使用起来复杂,不适合上手,这里找到一款ijkplayer是Bilibili基于ffmpeg开发并开源的轻量级视频播放器,支持播放本

ijkplayer播放视频的简单应用-爱代码爱编程

导入依赖 compile 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.5' 权限 <uses-permission android:name="android.permi

超级简单的播放视频的方法(ijkplayer)-爱代码爱编程

搭建环境,导入依赖 implementation 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.5' 权限 <uses-permission android:name="

android使用jjdxm-ijkplayer播放视频_「已注销」的博客-爱代码爱编程_jjdxm_ijkplayer

添加依赖更改配置信息添加权限布局文件逻辑 添加依赖 implementation 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.5' 更改配置信息 AndroidManife

Android Q 滑屏解锁误操作判断规则-爱代码爱编程

滑屏解锁误判断规则。 android P之前: com.android.systemui.statusbar.phone.PanelView protected boolean flingExpands(float vel, float vectorVel, float x, float y) { if (isFalseTou

Android仿抖音主页效果实现-爱代码爱编程

目录 写在前面 一、准备工作 1.1、主页面布局 1.2、列表Item布局 1.3、列表Item适配器 二、自定义LayoutManager 三、实现播放 补充:源码地址:https://github.com/JArchie/TiktokDemo 写在前面 各位老铁,我又来啦!既然来了,那肯定又来搞事情啦,话不多说,先上图!

iptv电视直播app_IPTV还能这样免费看的-爱代码爱编程

众所周知,随着电视的升级,IPTV也逐渐走进各家各户。而这个IPTV用户一般是三大网络运营商旗下的用户。这是宽带下带来的另一个业务,当然这个IPTV可以选择性开通。当然开通是另外收费的。 而有没有方法可以“免费”观看呢?当然是有的。 这就是网络机顶盒或者自带机顶盒的电视。安装第三方直播软件。 如:电视家3.0、小薇直播、火星直

android最新直播框架,Android直播类框架-爱代码爱编程

直播 KingTV https://github.com/jenly1314/KingTV jjdxm-ijkplayer 直播相关开源框架 compile 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.5' //--- compile 'tv.danmaku.ijk.media:ijkplayer-

android b站 播放器,IjkPlayer(B站播放器)-爱代码爱编程

第一步,当然是导入依赖 implementation 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.5' 紧接着,在清单文件中获取权限 布局: android:id="@+id/ijk_iv_rotation" android:layout_width="match_parent" android:

Android-超好用的播放器——ijkplayer,移动应用开发课程感想-爱代码爱编程

//生成一个新的surface view surfaceView = new SurfaceView(mContext); surfaceView.getHolder().addCallback(new LmnSurfaceCallback()); LayoutParams layoutParams = new LayoutParams(LayoutPar

编译好的ijkplayer导入AS工程进行二次开发-爱代码爱编程

关于ijkplayer的编译,可以先看前面的文章--ijkplayer编译流程详解 编译好之后,导入AS工程,导入的时候还是遇到了一些问题,这里记录一下。 1、ERROR: Failed to resolve: com.android.support:appcompat-v7:23.0.1 使用androidstudio打开android/ijk

mediacodec硬解流程_音视频开发老舅的博客-爱代码爱编程

一 MediaCodec概述 MediaCodec 是Android 4.1(api 16)版本引入的低层编解码接口,同时支持音视频的编码和解码。通常与MediaExtractor、MediaMuxer、AudioTrack结合使用,能够编解码诸如H.264、H.265、AAC、3gp等常见的音视频格式。MediaCodec在编解码的过程中使用了一组输入

ijkplayer基于rtsp直播延时的深度优化-爱代码爱编程

现在ijkPlayer是许多播放器、直播平台的首选,相信很多开发者都接触过ijkPlayer,无论是Android工程师还是iOS工程师。我曾经在Github上的ijkPlayer开源项目上提问过:视频流为1080P、30fps,如何优化RTSP直播的延时为大约100ms呢? 发现大家对RTSP直播延时优化非常感兴趣,纷纷提问或者给出自己的观点。本文主要

第三方视频播放-爱代码爱编程

ijkplayer可以支持网络和本地的视频播放,注意路径就可以了 添加依赖 compile 'com.dou361.ijkplayer:jjdxm-ijkplayer:1.0.5' 布局文件 <com.dou361.ijkplayer.widget.IjkVideoView android:layout_width="mat

编译ijkplayer步骤流程和遇到的坑_ijkplayer windows编译-爱代码爱编程

一、编译环境 1、系统:window11下的子系统Ubuntu18.04.5 LTS 2、jdk:1.8.0_312 3、ndk:android-ndk-r10e-linux-x86_64 4、sdk:android-sdk_r24.4.1-linux 二、编译环境及相关依赖搭建 1、安装必要的软件和依赖 sudo