首页 > 代码库 > android直播之流媒体开发(转载)

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.   
  11.     <EditText  
  12.         android:id="@+id/live_url"  
  13.         android:layout_width="match_parent"  
  14.         android:layout_height="100dp" />  
  15.   
  16.     <Button  
  17.         android:id="@+id/play"  
  18.         android:layout_width="120dp"  
  19.         android:layout_height="60dp"  
  20.         android:layout_below="@id/live_url"  
  21.         android:layout_centerHorizontal="true"  
  22.         android:layout_marginTop="100dp"  
  23.         android:text="Play" >  
  24.     </Button>  
  25.   
  26. </RelativeLayout>  


主界面的类:

[java] view plaincopy
  1. package com.jwzhangjie.live;  
  2.   
  3. import android.os.Bundle;  
  4. import android.app.Activity;  
  5. import android.content.Intent;  
  6. import android.view.Menu;  
  7. import android.view.View;  
  8. import android.view.View.OnClickListener;  
  9. import android.widget.Button;  
  10. import android.widget.EditText;  
  11.   
  12. public class Live extends Activity {  
  13.   
  14.     public static final String  DEFAULTPATH = "http://ipadlive.cntv.soooner.com/cctv_p2p_hdcctv6.m3u8";  
  15.     EditText Live_Url;  
  16.     Button PlayBtn;  
  17.     @Override  
  18.     protected void onCreate(Bundle savedInstanceState) {  
  19.         super.onCreate(savedInstanceState);  
  20.         setContentView(R.layout.activity_live);  
  21.         Live_Url = (EditText)findViewById(R.id.live_url);  
  22.         Live_Url.setText(DEFAULTPATH);  
  23.         PlayBtn = (Button)findViewById(R.id.play);  
  24.         PlayBtn.setOnClickListener(new OnClickListener() {  
  25.             @Override  
  26.             public void onClick(View v) {  
  27.                 Intent intent = new Intent();  
  28.                 intent.setClass(Live.this, JieVideoPlayer.class);  
  29.                 String path = Live_Url.getText().toString();  
  30.                 if (path == null) {  
  31.                     path = DEFAULTPATH;  
  32.                 }  
  33.                 intent.putExtra("path", path);  
  34.                 startActivity(intent);  
  35.             }  
  36.         });  
  37.     }  
  38.   
  39.     @Override  
  40.     public boolean onCreateOptionsMenu(Menu menu) {  
  41.         getMenuInflater().inflate(R.menu.live, menu);  
  42.         return true;  
  43.     }  
  44.   
  45. }  


播放界面的类:

