Android TV直播电视节目

更多技术博客,项目,欢迎关注公众号:

Android TV开发交流群:135622564

传统电视直播节目,在Android TV上起着越来越重要的作用,央视,各地卫视,满足观众日益增长的多元化需求

看下效果图:

代码实现思路:

1、通过RecycleView为对应的节目item,遥控器按键,可触发跳到对应的直播节目

2、用对IjkPlayer进行二次封装,并能用于播放视频源。

3、视频源m3u8,可能存在失效,目前获取了一个比较稳定的视频源

代码实现:

主页面:Recycleview对应adapater

直播节目源

播放器

播放页处理

主页面:

/*

* Copyright (C) 2016 hejunlin

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

public class MainActivity extends Activity {

private MetroViewBorderImpl mMetroViewBorderImpl;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mMetroViewBorderImpl = new MetroViewBorderImpl(this);

mMetroViewBorderImpl.setBackgroundResource(R.drawable.border_color);

loadRecyclerViewMenuItem();

}

private void loadRecyclerViewMenuItem() {

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.ry_menu_item);

GridLayoutManager layoutManager = new GridLayoutManager(this, 1);

layoutManager.setOrientation(LinearLayoutManager.VERTICAL);

recyclerView.setLayoutManager(layoutManager);

recyclerView.setFocusable(false);

mMetroViewBorderImpl.attachTo(recyclerView);

createOptionItemData(recyclerView, R.layout.detail_menu_item);

}

private void createOptionItemData(RecyclerView recyclerView, int id) {

OptionItemAdapter adapter = new OptionItemAdapter(this, id);

recyclerView.setAdapter(adapter);

recyclerView.scrollToPosition(0);

}

}

播放页:

/*

* Copyright (C) 2016 hejunlin

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

public class LiveActivity extends Activity {

private IjkVideoView mVideoView;

private RelativeLayout mVideoViewLayout;

private RelativeLayout mLoadingLayout;

private TextView mLoadingText;

private TextView mTextClock;

private String mVideoUrl = "";

private int mRetryTimes = 0;

private static final int CONNECTION_TIMES = 5;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_live);

mVideoUrl = getIntent().getStringExtra("url");

mVideoView = (IjkVideoView) findViewById(R.id.videoview);

mVideoViewLayout = (RelativeLayout) findViewById(R.id.fl_videoview);

mLoadingLayout = (RelativeLayout) findViewById(R.id.rl_loading);

mLoadingText = (TextView) findViewById(R.id.tv_load_msg);

mTextClock = (TextView)findViewById(R.id.tv_time);

mTextClock.setText(getDateFormate());

mLoadingText.setText("节目加载中...");

initVideo();

}

private String getDateFormate(){

Calendar c = Calendar.getInstance();

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String formattedDate = df.format(c.getTime());

return formattedDate;

}

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) {

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(LiveActivity.this)

.setMessage("节目暂时不能播放")

.setPositiveButton(R.string.VideoView_error_button,

new DialogInterface.OnClickListener() {

public void onClick(DialogInterface dialog, int whichButton) {

LiveActivity.this.finish();

}

})

.setCancelable(false)

.show();

} else {

mVideoView.stopPlayback();

mVideoView.release(true);

mVideoView.setVideoURI(Uri.parse(mVideoUrl));

}

return false;

}

});

}

@Override

protected void onResume() {

super.onResume();

}

@Override

protected void onPause() {

super.onPause();

}

@Override

protected void onStop() {

super.onStop();

if (!mVideoView.isBackgroundPlayEnabled()) {

mVideoView.stopPlayback();

mVideoView.release(true);

mVideoView.stopBackgroundPlay();

}

IjkMediaPlayer.native_profileEnd();

}

public static void activityStart(Context context, String url) {

Intent intent = new Intent(context, LiveActivity.class);

intent.putExtra("url", url);

context.startActivity(intent);

}

@Override

public void onConfigurationChanged(Configuration newConfig) {

super.onConfigurationChanged(newConfig);

}

}

播放器是用二次封装的ijkplayer,从主页面传url到播放页面,关才mediaplayer相关,之前专门写了专题分析,mediaplayer的状态可参考《Android Multimedia框架总结(一)MediaPlayer介绍之状态图及生命周期》

第三方播放器典型特点就是另起一个mediaplayerservice,注意这是另外一个进程,为什么是另一个进程,可参见我的文章:MediaPlayer的C/S模型。对于ijkplayer这个框架,因为做实例,才引入,不做评价,也不会去深究,满足基本播放需求就ok。市场上有很多第三方播放框架,ijkplayer,vitamio,百度云播放等。

再看下播放页的播放panel:

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#22000000"

android:orientation="vertical">

android:id="@+id/fl_videoview"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@color/colorBlack">

android:id="@+id/videoview"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:layout_centerInParent="true"

android:background="@color/colorBlack">

android:id="@+id/rl_loading"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="#de262a3b">

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" />

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" />

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="@color/player_panel_background_color">

android:id="@+id/tv_title"

android:layout_width="wrap_content"

android:layout_height="60dp"

android:textSize="24dp"

android:text="Android TV开发总结(六)构建一个TV app的直播节目实例"

android:layout_centerVertical="true"

android:layout_marginTop="18dp"

android:textColor="@color/white"/>

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"/>

这里有几个点要注意 :

为演示,并未对层级进行使用FrameLayout,及viewstub,include等性能优化相关的,在实际商用项目中,建议写xml文件,尽可能遵循过少的层级,高级标签及FrameLayout等技巧。

所有的size切勿直接写死,用 android:layout_marginTop="@dimen/dimen_20dp"表示,string值统一写到string.xml中,这些基本的规范,会让你提高不少效率。

欢迎关注我的个人公众号,android 技术干货,问题深度总结,FrameWork源码解析,插件化研究,最新开源项目推荐

License

Copyright (C) 2016 hejunlin

Licensed under the Apache License, Version 2.0 (the "License");

you may not use this file except in compliance with the License.

You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software

distributed under the License is distributed on an "AS IS" BASIS,

WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and

limitations under the License.

android live 电视 源码,GitHub - mxiaoguang/LivePlayback: Android TV直播电视节目 ,包含各央视频道及卫视频道...相关推荐

  1. android瀑布流布局源码,GitHub - dodola/android_waterfall: Android版的瀑布流布局

    Android瀑布流实例 此项目由于最初设计问题,导致现在问题比较多,暂时停止维护. 我现在在其他类似的瀑布流上进行完善开发, ####请关注: 有必要解释一下程序为什么采用addview方式而不是做 ...

  2. android 2.3源码 百度网盘,Android 2.3.5源代码 更新至android 4.4,可以下载,度娘网盘...

    重新打包到度娘的disk了,不用看到115的广告了!!!由于115的问题,最近上班忙,各种事情,源码我会尽量上传:百度网盘,最下面的是MSM高通内核源码.后面会陆 Android 4.4源码下载(li ...

  3. Android小项目源码汇总

     Android小应用源码之贪吃蛇 Android小应用源码之CamMonitor Android小应用源码之SpeakMessageService Android小应用源码之mediaplayer ...

  4. github Android优秀项目源码

    BeautifulRefreshLayout-漂亮的美食下拉刷新https://github.com/android-cjj/BeautifulRefreshLayout/tree/Beautiful ...

  5. GitHub上最火的22个Android开源项目源码(最少的一个也超过10k star)

    GitHub上最火的22个Android开源项目源码均超万星 chat图表 最全android工具类库 29.6k start Android智能下拉刷新框架-SmartRefreshLayout 2 ...

  6. android 浏览器源码分析,从源码出发深入理解 Android Service

    原标题:从源码出发深入理解 Android Service 原文链接: 建议在浏览器上打开,删除了大量代码细节,:) 本文是 Android 系统学习系列文章中的第三章节的内容,介绍了 Android ...

  7. Android 7.0 源码分析项目一期竣工啦

    从 Android 入行开始,因为工作需求和解决疑难bug的原因陆陆续续的看过一些源码,但都不成系统,从2016年年底开始,在Github上建了一个Android Open Source Projec ...

  8. Android开源框架源码鉴赏:VirtualAPK

    文章目录 一 VirtualAPK的初始化流程 二 VirtualAPK的的加载流程 三 VirtualAPK启动组件的流程 3.1 Activity 3.2 Service 3.3 Broadcas ...

  9. Android Gradle Plugin 源码阅读与编译

    前言 为了解一些Andorid的构建流程,有时候需要阅读Android Gradle Plugin的相关源码的.自己阅读Android Gradle Plugin源码主要经历了三个时期: 1.AOSP ...

最新文章

  1. CentOS firewall添加开放端口
  2. 顺序表应用4:元素位置互换之逆置算法
  3. 七十、SpringBoot整合 Druid数据源
  4. BZOJ3572 [Hnoi2014]世界树 【虚树 + 树形dp】
  5. 蜜蜂路线(洛谷P2437题题解,Java语言描述)
  6. LINUX也有C#?
  7. 如何从硬盘安装Linux
  8. 不使用imrotate 的图像旋转实现
  9. OpenG绘图方式比较
  10. HDU 6070 Dirt Ratio
  11. 赵小楼《天道》《遥远的救世主》解读(84)救主文化是什么?
  12. php写aaa-zzz,php算法打印aa aaa ab aab直到zzz
  13. 详解Guitar Pro 7小节的组织定义
  14. python判断线程是否执行完成_判断Threading.start新线程是否执行完毕的实例
  15. spring-scop (单例模式?)
  16. 送你一套免费英语资料(价值1899)
  17. jsp做的留言系统(防止非法登录、增删改查留言)
  18. vim插入模式小技巧
  19. 普林斯顿计算机科学怎么样,普林斯顿大学计算机科学世界排名2019年最新排名第8(THE世界排名)...
  20. 优思学院|3M的传奇故事和六西格玛管理

热门文章

  1. 通用嵌入式系统测试平台 ETest简介
  2. 地方政府不愿房价下跌 救市或化解房地产调控
  3. 人机交互是为了解决计算机的,人机交互与交互设计有什么区别
  4. UST 与美元脱钩,LUNA 暴跌 99.9%
  5. Long Way To Go 之 Python 2
  6. l1300打印机纸进不去_爱普生打印机不进纸该怎么解决?
  7. c语言程序中复合句用什么表示,c语言程序设计(包云)c第1章概述
  8. 武汉理工计算机与名校的差距
  9. 浙大与北大计算机考研分数线,2017浙大考研复试分数线及相关问题
  10. android phone电脑驱动下载,全机型Android Phone驱动及安装教程(XP,Vista,Win7).pdf