前言

Ijkplayer是B站开源的一款多媒体播放引擎,其基于ffmpeg开并支持很多的在线媒体播放格式。本文实现了在安卓TV上播放各大电视台的直播,其格式是.m3u8。当然了只要是编译的Ijkplayer支持的格式这款播放器自然可以播放。

首先上界面:

播放器界面非常简单,因为是用电视遥控器操作,所以布局和操作力求简单易用。布局分为播放区域和左侧菜单,按遥控器的确定按钮调出菜单,可以选择界面确认后进入播放界面。下面开始讲如何实现:

一,创建布局

播放器主界面布局文件activity_play_rel.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="vertical">  <LinearLayout  android:layout_width="fill_parent"  android:layout_height="fill_parent"  android:orientation="vertical">  <RelativeLayout  android:id="@+id/fl_videoview"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:background="@color/colorBlack">  <com.gxf.liveplay.ijkplayer.media.IjkVideoView  android:id="@+id/videoview"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:layout_centerInParent="true"  android:background="@color/colorBlack"></com.gxf.liveplay.ijkplayer.media.IjkVideoView>  <RelativeLayout  android:id="@+id/rl_loading"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:background="#de262a3b">  <TextView  android:id="@+id/tv_load_msg"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_below="@+id/pb_loading"  android:layout_centerInParent="true"  android:layout_marginTop="6dp"  android:textColor="#ffffff"  android:textSize="16sp" />  <ProgressBar  android:id="@+id/pb_loading"  android:layout_width="60dp"  android:layout_height="60dp"  android:layout_centerInParent="true"  android:layout_marginTop="60dp"  android:indeterminate="false"  android:indeterminateDrawable="@drawable/video_loading"  android:padding="5dp" />  </RelativeLayout>  <!-- <LinearLayout  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:background="@color/player_panel_background_color">  <TextView  android:id="@+id/tv_title"  android:layout_width="wrap_content"  android:layout_height="60dp"  android:textSize="24dp"  android:text=""  android:layout_centerVertical="true"  android:layout_marginTop="18dp"  android:textColor="@color/white"/>  <TextView  android:id="@+id/tv_time"  android:layout_width="wrap_content"  android:layout_height="60dp"  android:textSize="20dp"  android:layout_toRightOf="@id/tv_title"  android:layout_alignParentRight="true"  android:layout_centerVertical="true"  android:layout_marginLeft="60dp"  android:layout_marginTop="20dp"  android:textColor="@color/white"/>  </LinearLayout>-->  </RelativeLayout>  </LinearLayout>  <include layout="@layout/layout_menu" />
</RelativeLayout>
复制代码

整体分为两部分:上边为播放器实现的界面布局,下边为左侧菜单布局。这里没有采用滑动调出左侧菜单的效果,只是采用相对布局通过设定菜单的宽带直接覆盖在播放器布局之上。IjkVidoView下边的是播放器的控制器布局,可以扩展实现进度音量等控制,本文尚未实现。

接下来看左侧菜单布局文件layout_menu.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
复制代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="360dp"  android:layout_height="match_parent"  android:id="@+id/leftMenuCtrl"  android:layout_gravity="left"  android:visibility="gone"  android:background="@drawable/dark_no_shadow"  android:orientation="vertical">  <LinearLayout  android:layout_width="wrap_content"  android:layout_height="0dp"  android:layout_weight="1"  android:layout_gravity="center"  android:orientation="horizontal">  <ImageButton  android:id="@+id/turnLeft"  android:layout_width="30px"  android:layout_height="40px"  android:layout_gravity="center"  android:adjustViewBounds="false"  android:background="@drawable/tv_switch_bg_left"  android:onClick="turnLeft" />  <TextView  android:id="@+id/tvGroupTitle"  android:layout_width="300px"  android:layout_height="100px"  android:layout_gravity="center"  android:gravity="center"  android:text="我的频道"  android:textColor="@color/white"  android:textSize="24sp"  android:textStyle="bold"  />  <ImageButton  android:id="@+id/turnRight"  android:layout_width="30px"  android:layout_height="40px"  android:layout_gravity="center"  android:adjustViewBounds="false"  android:background="@drawable/tv_switch_bg_right"  android:onClick="turnRight" />  </LinearLayout>  <ListView  android:id="@+id/listView"  android:layout_width="match_parent"  android:layout_height="0dp"  android:layout_weight="9"  android:layout_gravity="center"  android:listSelector="@color/colorPrimaryDark"/>
</LinearLayout>
复制代码

