基于exoPlayer 拓展自定義播放器

基于exoPlayer 自定義播放器 Jplayer支持功能:

  • 1 ExoUserPlayer 基本播放
  • 2 GestureVideoPlayer 增加手勢(shì) 亮度粗悯,音量,快進(jìn),等手勢(shì)
  • 3 ManualPlayer 默認(rèn)手動(dòng)播放荆几,增加默認(rèn)圖
  • 5 增加廣告視頻預(yù)覽切換
  • 6 增加視頻清晰度切換
  • 7 增加緩存視頻功能
  • 8 支持自定義各種數(shù)據(jù)源加載 Okttp,Rtmp, 緩存,Cronet等協(xié)議,
  • 9 支持列表播放視頻
  • 10 支持多種文件類型,MP4,M4A唉锌,WebM,Matroska竿奏,Ogg袄简,WAV,MP3泛啸,MPEG-TS绿语,MPEG-PS,F(xiàn)LV候址,ADTS (AAC)吕粹,F(xiàn)lac,M3U8 等
  • 11 支持網(wǎng)絡(luò)類型 提示是否播放

預(yù)覽 顯示有點(diǎn)卡宗雇,幀數(shù)低昂芜,實(shí)際很流暢

sss.gif

一.引用類庫(kù)

 repositories {
        jcenter()
        maven { url "https://jitpack.io" }
    }
    
dependencies {
   compile 'com.ycjiang:VideoPlayModule:1.5.4'

}

最新版本號(hào)--戳我

二.控件屬性

1.控件屬性引用

  <chuangyuan.ycj.videolibrary.widget.VideoPlayerView
        android:id="@+id/exo_play_context_id"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent"
        app:resize_mode="fit"
        app:show_timeout="3000"
        app:controller_layout_id="@layout/simple_exo_playback_control_view"
        app:player_layout_id="@layout/simple_exo_view"
        app:surface_type="texture_view"
        app:use_artwork="true"
        app:paddingEnd="0dp"
        app:paddingStart="0dp"
        app:fastforward_increment="0"
        app:rewind_increment="0"
        app:user_watermark="@mipmap/watermark_big"
        app:player_list="true"
        app:use_controller="true" />

2.屬性說(shuō)明

  1. player_layout_id 播放器布局, //必選