[java] view plaincopy
  1. package com.jwzhangjie.live;  
  2.   
  3. import io.vov.vitamio.LibsChecker;  
  4. import io.vov.vitamio.MediaPlayer;  
  5. import io.vov.vitamio.MediaPlayer.OnCompletionListener;  
  6. import io.vov.vitamio.MediaPlayer.OnInfoListener;  
  7. import io.vov.vitamio.widget.MediaController;  
  8. import io.vov.vitamio.widget.VideoView;  
  9. import android.annotation.SuppressLint;  
  10. import android.app.Activity;  
  11. import android.content.Context;  
  12. import android.content.pm.ActivityInfo;  
  13. import android.content.res.Configuration;  
  14. import android.media.AudioManager;  
  15. import android.net.Uri;  
  16. import android.os.Bundle;  
  17. import android.os.Handler;  
  18. import android.os.Message;  
  19. import android.util.Log;  
  20. import android.view.Display;  
  21. import android.view.GestureDetector.SimpleOnGestureListener;  
  22. import android.view.GestureDetector;  
  23. import android.view.MotionEvent;  
  24. import android.view.View;  
  25. import android.view.ViewGroup;  
  26. import android.view.WindowManager;  
  27. import android.widget.ImageView;  
  28.   
  29. @SuppressLint("HandlerLeak")  
  30. public class JieVideoPlayer extends Activity implements OnCompletionListener, OnInfoListener {  
  31.   
  32.     private String mPath;  
  33.     private String mTitle;  
  34.     private VideoView mVideoView;  
  35.     private View mVolumeBrightnessLayout;  
  36.     private ImageView mOperationBg;  
  37.     private ImageView mOperationPercent;  
  38.     private AudioManager mAudioManager;  
  39.     /** 声音 */  
  40.     private int mMaxVolume;  
  41.     /** 当前声音 */  
  42.     private int mVolume = -1;  
  43.     /** 当前亮度 */  
  44.     private float mBrightness = -1f;  
  45.     /** 当前缩放模式 */  
  46.     private int mLayout = VideoView.VIDEO_LAYOUT_ZOOM;  
  47.     private GestureDetector mGestureDetector;  
  48.     private MediaController mMediaController;  
  49.     private View mLoadingView;  
  50.     @Override  
  51.     public void onCreate(Bundle savedInstanceState) {  
  52.         super.onCreate(savedInstanceState);  
  53.   
  54.         if (!LibsChecker.checkVitamioLibs(this))  
  55.             return;  
  56.   
  57.         // ~~~ 获取播放地址和标  
  58.         // ~~~ 绑定控件  
  59.         setContentView(R.layout.videoview);  
  60.         mPath = getIntent().getStringExtra("path");  
  61.         mVideoView = (VideoView) findViewById(R.id.surface_view);  
  62.         mVolumeBrightnessLayout = findViewById(R.id.operation_volume_brightness);  
  63.         mOperationBg = (ImageView) findViewById(R.id.operation_bg);  
  64.         mOperationPercent = (ImageView) findViewById(R.id.operation_percent);  
  65.         mLoadingView = findViewById(R.id.video_loading);  
  66.         // ~~~ 绑定事件  
  67.         mVideoView.setOnCompletionListener(this);  
  68.         mVideoView.setOnInfoListener(this);  
  69.   
  70.         // ~~~ 绑定数据  
  71.         mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);  
  72.         mMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);  
  73.           
  74.         if (mPath.startsWith("http:")){  
  75.             mVideoView.setVideoURI(Uri.parse(mPath));  
  76.         }  
  77.         else{  
  78.             mVideoView.setVideoPath(mPath);  
  79.         }  
  80.         //设置显示名称  
  81.         mMediaController = new MediaController(this);  
  82.         mMediaController.setFileName(mTitle);  
  83.         mVideoView.setMediaController(mMediaController);  
  84.         mVideoView.requestFocus();  
  85.   
  86.         mGestureDetector = new GestureDetector(thisnew MyGestureListener());  
  87.         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);  
  88.     }  
  89.   
  90.     @Override  
  91.     protected void onPause() {  
  92.         super.onPause();  
  93.         if (mVideoView != null)  
  94.             mVideoView.pause();  
  95.     }  
  96.   
  97.     @Override  
  98.     protected void onResume() {  
  99.         super.onResume();  
  100.         if (mVideoView != null)  
  101.             mVideoView.resume();  
  102.     }  
  103.   
  104.     @Override  
  105.     protected void onDestroy() {  
  106.         super.onDestroy();  
  107.         if (mVideoView != null)  
  108.             mVideoView.stopPlayback();  
  109.     }  
  110.   
  111.     @Override  
  112.     public boolean onTouchEvent(MotionEvent event) {  
  113.         if (mGestureDetector.onTouchEvent(event))  
  114.             return true;  
  115.   
  116.         // 处理手势结束  
  117.         switch (event.getAction() & MotionEvent.ACTION_MASK) {  
  118.         case MotionEvent.ACTION_UP:  
  119.             endGesture();  
  120.             break;  
  121.         }  
  122.   
  123.         return super.onTouchEvent(event);  
  124.     }  
  125.   
  126.     /** 手势结束 */  
  127.     private void endGesture() {  
  128.         mVolume = -1;  
  129.         mBrightness = -1f;  
  130.   
  131.         // 隐藏  
  132.         mDismissHandler.removeMessages(0);  
  133.         mDismissHandler.sendEmptyMessageDelayed(0500);  
  134.     }  
  135.   
  136.     private class MyGestureListener extends SimpleOnGestureListener {  
  137.   
  138.         /** 双击 */  
  139.         @Override  
  140.         public boolean onDoubleTap(MotionEvent e) {  
  141.             if (mLayout == VideoView.VIDEO_LAYOUT_ZOOM)  
  142.                 mLayout = VideoView.VIDEO_LAYOUT_ORIGIN;  
  143.             else  
  144.                 mLayout++;  
  145.             if (mVideoView != null)  
  146.                 mVideoView.setVideoLayout(mLayout, 0);  
  147.             return true;  
  148.         }  
  149.   
  150.         /** 滑动 */  
  151.         @SuppressWarnings("deprecation")  
  152.         @Override  
  153.         public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {  
  154.             float mOldX = e1.getX(), mOldY = e1.getY();  
  155.             int y = (int) e2.getRawY();  
  156.             Display disp = getWindowManager().getDefaultDisplay();  
  157.             int windowWidth = disp.getWidth();  
  158.             int windowHeight = disp.getHeight();  
  159.   
  160.             if (mOldX > windowWidth * 4.0 / 5)// 右边滑动  
  161.                 onVolumeSlide((mOldY - y) / windowHeight);  
  162.             else if (mOldX < windowWidth / 5.0)// 左边滑动  
  163.                 onBrightnessSlide((mOldY - y) / windowHeight);  
  164.   
  165.             return super.onScroll(e1, e2, distanceX, distanceY);  
  166.         }  
  167.     }  
  168.   
  169.     /** 定时隐藏 */  
  170.     private Handler mDismissHandler = new Handler() {  
  171.         @Override  
  172.         public void handleMessage(Message msg) {  
  173.             mVolumeBrightnessLayout.setVisibility(View.GONE);  
  174.         }  
  175.     };  
  176.   
  177.     /** 
  178.      * 滑动改变声音大小 
  179.      *  
  180.      * @param percent 
  181.      */  
  182.     private void onVolumeSlide(float percent) {  
  183.         if (mVolume == -1) {  
  184.             mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);  
  185.             if (mVolume < 0)  
  186.                 mVolume = 0;  
  187.   
  188.             // 显示  
  189.             mOperationBg.setImageResource(R.drawable.video_volumn_bg);  
  190.             mVolumeBrightnessLayout.setVisibility(View.VISIBLE);  
  191.         }  
  192.   
  193.         int index = (int) (percent * mMaxVolume) + mVolume;  
  194.         if (index > mMaxVolume)  
  195.             index = mMaxVolume;  
  196.         else if (index < 0)  
  197.             index = 0;  
  198.   
  199.         // 变更声音  
  200.         mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);  
  201.   
  202.         // 变更进度??  
  203.         ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams();  
  204.         lp.width = findViewById(R.id.operation_full).getLayoutParams().width * index / mMaxVolume;  
  205.         mOperationPercent.setLayoutParams(lp);  
  206.     }  
  207.   
  208.     /** 
  209.      * 滑动改变亮度 
  210.      *  
  211.      * @param percent 
  212.      */  
  213.     private void onBrightnessSlide(float percent) {  
  214.         if (mBrightness < 0) {  
  215.             mBrightness = getWindow().getAttributes().screenBrightness;  
  216.             if (mBrightness <= 0.00f)  
  217.                 mBrightness = 0.50f;  
  218.             if (mBrightness < 0.01f)  
  219.                 mBrightness = 0.01f;  
  220.   
  221.             // 显示  
  222.             mOperationBg.setImageResource(R.drawable.video_brightness_bg);  
  223.             mVolumeBrightnessLayout.setVisibility(View.VISIBLE);  
  224.         }  
  225.         WindowManager.LayoutParams lpa = getWindow().getAttributes();  
  226.         lpa.screenBrightness = mBrightness + percent;  
  227.         if (lpa.screenBrightness > 1.0f)  
  228.             lpa.screenBrightness = 1.0f;  
  229.         else if (lpa.screenBrightness < 0.01f)  
  230.             lpa.screenBrightness = 0.01f;  
  231.         getWindow().setAttributes(lpa);  
  232.   
  233.         ViewGroup.LayoutParams lp = mOperationPercent.getLayoutParams();  
  234.         lp.width = (int) (findViewById(R.id.operation_full).getLayoutParams().width * lpa.screenBrightness);  
  235.         mOperationPercent.setLayoutParams(lp);  
  236.     }  
  237.   
  238.     @Override  
  239.     public void onConfigurationChanged(Configuration newConfig) {  
  240.         if (mVideoView != null)  
  241.             mVideoView.setVideoLayout(mLayout, 0);  
  242.         super.onConfigurationChanged(newConfig);  
  243.     }  
  244.   
  245.     @Override  
  246.     public void onCompletion(MediaPlayer player) {  
  247.         Log.e("tet""播放完成");  
  248.     }  
  249.   
  250.     private void stopPlayer() {  
  251.         if (mVideoView != null)  
  252.             mVideoView.pause();  
  253.     }  
  254.   
  255.     private void startPlayer() {  
  256.         if (mVideoView != null)  
  257.             mVideoView.start();  
  258.     }  
  259.   
  260.     private boolean isPlaying() {  
  261.         return mVideoView != null && mVideoView.isPlaying();  
  262.     }  
  263.   
  264.     /** 是否????自动恢复播放,用于自动暂停,恢复播放 */  
  265.     private boolean needResume;  
  266.   
  267.     @Override  
  268.     public boolean onInfo(MediaPlayer arg0, int arg1, int down_rate) {  
  269.         switch (arg1) {  
  270.         case MediaPlayer.MEDIA_INFO_BUFFERING_START:  
  271.             //????缓存,暂停播??  
  272.             if (isPlaying()) {  
  273.                 stopPlayer();  
  274.                 needResume = true;  
  275.             }  
  276.             mLoadingView.setVisibility(View.VISIBLE);  
  277.             break;  
  278.         case MediaPlayer.MEDIA_INFO_BUFFERING_END:  
  279.             //缓存完成,继续播??  
  280.             if (needResume)  
  281.                 startPlayer();  
  282.             mLoadingView.setVisibility(View.GONE);  
  283.             break;  
  284.         case MediaPlayer.MEDIA_INFO_DOWNLOAD_RATE_CHANGED:  
  285.             //显示 下载速度  
  286.             Log.e("test","download rate:" + down_rate);  
  287. //          mLoadingPerce.setText("正在缓冲??.."+"缓冲完成??+down_rate);  
  288.             //mListener.onDownloadRateChanged(arg2);  
  289.             break;  
  290.         }  
  291.         return true;  
  292.     }  
  293. }  