上边的LinearLayout用于切换节目组,下边是ListView显示每个分组下的节目列表。这次布局就实现了,这是相当简单的。

二,实现播放

LiveActivityRel实现了播放功能,启动该Activity的时候传入媒体资源的地址mVideoUrl,然后启动Ijkplayer的播放功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
复制代码
public void initVideo() {  // init player`  IjkMediaPlayer.loadLibrariesOnce(null);  IjkMediaPlayer.native_profileBegin("libijkplayer.so");  mVideoView.setVideoURI(Uri.parse(mVideoUrl));  mVideoView.setOnPreparedListener(new IMediaPlayer.OnPreparedListener() {  @Override  public void onPrepared(IMediaPlayer mp) {  mp.setVolume(100, 100);  mVideoView.start();  }  });  mVideoView.setOnInfoListener(new IMediaPlayer.OnInfoListener() {  @Override  public boolean onInfo(IMediaPlayer mp, int what, int extra) {  switch (what) {  case IjkMediaPlayer.MEDIA_INFO_BUFFERING_START:  mLoadingLayout.setVisibility(View.VISIBLE);  break;  case IjkMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START:  case IjkMediaPlayer.MEDIA_INFO_BUFFERING_END:  mLoadingLayout.setVisibility(View.GONE);  break;  }  return false;  }  });  mVideoView.setOnCompletionListener(new IMediaPlayer.OnCompletionListener() {  @Override  public void onCompletion(IMediaPlayer mp) {  mLoadingLayout.setVisibility(View.VISIBLE);  mVideoView.stopPlayback();  mVideoView.release(true);  mVideoView.setVideoURI(Uri.parse(mVideoUrl));  }  });  mVideoView.setOnErrorListener(new IMediaPlayer.OnErrorListener() {  @Override  public boolean onError(IMediaPlayer mp, int what, int extra) {  if (++mRetryTimes > CONNECTION_TIMES) {  new AlertDialog.Builder(LiveActivityRel.this)  .setMessage("该频道媒体资源出现错误,节目暂时不能播放...")  .setPositiveButton(R.string.VideoView_error_button,  new DialogInterface.OnClickListener() {  public void onClick(DialogInterface dialog, int whichButton) {  dialog.dismiss();  //LiveActivityRel.this.finish();  }  })  .setCancelable(false)  .show();  } else {  mVideoView.stopPlayback();  mVideoView.release(true);  mVideoView.setVideoURI(Uri.parse(mVideoUrl));  }  return false;  }  });  }
复制代码

这里也是很简答的,首先进行库的加载和初始化,绑定各种事件,然后在setOnPreparedListener中启动播放。其余的功能主要是涉及到UI和数据解析。节目列表是一个JSON结构,在原来的项目是有API进行登录和节目列表获取的。为了方便本文直接把节目列表写死,同时启动的Activity设置为MainActivityOffline。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
复制代码
package com.gxf.liveplay;  import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Toast;  /** * splash * 启动登录检测 */
public class MainActivityOffline extends Activity {  private final int SPLASH_DISPLAY_LENGHT = 1000; // 两秒后进入系统  private boolean isUpdateChecked = false;  public void checkLogin(){  SharedPreferences userSettings = getSharedPreferences("auth", Context.MODE_PRIVATE);  final String lastVedioUrl = userSettings.getString("lastVedioUrl", "none");  final Toast toast = Toast.makeText(MainActivityOffline.this, "系统初始化失败...", Toast.LENGTH_SHORT);  // 开启一个子线程,进行网络操作,等待有返回结果,使用handler通知UI  new Thread(new Runnable() {  @Override  public void run() {  try {  PlayListCache.initPlayInfo(null,null);  String url = lastVedioUrl;  if (url.equals("none"))  url = PlayListCache.playListMap.get(PlayListCache.playListMap.keySet().iterator().next());  LiveActivityRel.activityStart(MainActivityOffline.this, url);  MainActivityOffline.this.finish();  } catch (Exception e) {  toast.show();  e.printStackTrace();  }  }  }).start();  }  @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  checkLogin();  }
}
复制代码

启动App在一个线程里去获取节目列表并缓存起来放在PlayListCache中,然后调用LiveActivityRel并传入一个默认的播放地址(首次启动)或者上次播放的地址。至于登录和HttpUtils中的代码(主要用于节目列表和登录控制)就不在赘述了,因为不属于本文的重点。

三,项目的代码

github.com/gongxufan/T…

THE END

PS:本项目中的播放源地址可能会失效,如需测试需要更改可用的播放源。

具体代码在com.gxf.liveplay.HttpUtils#getOfflinePlayList,数据格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
复制代码
[  {  "group": "省内频道",  "list": [  {  "湖南都市": "http://220.248.175.231:6610/001/2/ch00000090990000001049/index.m3u8?virtualDomain=001.live_hls.zte.com"  },  {  "湖南经视": "http://220.248.175.230:6610/001/2/ch00000090990000001052/index.m3u8?virtualDomain=001.live_hls.zte.com"  }  ]  },  {  "group": "其他频道",  "list": [  {  "安徽卫视": "http://220.248.175.230:6610/001/2/ch00000090990000001024/index.m3u8?virtualDomain=001.live_hls.zte.com"  },  {  "北京卫视": "http://220.248.175.230:6610/001/2/ch00000090990000001025/index.m3u8?virtualDomain=001.live_hls.zte.com"  }  ]  },  {  "group": "高清频道",  "list": [  {  "CCTV1综合HD": "http://220.248.175.230:6610/001/2/ch00000090990000001075/index.m3u8?virtualDomain=001.live_hls.zte.com"  },  {  "湖南经视HD": "http://220.248.175.230:6610/001/2/ch00000090990000001080/index.m3u8?virtualDomain=001.live_hls.zte.com"  }  ]  },  {  "group": "央视频道",  "list": [  {  "CCTV1综合": "http://220.248.175.230:6610/001/2/ch00000090990000001075/index.m3u8?virtualDomain=001.live_hls.zte.com"  },  {  "CCTV证券": "http://220.248.175.230:6610/001/2/ch00000090990000001133/index.m3u8?virtualDomain=001.live_hls.zte.com"  }  ]  }
]
复制代码

【基于Ijkplayer】安卓机顶盒电视播放器开发相关推荐

  1. android 基于ijkplayer项目进行的播放器

    jjdxm_ijkplayer 项目地址:jjdxm_ijkplayer 简介:基于 ijkplayer 简单的 UI 界面 当前项目是基于 ijkplayer 项目进行的播放器界面 UI 封装. 是 ...

  2. 【基于Python+tkinter的音乐播放器开发-哔哩哔哩】 https://b23.tv/eG2TwOL

    [基于Python+tkinter的音乐播放器开发-哔哩哔哩] https://b23.tv/eG2TwOL https://b23.tv/eG2TwOL

  3. 基于android系统的音乐播放器,基于Android系统的音乐播放器软件设计与实现.doc

    基于Android平台的音乐播放器 The Development of Mobile Music Player Based on Android platform system 学生学号: 学生姓名 ...

  4. 智能android电视更换播放器,GitHub - qfwc258/TvPlayer: android智能电视播放器,可以播放各电视台节目,播放基于ijkplayer的实现。...

    TvPlayer 1,android智能电视播放器,可以播放各电视台节目,播放基于ijkplayer的实现 2,测试的源地址可能失效,如需测试可以自己更换播放源.HttpUtils.getOfflin ...

  5. 智能android电视更换播放器,GitHub - kaigeLove/TvPlayer: android智能电视播放器,可以播放各电视台节目,播放基于ijkplayer的实现。...

    TvPlayer 1,android智能电视播放器,可以播放各电视台节目,播放基于ijkplayer的实现 2,测试的源地址可能失效,如需测试可以自己更换播放源.HttpUtils.getOfflin ...

  6. 智能android电视更换播放器,GitHub - xioxu/TvPlayer: android智能电视播放器,可以播放各电视台节目,播放基于ijkplayer的实现。...

    TvPlayer 1,android智能电视播放器,可以播放各电视台节目,播放基于ijkplayer的实现 2,测试的源地址可能失效,如需测试可以自己更换播放源.HttpUtils.getOfflin ...

  7. 异地过年,我要用它看春晚!- Qt趣味开发之基于QtAV的电视播放器

    今年过年因为疫情的关系,在工作地点过年.家里穷的连个电视都没有,春晚都看不了,怎么办??!! QtAV是一个开源的音视频播放器,支持播放本地文件和网络流媒体.并集成了多种视频渲染方式,使用它的简单的A ...

  8. 张利国,龚海平,王植萌.android移动开发入门与进阶,开题报告-基于Android的手机音乐播放器的设计与实现.doc...

    盐城师范学院 毕业设计开题报告 题 目: 基于android的手机音乐播放器 的设计与实现 姓 名: 二级学院: 信息工程学院 专 业: 软件工程 班 级: 12(1) 学 号: 指导教师: 职称: ...

  9. 基于VLC的播放器开发

    VLC的C++封装 因为工作需要,研究了一段时间的播放器开发,如果从头开始做,可以学习下FFmpeg(http://www.ffmpeg.org/),很多播放器都是基于FFmpeg开发的,但是这样工作 ...

最新文章

  1. .NET判断字符串是否是数值型或xxx型
  2. 网页中PNG透明背景图片的完美应用
  3. HDU 4614 Vases and Flowers 【线段树】+【二分】
  4. Python编程基础:第五十五节 map函数Map
  5. Hadoop的学习前奏(二)——Hadoop集群的配置
  6. Ruby实例方法和类方法的简写
  7. layui怎样将响应数据展示在页面_layui怎么对弹出层显示数据
  8. 【深度学习理论】一文搞透pytorch中的tensor、autograd、反向传播和计算图
  9. 技术项目 - MySQL多从系统的主库选择
  10. html5用户注册页面代码,HTML5注册页面示例代码_html5教程技巧
  11. 安丘妇幼保健院智能照明监控系统的设计与应用-安科瑞耿敏花
  12. select2 使用详解
  13. 应用统计学与计算机论文,浅谈统计学在生活中的应用
  14. java excel 导入试题
  15. python项目实战:天眼查询你所需的公司信息
  16. Git分支图解理解其概念HEAD,git branch name,git checkout name,git log --oneline --decorate
  17. 中年危机也许只是个幻觉
  18. windows11应用商店错误:0x800704cf
  19. 全键盘 linux 手机,当年青葱的岁月:10佳全键盘智能手机盘点
  20. 米思齐Mixly图形化编程---遥控灯

热门文章

  1. Sketch for mac(矢量绘图UI设计)
  2. 工业计算机刷游戏,我的世界电脑版工业2教程 带你深入了解游戏
  3. 部署城市级室外无线局域网的成功战略
  4. 国内外几大浏览器性能比较
  5. 数据中心现场施工管理难点案例分析
  6. 滑雪游戏中,有俩种障碍物,合并障碍物的作用是什么
  7. 10月31日到12月04日学习总结
  8. python淘宝秒杀_Python 实现淘宝秒杀的示例代码
  9. 机械专业应具备什么计算机能力
  10. 中兴交换机stp mstp 配置实例 原理