player_layout_id 目前支持指定布局simple_exo_playback_control_view 后續(xù)版本赔蒲,開(kāi)放自定義使用這自定義
  1. controller_layout_id 控制器布局` //必選
controller_layout_id  支持自定義布局
  1. surface_type 視頻渲染類型 //texture_view 和surface_view //枚舉類型。默認(rèn)surface_view
    列表播放只能選擇texture_view 不能選擇surface_view良漱,詳情頁(yè)面播放推薦surface_view 
  1. use_controller 是否用戶控制控制器 布爾類型
  2. resize_mode 視頻縮放渲染顯示方式一共4種 //可選 美劇類型
    1.fit          //正常模式
    2.fixed_width  //保持的是視頻寬度舞虱,拉伸視頻高度
    3.fixed_height //保持的是視頻高度,拉伸視頻寬度
    4.fill          //全屏模式母市,拉伸視頻寬高
  1. default_artwork 占位圖 //可選
 占位圖 注意在控制布局后下面
  1. show_timeout 控制布局隱藏時(shí)間 默認(rèn)值為3秒 //可選
  2. paddingEnd矾兜,paddingStart 設(shè)置邊距 默認(rèn)值為0 //可選
  3. fastforward_increment 設(shè)置快進(jìn)增量,以毫秒為單位。 //可選
  4. rewind_increment 設(shè)置快退增量,以毫秒為單位患久。 //可選
  5. user_watermark 水印圖片 默認(rèn)在右上角 //可選
  6. player_list 是否指定列表播放 //可選 默認(rèn) false true 列表播放

3.修改網(wǎng)絡(luò)對(duì)話框提示文字內(nèi)容

 app.strings.xml
 <string name="exo_play_reminder">您當(dāng)前網(wǎng)絡(luò)不是wifi椅寺,是否繼續(xù)觀看視頻</string>
 <string name="exo_play_wifi_hint_no">提示</string>

4.在功能清單聲明 AndroidManifest.xml

在activity節(jié)點(diǎn) 加上“android:configChanges="orientation|keyboardHidden|screenSize"”
如下實(shí)例:

      <activity android:name="chuangyuan.ycj.yjplay.MainListActivity"
       android:configChanges="orientation|keyboardHidden|screenSize"
       android:screenOrientation="portrait">

3.JAVA 代碼

1 播放控制類

1.ExoUserPlayer 基本播放父類浑槽,實(shí)現(xiàn)基本播放,設(shè)置setPlayUri();會(huì)自動(dòng)加載播放
2.GestureVideoPlayer 具有手勢(shì)操作播放(調(diào)節(jié)亮度和視頻進(jìn)度,和音量)會(huì)自動(dòng)加載播放
2.ManualPlayer 點(diǎn)擊開(kāi)始按鈕播放,具有手勢(shì)功能返帕,和列表播放

2 播放

//實(shí)例化播放控制類
 ManualPlayer exoPlayerManager = new ManualPlayer(this,R.id.exo_play_context_id);
//自定義你的數(shù)據(jù)源桐玻,后面詳細(xì)介紹如何自定義數(shù)據(jù)源類
 // ManualPlayer exoPlayerManager = new ManualPlayer(this,R.id.exo_play_context_id,new DataSource(this));
 //加載m3u8
 exoPlayerManager.setPlayUri("http://dlhls.cdn.zhanqi.tv/zqlive/35180_KUDhx.m3u8");
 //加載ts.文件
 exoPlayerManager.setPlayUri("http://185.73.239.15:25461/live/1/1/924.ts");
 //播放本地視頻
 // exoPlayerManager.setPlayUri("/storage/emulated/0/DCIM/Camera/VID_20170717_011150.mp4");
 //下面開(kāi)啟多線路播放
 //  exoPlayerManager.setShowVideoSwitch(true); //開(kāi)啟切換按鈕,默認(rèn)關(guān)閉
 //String [] test={"http://120.25.246.21/vrMobile/travelVideo/zhejiang_xuanchuanpian.mp4","http://120.25.246.21/vrMobile/travelVideo/zhejiang_xuanchuanpian.mp4","http://120.25.246.21/vrMobile/travelVideo/zhejiang_xuanchuanpian.mp4"};
 // String[] name={"超清","高清","標(biāo)清"};
 //exoPlayerManager.setPlaySwitchUri(test,name);
 //添加水印圖片
 // exoPlayerManager.setExoPlayWatermarkImg();

1.實(shí)例化播放控制類

  ManualPlayer exoPlayerManager = new ManualPlayer(this,R.id.exo_play_context_id);
  ManualPlayer exoPlayerManager = new ManualPlayer(this,videoPlayerView);

2.自定義你的數(shù)據(jù)源荆萤,后面詳細(xì)介紹如何自定義數(shù)據(jù)源類

 ManualPlayer exoPlayerManager = new ManualPlayer(this,R.id.exo_play_context_id,new DataSource(this));
 ManualPlayer exoPlayerManager = new ManualPlayer(this,videoPlayerView,new DataSource(this));

3.設(shè)置視頻標(biāo)題

  exoPlayerManager.setTitle("視頻標(biāo)題");

4.添加水印圖片

 exoPlayerManager.setExoPlayWatermarkImg(R.mipmap.watermark_big);     

5.設(shè)置開(kāi)始播放進(jìn)度

 exoPlayerManager.setPosition(1000)

6.設(shè)置視頻路徑

 exoPlayerManager.setPlayUri("http://dlhls.cdn.zhanqi.tv/zqlive/35180_KUDhx.m3u8");
 exoPlayerManager.setPlayUri(Uri.parse("http://dlhls.cdn.zhanqi.tv/zqlive/35180_KUDhx.m3u8"));
 exoPlayerManager.setPlayUri(Environment.getExternalStorageDirectory().getAbsolutePath()+"/test.h264"); //本地視頻

7.設(shè)置多線路播放

  //開(kāi)啟多線路設(shè)置镊靴,默認(rèn)關(guān)閉 
  exoPlayerManager.setShowVideoSwitch(true);
  //支持List列表
  String [] test={"http://120.25.246.21/vrMobile/travelVideo/zhejiang_xuanchuanpian.mp4",
  "http://120.25.246.21/vrMobile/travelVideo/zhejiang_xuanchuanpian.mp4",
   http://120.25.246.21/vrMobile/travelVideo/zhejiang_xuanchuanpian.mp4"};
   String[] name={"超清","高清","標(biāo)清"};
   exoPlayerManager.setPlaySwitchUri(test,name);

8.設(shè)置監(jiān)聽(tīng)回調(diào)VideoInfoListener

 exoPlayerManager.setVideoInfoListener(new VideoInfoListener() {
               @Override
               public void onPlayStart() {
                     //開(kāi)始播放
               }
   
               @Override
               public void onLoadingChanged() {
                         //加載變化
               }
   
               @Override
               public void onPlayerError(ExoPlaybackException e) {
                         //加載錯(cuò)誤
              }
   
               @Override
               public void onPlayEnd() {
                      //播放結(jié)束
               }
               @Override
               public void onRepeatModeChanged(int repeatMode) {
                   //模式變化
               }
           });  

9.覆寫Activity和Fragment周期方法

        Override
        public void onResume() {
            super.onResume();
            Log.d(TAG, "onResume");
            exoPlayerManager.onResume();
        }
    
        @Override
        public void onPause() {
            super.onPause();
            Log.d(TAG, "onPause");
            exoPlayerManager.onPause();
        }
    
    
        @Override
        protected void onDestroy() {
            exoPlayerManager.onDestroy();
            super.onDestroy();
    
        }
    
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            exoPlayerManager.onConfigurationChanged(newConfig);//橫豎屏切換
            super.onConfigurationChanged(newConfig);
        }
    
        @Override
        public void onBackPressed() {//使用播放返回鍵監(jiān)聽(tīng)
        
                   if (   exoPlayerManager.onBackPressed()){
                       finish();
                   }
        }

三.列表

1.列表播放,只能使用ManualPlayer,在你的VideoHolder

  • 1在列表控件使用屬性 ”app:controller_layout_id="@layout/simple_exo_playback_list_view"“ //提供默列表控制布局
  • 2.player_list="true" 設(shè)置為true 開(kāi)啟列表模式
  • 3.demo:
     public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoViewHolder> {
  
       private Context mContext;
      private List<String> mVideoList;
      public VideoAdapter(Context context, List<String> videoList) {
          mContext = context;
          mVideoList = videoList;
      }
  
      @Override
      public int getItemCount() {
          return mVideoList.size();
      }
      @Override
      public VideoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
          View itemView = LayoutInflater.from(mContext).inflate(R.layout.item_video1, parent, false);
          return new VideoViewHolder(itemView);
      }
  
      @Override
      public void onBindViewHolder(VideoViewHolder holder, int position) {
          String video = mVideoList.get(position);
          holder.bindData(video);
      }
  
      public class VideoViewHolder extends RecyclerView.ViewHolder {
          ManualPlayer userPlayer;
          VideoPlayerView playerView;
          public VideoViewHolder(View itemView) {
              super(itemView);
              //初始化控件
              playerView = (VideoPlayerView) itemView.findViewById(R.id.item_exo_player_view);
              userPlayer = new ManualPlayer((Activity) mContext, playerView);
          }
 
         /**
         *綁定數(shù)據(jù)源
         ***/
          public void bindData(String videoBean) {
              userPlayer.setTitle("" + getAdapterPosition());
              userPlayer.setPlayUri(videoBean);
              Glide.with(mContext)
              .load("http://i3.letvimg.com/lc08_yunzhuanma/201707/29/20/49/3280a525bef381311b374579f360e80a_v2_MTMxODYyNjMw/thumb/2_960_540.jpg")
              .into(playerView.getPreviewImage());
          }
      }

2.列表播放周期方法 列表在Activity或者Fragment 實(shí)現(xiàn)相應(yīng)周期方法

               protected void onPause() {
                   super.onPause();
                   VideoPlayerManager.getInstance().onPause();
               }
               @Override
                protected void onResume() {
                   super.onResume();
                   VideoPlayerManager.getInstance().onResume();
               }
               @Override
               protected void onDestroy() {
                   super.onDestroy();
                   VideoPlayerManager.getInstance().onDestroy();
               }
               @Override
               public void onBackPressed() {
                   //返回監(jiān)聽(tīng)類
                   if (VideoPlayerManager.getInstance().onBackPressed()){
                       finish();
                   }
               } 

四.數(shù)據(jù)源工廠類

1.默認(rèn)數(shù)據(jù)源

    緩存 : CacheDataSinkFactory,CacheDataSourceFactory
    http : DefaultDataSourceFactory,DefaultHttpDataSourceFactory
    Priority : PriorityDataSourceFactory      

2 自定義數(shù)據(jù)源引用

compile 'com.google.android.exoplayer:extension-okhttp:r2.5.1'
compile 'com.google.android.exoplayer:extension-rtmp:r2.5.1'

3.自定義數(shù)據(jù)源工廠類:

  • 實(shí)現(xiàn)接口 DataSourceListener 然后在getDataSourceFactory方法里 自定義 數(shù)據(jù)源
  • 在你使用播放控件時(shí)中實(shí)例化類
   exoPlayerManager = new GestureVideoPlayer(this,videoPlayerView,new DataSource(this));
   exoPlayerManager = new GestureVideoPlayer(this,(R.id.exo_play_context_id,new DataSource(this));
  • demo代碼:
public class DataSource implements DataSourceListener {
      public static final String TAG = "DataSource";
      private Context context;
       public   DataSource (Context context){
           this.context=context;
       }
      @Override
      public com.google.android.exoplayer2.upstream.DataSource.Factory getDataSourceFactory() {
           OkHttpClient  okHttpClient = new OkHttpClient();
           OkHttpDataSourceFactory OkHttpDataSourceFactory=    new OkHttpDataSourceFactory(okHttpClient, Util.getUserAgent(context, context.getApplicationContext().getPackageName()),new DefaultBandwidthMeter() );
              //使用OkHttpClient 數(shù)據(jù)源工廠
            //return  OkHttpDataSourceFactory; ;
            //默認(rèn)數(shù)據(jù)源工廠
            // return new JDefaultDataSourceFactory(context);
            // Rtmp數(shù)據(jù)源工廠 對(duì) Rtmp 協(xié)議支持
            // return  new RtmpDataSourceFactory();
           //緩存使用和組合使用
            LeastRecentlyUsedCacheEvictor evictor = new LeastRecentlyUsedCacheEvictor(1000000000);
           SimpleCache   simpleCache = new SimpleCache(new File(context.getCacheDir(), "media"), evictor);
           //緩存數(shù)據(jù)源使用链韭,內(nèi)部使用DefaultDataSourceFactory數(shù)據(jù)源工廠類
           // return  new CacheDataSinkFactory(simpleCache,10000);
           // 配合okHttp數(shù)據(jù)源工廠類
           return  new CacheDataSourceFactory(simpleCache, OkHttpDataSourceFactory);
           //使用配合默認(rèn)數(shù)據(jù)源紅工廠類
           // return  new CacheDataSourceFactory(simpleCache, new JDefaultDataSourceFactory(context));
           //使用提供緩存數(shù)據(jù)源工廠類
           // return new CacheDataSourceFactory(context,1000,1000);
          }

}

五.自定義控制布局

  • 1.使用自定義控制布局 app:controller_layout_id="@layout/simple_exo_playback_control_view" 詳細(xì)看 demo
app:controller_layout_id  指向您的布局名稱 
20170905164501.png
  • 2.注意自定義控制布局事項(xiàng) 不能改變控件類型偏竟,可以改變控件的樣式,位置敞峭,屬性等

項(xiàng)目地址-戳我

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末踊谋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子旋讹,更是在濱河造成了極大的恐慌殖蚕,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骗村,死亡現(xiàn)場(chǎng)離奇詭異嫌褪,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)胚股,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門笼痛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人琅拌,你說(shuō)我怎么就攤上這事缨伊。” “怎么了进宝?”我有些...
    開(kāi)封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵刻坊,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我党晋,道長(zhǎng)谭胚,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任未玻,我火速辦了婚禮灾而,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扳剿。我一直安慰自己旁趟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布庇绽。 她就那樣靜靜地躺著锡搜,像睡著了一般橙困。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上耕餐,一...
    開(kāi)封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天凡傅,我揣著相機(jī)與錄音,去河邊找鬼蛾方。 笑死像捶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的桩砰。 我是一名探鬼主播拓春,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼亚隅!你這毒婦竟也來(lái)了硼莽?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤煮纵,失蹤者是張志新(化名)和其女友劉穎懂鸵,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體行疏,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡匆光,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了酿联。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片终息。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖贞让,靈堂內(nèi)的尸體忽然破棺而出周崭,到底是詐尸還是另有隱情,我是刑警寧澤喳张,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布续镇,位于F島的核電站,受9級(jí)特大地震影響销部,放射性物質(zhì)發(fā)生泄漏摸航。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一舅桩、第九天 我趴在偏房一處隱蔽的房頂上張望忙厌。 院中可真熱鬧,春花似錦江咳、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)爹土。三九已至,卻和暖如春踩身,著一層夾襖步出監(jiān)牢的瞬間胀茵,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工挟阻, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留琼娘,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓附鸽,卻偏偏與公主長(zhǎng)得像脱拼,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子坷备,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理熄浓,服務(wù)發(fā)現(xiàn),斷路器省撑,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • 本人初學(xué)Android赌蔑,最近做了一個(gè)實(shí)現(xiàn)安卓簡(jiǎn)單音樂(lè)播放功能的播放器,收獲不少竟秫,于是便記錄下來(lái)自己的思路與知識(shí)總結(jié)...
    落日柳風(fēng)閱讀 19,080評(píng)論 2 41
  • ¥開(kāi)啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開(kāi)一個(gè)線程娃惯,因...
    小菜c閱讀 6,358評(píng)論 0 17
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法肥败,內(nèi)部類的語(yǔ)法趾浅,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法拙吉,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,581評(píng)論 18 399
  • 一潮孽、雞湯 appwidget是android中小組件,我們經(jīng)常說(shuō)的widget其實(shí)是指的那些button筷黔、text...
    歡樂(lè)斗佛閱讀 2,236評(píng)論 1 8