android直播之流媒体开发(转载)

1、流媒体开发之--直播实现

2、流媒体开发之-直播自定义列表

3、流媒体开发之-服务器图片的加载

4、流媒体开发之-直播自定义分类

5、流媒体开发之-获取直播节目预告-1

6、流媒体开发之-直播界面切换电视台频道

关于直播的相关信息这里不做详解,我们对直播应该很熟悉,实现生活中有各种直播,他们
如何实现的呢,其实开发一个简单不能简单的直播,只需要两个:1、直播地址
2、播放器,对于直播地址我们可以利用很多软件获取连接,播放器,现在开源的也有很多,最常见的就是ffmpeg,但是如果直接用ffmpeg开发工作量
比较大,我们可以使用第三方的播放器库,例如vlc,vitamio等等,这里我使用的时vitamio库。

首先建立一个项目,命名为Live,项目建立好了以后我们需要配置vitamio需要的环境,网上有很多,这里就不写出了,添加了依赖库后添加一个主界面,这里我只添加了一个EditView和Button,配置如下:

[html] view plaincopy

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

  2. xmlns:tools="http://schemas.android.com/tools"

  3. android:layout_width="match_parent"

  4. android:layout_height="match_parent"

  5. android:paddingBottom="@dimen/activity_vertical_margin"

  6. android:paddingLeft="@dimen/activity_horizontal_margin"

  7. android:paddingRight="@dimen/activity_horizontal_margin"

  8. android:paddingTop="@dimen/activity_vertical_margin"

  9. tools:context=".Live" >
  10. <EditText

  11. android:id="@+id/live_url"

  12. android:layout_width="match_parent"

  13. android:layout_height="100dp" />
  14. <Button

  15. android:id="@+id/play"

  16. android:layout_width="120dp"

  17. android:layout_height="60dp"

  18. android:layout_below="@id/live_url"

  19. android:layout_centerHorizontal="true"

  20. android:layout_marginTop="100dp"

  21. android:text="Play" >

  22. </Button>
  23. </RelativeLayout>

主界面的类:

[java] view plaincopy

  1. package com.jwzhangjie.live;
  2. import android.os.Bundle;

  3. import android.app.Activity;

  4. import android.content.Intent;

  5. import android.view.Menu;

  6. import android.view.View;

  7. import android.view.View.OnClickListener;

  8. import android.widget.Button;

  9. import android.widget.EditText;
  10. public class Live extends Activity {
  11. public static final String  DEFAULTPATH = "http://ipadlive.cntv.soooner.com/cctv_p2p_hdcctv6.m3u8";

  12. EditText Live_Url;

  13. Button PlayBtn;

  14. @Override

  15. protected void onCreate(Bundle savedInstanceState) {

  16. super.onCreate(savedInstanceState);

  17. setContentView(R.layout.activity_live);

  18. Live_Url = (EditText)findViewById(R.id.live_url);

  19. Live_Url.setText(DEFAULTPATH);

  20. PlayBtn = (Button)findViewById(R.id.play);

  21. PlayBtn.setOnClickListener(new OnClickListener() {

  22. @Override

  23. public void onClick(View v) {

  24. Intent intent = new Intent();

  25. intent.setClass(Live.this, JieVideoPlayer.class);

  26. String path = Live_Url.getText().toString();

  27. if (path == null) {

  28. path = DEFAULTPATH;

  29. }

  30. intent.putExtra("path", path);

  31. startActivity(intent);

  32. }

  33. });

  34. }
  35. @Override

  36. public boolean onCreateOptionsMenu(Menu menu) {

  37. getMenuInflater().inflate(R.menu.live, menu);

  38. return true;

  39. }
  40. }

播放界面的类:

[java] view plaincopy

  1. package com.jwzhangjie.live;
  2. import io.vov.vitamio.LibsChecker;

  3. import io.vov.vitamio.MediaPlayer;

  4. import io.vov.vitamio.MediaPlayer.OnCompletionListener;

  5. import io.vov.vitamio.MediaPlayer.OnInfoListener;

  6. import io.vov.vitamio.widget.MediaController;

  7. import io.vov.vitamio.widget.VideoView;

  8. import android.annotation.SuppressLint;

  9. import android.app.Activity;

  10. import android.content.Context;

  11. import android.content.pm.ActivityInfo;

  12. import android.content.res.Configuration;

  13. import android.media.AudioManager;

  14. import android.net.Uri;

  15. import android.os.Bundle;

  16. import android.os.Handler;

  17. import android.os.Message;

  18. import android.util.Log;

  19. import android.view.Display;

  20. import android.view.GestureDetector.SimpleOnGestureListener;

  21. import android.view.GestureDetector;

  22. import android.view.MotionEvent;

  23. import android.view.View;

  24. import android.view.ViewGroup;

  25. import android.view.WindowManager;

  26. import android.widget.ImageView;
  27. @SuppressLint("HandlerLeak")

  28. public class JieVideoPlayer extends Activity implements OnCompletionListener, OnInfoListener {
  29. private String mPath;

  30. private String mTitle;

  31. private VideoView mVideoView;

  32. private View mVolumeBrightnessLayout;

  33. private ImageView mOperationBg;

  34. private ImageView mOperationPercent;

  35. private AudioManager mAudioManager;

  36. /** 声音 */

  37. private int mMaxVolume;

  38. /** 当前声音 */

  39. private int mVolume = -1;

  40. /** 当前亮度 */

  41. private float mBrightness = -1f;

  42. /** 当前缩放模式 */

  43. private int mLayout = VideoView.VIDEO_LAYOUT_ZOOM;

  44. private GestureDetector mGestureDetector;

  45. private MediaController mMediaController;

  46. private View mLoadingView;

  47. @Override

  48. public void onCreate(Bundle savedInstanceState) {

  49. super.onCreate(savedInstanceState);
  50. if (!LibsChecker.checkVitamioLibs(this))

  51. return;
  52. // ~~~ 获取播放地址和标

  53. // ~~~ 绑定控件

  54. setContentView(R.layout.videoview);

  55. mPath = getIntent().getStringExtra("path");

  56. mVideoView = (VideoView) findViewById(R.id.surface_view);

  57. mVolumeBrightnessLayout = findViewById(R.id.operation_volume_brightness);

  58. mOperationBg = (ImageView) findViewById(R.id.operation_bg);

  59. mOperationPercent = (ImageView) findViewById(R.id.operation_percent);

  60. mLoadingView = findViewById(R.id.video_loading);

  61. // ~~~ 绑定事件

  62. mVideoView.setOnCompletionListener(this);

  63. mVideoView.setOnInfoListener(this);
  64. // ~~~ 绑定数据

  65. mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

  66. mMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
  67. if (mPath.startsWith("http:")){

  68. mVideoView.setVideoURI(Uri.parse(mPath));

  69. }

  70. else{

  71. mVideoView.setVideoPath(mPath);

  72. }

  73. //设置显示名称

  74. mMediaController = new MediaController(this);

  75. mMediaController.setFileName(mTitle);

  76. mVideoView.setMediaController(mMediaController);

  77. mVideoView.requestFocus();
  78. mGestureDetector = new GestureDetector(this, new MyGestureListener());

  79. setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

  80. }
  81. @Override

  82. protected void onPause() {

  83. super.onPause();

  84. if (mVideoView != null)

  85. mVideoView.pause();

  86. }
  87. @Override

  88. protected void onResume() {

  89. super.onResume();

  90. if (mVideoView != null)

  91. mVideoView.resume();

  92. }
  93. @Override

  94. protected void onDestroy() {

  95. super.onDestroy();

  96. if (mVideoView != null)

  97. mVideoView.stopPlayback();

  98. }
  99. @Override

  100. public boolean onTouchEvent(MotionEvent event) {

  101. if (mGestureDetector.onTouchEvent(event))

  102. return true;
  103. // 处理手势结束

  104. switch (event.getAction() & MotionEvent.ACTION_MASK) {

  105. case MotionEvent.ACTION_UP:

  106. endGesture();

  107. break;

  108. }
  109. return super.onTouchEvent(event);

  110. }
  111. /** 手势结束 */

  112. private void endGesture() {

  113. mVolume = -1;

  114. mBrightness = -1f;
  115. // 隐藏

  116. mDismissHandler.removeMessages(0);

  117. mDismissHandler.sendEmptyMessageDelayed(0, 500);

  118. }
  119. private class MyGestureListener extends SimpleOnGestureListener {
  120. /** 双击 */

  121. @Override

  122. public boolean onDoubleTap(MotionEvent e) {

  123. if (mLayout == VideoView.VIDEO_LAYOUT_ZOOM)

  124. mLayout = VideoView.VIDEO_LAYOUT_ORIGIN;

  125. else

  126. mLayout++;

  127. if (mVideoView != null)

  128. mVideoView.setVideoLayout(mLayout, 0);

  129. return true;

  130. }
  131. /** 滑动 */

  132. @SuppressWarnings("deprecation")

  133. @Override

  134. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {

  135. float mOldX = e1.getX(), mOldY = e1.getY();

  136. int y = (int) e2.getRawY();

  137. Display disp = getWindowManager().getDefaultDisplay();

  138. int windowWidth = disp.getWidth();

  139. int windowHeight = disp.getHeight();
  140. if (mOldX > windowWidth * 4.0 / 5)// 右边滑动

  141. onVolumeSlide((mOldY - y) / windowHeight);

  142. else if (mOldX < windowWidth / 5.0)// 左边滑动

  143. onBrightnessSlide((mOldY - y) / windowHeight);
  144. return super.onScroll(e1, e2, distanceX, distanceY);

  145. }

  146. }
  147. /** 定时隐藏 */

  148. private Handler mDismissHandler = new Handler() {

  149. @Override

  150. public void handleMessage(Message msg) {

  151. mVolumeBrightnessLayout.setVisibility(View.GONE);

  152. }

  153. };
  154. /**

  155. * 滑动改变声音大小

  156. *

  157. * @param percent

  158. */

  159. private void onVolumeSlide(float percent) {

  160. if (mVolume == -1) {

  161. mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);

  162. if (mVolume < 0)

  163. mVolume = 0;
  164. // 显示

  165. mOperationBg.setImageResource(R.drawable.video_volumn_bg);

  166. mVolumeBrightnessLayout.setVisibility(View.VISIBLE);

  167. }
  168. int index = (int) (percent * mMaxVolume) + mVolume;

  169. if (index > mMaxVolume)

  170. index = mMaxVolume;

  171. else if (index < 0)

  172. index = 0;
  173. // 变更声音

  174. mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);
  175. // 变更进度??

  176. ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams();

  177. lp.width = findViewById(R.id.operation_full).getLayoutParams().width * index / mMaxVolume;

  178. mOperationPercent.setLayoutParams(lp);

  179. }
  180. /**

  181. * 滑动改变亮度

  182. *

  183. * @param percent

  184. */

  185. private void onBrightnessSlide(float percent) {

  186. if (mBrightness < 0) {

  187. mBrightness = getWindow().getAttributes().screenBrightness;

  188. if (mBrightness <= 0.00f)

  189. mBrightness = 0.50f;

  190. if (mBrightness < 0.01f)

  191. mBrightness = 0.01f;
  192. // 显示

  193. mOperationBg.setImageResource(R.drawable.video_brightness_bg);

  194. mVolumeBrightnessLayout.setVisibility(View.VISIBLE);

  195. }

  196. WindowManager.LayoutParams lpa = getWindow().getAttributes();

  197. lpa.screenBrightness = mBrightness + percent;

  198. if (lpa.screenBrightness > 1.0f)

  199. lpa.screenBrightness = 1.0f;

  200. else if (lpa.screenBrightness < 0.01f)

  201. lpa.screenBrightness = 0.01f;

  202. getWindow().setAttributes(lpa);
  203. ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams();

  204. lp.width = (int) (findViewById(R.id.operation_full).getLayoutParams().width * lpa.screenBrightness);

  205. mOperationPercent.setLayoutParams(lp);

  206. }
  207. @Override

  208. public void onConfigurationChanged(Configuration newConfig) {

  209. if (mVideoView != null)

  210. mVideoView.setVideoLayout(mLayout, 0);

  211. super.onConfigurationChanged(newConfig);

  212. }
  213. @Override

  214. public void onCompletion(MediaPlayer player) {

  215. Log.e("tet", "播放完成");

  216. }
  217. private void stopPlayer() {

  218. if (mVideoView != null)

  219. mVideoView.pause();

  220. }
  221. private void startPlayer() {

  222. if (mVideoView != null)

  223. mVideoView.start();

  224. }
  225. private boolean isPlaying() {

  226. return mVideoView != null && mVideoView.isPlaying();

  227. }
  228. /** 是否????自动恢复播放,用于自动暂停,恢复播放 */

  229. private boolean needResume;
  230. @Override

  231. public boolean onInfo(MediaPlayer arg0, int arg1, int down_rate) {

  232. switch (arg1) {

  233. case MediaPlayer.MEDIA_INFO_BUFFERING_START:

  234. //????缓存,暂停播??

  235. if (isPlaying()) {

  236. stopPlayer();

  237. needResume = true;

  238. }

  239. mLoadingView.setVisibility(View.VISIBLE);

  240. break;

  241. case MediaPlayer.MEDIA_INFO_BUFFERING_END:

  242. //缓存完成,继续播??

  243. if (needResume)

  244. startPlayer();

  245. mLoadingView.setVisibility(View.GONE);

  246. break;

  247. case MediaPlayer.MEDIA_INFO_DOWNLOAD_RATE_CHANGED:

  248. //显示 下载速度

  249. Log.e("test","download rate:" + down_rate);

  250. //          mLoadingPerce.setText("正在缓冲??.."+"缓冲完成??+down_rate);

  251. //mListener.onDownloadRateChanged(arg2);

  252. break;

  253. }

  254. return true;

  255. }

  256. }

播放界面的配置:

[html] view plaincopy

  1. <?xml version="1.0" encoding="utf-8"?>

  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

  3. android:layout_width="fill_parent"

  4. android:layout_height="fill_parent"

  5. android:orientation="vertical" >
  6. <io.vov.vitamio.widget.VideoView

  7. android:id="@+id/surface_view"

  8. android:layout_width="fill_parent"

  9. android:layout_height="fill_parent"

  10. android:layout_centerHorizontal="true"

  11. android:layout_centerVertical="true" />
  12. <LinearLayout

  13. android:id="@+id/video_loading"

  14. android:layout_width="wrap_content"

  15. android:layout_height="wrap_content"

  16. android:layout_centerInParent="true"

  17. android:gravity="center_vertical" >
  18. <ProgressBar

  19. android:layout_width="wrap_content"

  20. android:layout_height="wrap_content" />
  21. <TextView

  22. android:id="@+id/video_loading_perce"

  23. android:layout_width="wrap_content"

  24. android:layout_height="wrap_content"

  25. android:paddingTop="7.0dip"

  26. android:text="@string/video_layout_loading"

  27. android:textColor="@color/white"

  28. android:textSize="20.0sp" />

  29. </LinearLayout>
  30. <FrameLayout

  31. android:id="@+id/operation_volume_brightness"

  32. android:layout_width="wrap_content"

  33. android:layout_height="wrap_content"

  34. android:layout_centerInParent="true"

  35. android:background="#00000000"

  36. android:orientation="horizontal"

  37. android:padding="0dip"

  38. android:visibility="invisible" >
  39. <ImageView

  40. android:id="@+id/operation_bg"

  41. android:layout_width="wrap_content"

  42. android:layout_height="wrap_content"

  43. android:layout_gravity="center"

  44. android:src="@drawable/video_volumn_bg" />
  45. <FrameLayout

  46. android:layout_width="wrap_content"

  47. android:layout_height="wrap_content"

  48. android:layout_gravity="bottom|center_horizontal"

  49. android:paddingBottom="25dip" >
  50. <ImageView

  51. android:id="@+id/operation_full"

  52. android:layout_width="94dip"

  53. android:layout_height="wrap_content"

  54. android:layout_gravity="left"

  55. android:src="@drawable/video_num_bg" />
  56. <ImageView

  57. android:id="@+id/operation_percent"

  58. android:layout_width="0dip"

  59. android:layout_height="wrap_content"

  60. android:layout_gravity="left"

  61. android:scaleType="matrix"

  62. android:src="@drawable/video_num_front" />

  63. </FrameLayout>

  64. </FrameLayout>
  65. </RelativeLayout>

播放的显示效果:

时间: 2024-10-29 16:08:35

android直播之流媒体开发(转载)的相关文章

Android流媒体开发之路二:NDK开发Android端RTMP直播推流程序

NDK开发Android端RTMP直播推流程序 经过一番折腾,成功把RTMP直播推流代码,通过NDK交叉编译的方式,移植到了Android下,从而实现了Android端采集摄像头和麦克缝数据,然后进行h264视频编码和aac音频编码,并发送到RTMP服务器,从而实现Android摄像头直播.程序名为NdkRtmpEncoder,在这里把整个过程,和大体框架介绍一下,算是给需要的人引路. 开发思路 首先,为什么要用NDK来做,因为自己之前就已经实现过RTMP推流.RTMP播放.RTSP转码等等各种

android直播音频开发准备

前言 随着音视频领域的火热,在很多领域(教育,游戏,娱乐,体育,跑步,餐饮,音乐等)尝试做音视频直播/点播功能,那么作为开发一个小白,如何快速学习音视频基础知识,了解音视频编解码的传输协议,编解码方式,以及如何技术选型,如何解决遇到的坑,本文抛砖引玉,欢迎大咖交流. 一. 音视频的基础知识 1.1 基本概念 视频是什么 静止的画面叫图像(picture).连续的图像变化每秒超过24帧(frame)画面以上时,根椐视觉暂留原理, 人眼无法辨别每付单独的静态画面,看上去是平滑连续的视觉效果.这样的连

Android直播实现 Android端推流、播放

最近想实现一个Android直播,但是对于这方面的资料都比较零碎,一开始是打算用ffmpeg来实现编码推流,在搜集资料期间,找到了几个强大的开源库,直接避免了jni的代码,集成后只用少量的java代码就可实现编码.推流和取流播放,整理了一下做了一个demo,在这里记录一下 效果图:  编码和推流,有两个方案选择: 一: 使用javacv来实现,最终也是用过ffmpeg来进行编码和推流,javacv实现到可以直接接收摄像头的帧数据 需要自己实现的代码只是打开摄像头,写一个SurfaceView进行

Android直播,音视频播放那些事儿

前言 随着音视频领域的火热,在很多领域(教育,游戏,娱乐,体育,跑步,餐饮,音乐等)尝试做音视频直播/点播功能,那么作为开发一个小白,如何快速学习音视频基础知识,了解音视频编解码的传输协议,编解码方式,以及如何技术选型,如何解决遇到的坑,本文抛砖引玉,欢迎大咖交流. 一. 音视频的基础知识 1.1 基本概念 视频是什么 静止的画面叫图像(picture).连续的图像变化每秒超过24帧(frame)画面以上时,根椐视觉暂留原理, 人眼无法辨别每付单独的静态画面,看上去是平滑连续的视觉效果.这样的连

android和ios流媒体库推荐

1基本信息编辑 Vitamio是一款 Android 与 iOS 平台上的全能多媒体开发框架,全面支持硬件解码与 GPU 渲染.从2011年8月上线到2014年1月,Vitamio 凭借其简洁易用的 API 接口赢得了全球众多开发者的青睐,全球已经有超过3000 种应用在使用Vitamio,覆盖用户超过5亿. 2功能特性编辑 Vitamio能够流畅播放720P甚至1080P高清MKV,FLV,MP4,MOV,TS,RMVB等常见格式的视频,还可以在Android 与 iOS 上跨平台支持 MMS

直播系统怎么开发——直播平台源码

正当兴隆的直播行业如火如荼的发展,得益于手机的便利,手机直播APP也得以快速的推广.等手机直播APP用的多了,自然而然有人问了,直播软件怎么开发? 其实回答这个问题,还是得回到基础的东西--直播平台源码.正是得益于直播平台源码的运用,直播系统开发才会如此迅速的发展,在短时间内把手机直播APP推广的如此成功. 直播平台源码的成功运用,有以下几点: 1.RTMP是实时消息传输协议的首字母缩写.该协议基于TCP,是一个协议族,包括RTMP基本协议及RTMPT/RTMPS/RTMPE等多种变种.RTMP

Android 中带你开发一款自动爆破签名校验工具 kstools

"-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> Android中带你开发一款自动爆破签名校验工具kstools - 生死看淡,不服就干! - 博客频道 - CSDN.NET 生死看淡,不服就干! http://www.wjdiankong.cn 目录视图 摘要视图 订阅 [活动]2017 CSDN博客专栏评选 &n

android音乐播放器开发 SweetMusicPlayer 智能负载直插式歌词

在一份书面的使用MediaPlayer播放音乐, http://blog.csdn.net/huweigoodboy/article/details/39862773.假设没有本地歌词怎么办?如今来将一下载入在线歌词.好了,还是用那张图. 在实现这个功能的时候,lz尝试过baidu api,歌词迷api,后来选用了歌词迷api.尽管还是资源不全.并且还有非常多错误. 特别头疼的是有时候歌词竟然不分行.解析起来简直难受. 歌词迷api歌词查询地址:http://geci.me/api/lyric/

IOS 与ANDROID框架及应用开发模式对比一

IOS 和ANDROID操作系统都是目前流行的移动操作系统,被移动终端和智能设备大量采用,两者都采用了先进的软件技术进行设计,为了方便应用开发两者都采用了先进的设计模式.两者在框架设计上都采用了什么技术?都采用了什么设计模式?两者设计思路和应用开发模式有什么异同呢? 两者都采用了框架模式. IOS 的框架称为Cocoa Touch. 框架提供两个作用,一是类的集合,每个类构建一个问题空间,并提供完整的解决方案和服务:二更重要的是框架中的类相互依赖构成一个整体,制订并实现整个应用程序的结构.框架定