播放界面的配置:

[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.   
  7.     <io.vov.vitamio.widget.VideoView  
  8.         android:id="@+id/surface_view"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="fill_parent"  
  11.         android:layout_centerHorizontal="true"  
  12.         android:layout_centerVertical="true" />  
  13.   
  14.     <LinearLayout  
  15.         android:id="@+id/video_loading"  
  16.         android:layout_width="wrap_content"  
  17.         android:layout_height="wrap_content"  
  18.         android:layout_centerInParent="true"  
  19.         android:gravity="center_vertical" >  
  20.   
  21.         <ProgressBar  
  22.             android:layout_width="wrap_content"  
  23.             android:layout_height="wrap_content" />  
  24.   
  25.         <TextView  
  26.             android:id="@+id/video_loading_perce"  
  27.             android:layout_width="wrap_content"  
  28.             android:layout_height="wrap_content"  
  29.             android:paddingTop="7.0dip"  
  30.             android:text="@string/video_layout_loading"  
  31.             android:textColor="@color/white"  
  32.             android:textSize="20.0sp" />  
  33.     </LinearLayout>  
  34.   
  35.     <FrameLayout  
  36.         android:id="@+id/operation_volume_brightness"  
  37.         android:layout_width="wrap_content"  
  38.         android:layout_height="wrap_content"  
  39.         android:layout_centerInParent="true"  
  40.         android:background="#00000000"  
  41.         android:orientation="horizontal"  
  42.         android:padding="0dip"  
  43.         android:visibility="invisible" >  
  44.   
  45.         <ImageView  
  46.             android:id="@+id/operation_bg"  
  47.             android:layout_width="wrap_content"  
  48.             android:layout_height="wrap_content"  
  49.             android:layout_gravity="center"  
  50.             android:src="@drawable/video_volumn_bg" />  
  51.   
  52.         <FrameLayout  
  53.             android:layout_width="wrap_content"  
  54.             android:layout_height="wrap_content"  
  55.             android:layout_gravity="bottom|center_horizontal"  
  56.             android:paddingBottom="25dip" >  
  57.   
  58.             <ImageView  
  59.                 android:id="@+id/operation_full"  
  60.                 android:layout_width="94dip"  
  61.                 android:layout_height="wrap_content"  
  62.                 android:layout_gravity="left"  
  63.                 android:src="@drawable/video_num_bg" />  
  64.   
  65.             <ImageView  
  66.                 android:id="@+id/operation_percent"  
  67.                 android:layout_width="0dip"  
  68.                 android:layout_height="wrap_content"  
  69.                 android:layout_gravity="left"  
  70.                 android:scaleType="matrix"  
  71.                 android:src="@drawable/video_num_front" />  
  72.         </FrameLayout>  
  73.     </FrameLayout>  
  74.   
  75. </RelativeLayout>  


播放的显示效果: