概述

Vitamio 是一款 Android 与 iOS 平台上的全能多媒体开发框架,全面支持硬件解码与 GPU 渲染,底层音视频解码原理基于FFmpeg开发。Vitamio 凭借其简洁易用的 API 接口赢得了全球众多开发者的青睐。到目前,全球已经有超过一万款应用在使用 Vitamio,覆盖用户超过 5亿。
Vitamio 能够流畅播放720P甚至1080P高清MKV,FLV,MP4,MOV,TS,RMVB等常见格式的视频,还可以在 Android 上支持 MMS, RTSP, RTMP, HLS(m3u8) 等常见的多种视频流媒体协议,包括点播与直播。
支持 ARMv6 和 ARMv7 两种 ARM CPU,同时对 VFP, VFPv3, NEON 等指令集都做相应优化。
支持 Android 2.1+ 系统,支持超过 95% 的 Android 市场。同时 Android 2.1 之前的系统也基本支持,不过没做详细测试。
开源项目下载地址:https://github.com/yixia/VitamioBundle

配置Vitamio

导包

开源项目下载后目录结构如下:

其中的VitamioListActivity是官方提供的demo,而我们要导入的包是InitActivity。
Eclipse用户很简单,直接添加InitActivity为依赖工程即可。
Studio用户下载Studio Vitamio包,作为Module导入Project,然后修改以下信息:
app目录下的build.gradle,在dependencies 中添加依赖 compile project(‘:vitamio’) 如果你导入module中更改过名字的话 要改成修改后的名字 如图:

按照app目录下的build.gradle配置vitamio目录下的build.gradle(注意不是vitamio文件夹下app下的)

AndroidManifest配置

注册io.vov.vitamio.activity.InitActivity:

<activity
    android:name="io.vov.vitamio.activity.InitActivity"android:configChanges="orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"android:launchMode="singleTop"android:theme="@android:style/Theme.NoTitleBar"android:windowSoftInputMode="stateAlwaysHidden" />

添加权限:

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

使用Vitamio

VideoView控件的使用

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#696969"tools:context="com.hx.vitamio.MainActivity" ><io.vov.vitamio.widget.CenterLayout
        android:id="@+id/dd"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><io.vov.vitamio.widget.VideoView
            android:id="@+id/vitamio"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_centerHorizontal="true"android:layout_centerVertical="true" /></io.vov.vitamio.widget.CenterLayout><TextView
        android:id="@+id/buffer_percent"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignTop="@id/dd"android:layout_marginLeft="12dp"android:textColor="#e6ff01" /><TextView
        android:id="@+id/net_speed"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignTop="@id/dd"android:layout_marginLeft="12dp"android:layout_toRightOf="@id/buffer_percent"android:textColor="#04fa00" /><Button
        android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_alignParentTop="true"android:background="@mipmap/mediacontroller_sreen_size_100"android:onClick="changeLayout" /></RelativeLayout>
public class MainActivity extends Activity {private VideoView videoView;private TextView percentTv;private TextView netSpeedTv;private int mVideoLayout = 0;private String url1 = "http://112.253.22.157/17/z/z/y/u/zzyuasjwufnqerzvyxgkuigrkcatxr/hc.yinyuetai.com/D046015255134077DDB3ACA0D7E68D45.flv";private String url2 = "http://flashmedia.eastday.com/newdate/news/2016-11/shznews1125-19.mp4";private String url3 = "rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov";private String url4 = "http://42.96.249.166/live/388.m3u8";private String url5 = "http://live.3gv.ifeng.com/zixun.m3u8";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//检查vitamio框架是否可用if (!LibsChecker.checkVitamioLibs(this)) {return;}setContentView(R.layout.activity_main);//显示缓冲百分比的TextViewpercentTv = (TextView) findViewById(R.id.buffer_percent);//显示下载网速的TextViewnetSpeedTv = (TextView) findViewById(R.id.net_speed);//初始化加载库文件if (Vitamio.isInitialized(this)) {videoView = (VideoView) findViewById(R.id.vitamio);videoView.setVideoURI(Uri.parse(url1));videoView.setVideoQuality(MediaPlayer.VIDEOQUALITY_HIGH);MediaController controller = new MediaController(this);videoView.setMediaController(controller);videoView.setBufferSize(10240); //设置视频缓冲大小。默认1024KB,单位bytevideoView.requestFocus();videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mediaPlayer) {// optional need Vitamio 4.0mediaPlayer.setPlaybackSpeed(1.0f);//mediaPlayer.setLooping(true);}});videoView.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {@Overridepublic void onBufferingUpdate(MediaPlayer mp, int percent) {percentTv.setText("已缓冲:" + percent + "%");}});videoView.setOnInfoListener(new MediaPlayer.OnInfoListener() {@Overridepublic boolean onInfo(MediaPlayer mp, int what, int extra) {switch (what) {//开始缓冲case MediaPlayer.MEDIA_INFO_BUFFERING_START:percentTv.setVisibility(View.VISIBLE);netSpeedTv.setVisibility(View.VISIBLE);mp.pause();break;//缓冲结束case MediaPlayer.MEDIA_INFO_BUFFERING_END:percentTv.setVisibility(View.GONE);netSpeedTv.setVisibility(View.GONE);mp.start(); //缓冲结束再播放break;//正在缓冲case MediaPlayer.MEDIA_INFO_DOWNLOAD_RATE_CHANGED:netSpeedTv.setText("当前网速:" + extra + "kb/s");break;}return true;}});}}public void changeLayout(View view) {mVideoLayout++;if (mVideoLayout == 4) {mVideoLayout = 0;}switch (mVideoLayout) {case 0:mVideoLayout = VideoView.VIDEO_LAYOUT_ORIGIN;view.setBackgroundResource(R.mipmap.mediacontroller_sreen_size_100);break;case 1:mVideoLayout = VideoView.VIDEO_LAYOUT_SCALE;view.setBackgroundResource(R.mipmap.mediacontroller_screen_fit);break;case 2:mVideoLayout = VideoView.VIDEO_LAYOUT_STRETCH;view.setBackgroundResource(R.mipmap.mediacontroller_screen_size);break;case 3:mVideoLayout = VideoView.VIDEO_LAYOUT_ZOOM;view.setBackgroundResource(R.mipmap.mediacontroller_sreen_size_crop);break;}videoView.setVideoLayout(mVideoLayout, 0);}
}

注:网速慢的情况下,视频可能会缓冲很久才会播放,这时候可以通过setBufferSize设置视频缓冲大小。默认1024KB,我们可以给它改小点。

VideoView常用函数

/*** 获取扫描视频的Uri。* 参数layout(缩放参数)参见MediaPlayer的常量:VIDEO_LAYOUT_ORIGIN(原始大小)、VIDEO_LAYOUT_SCALE(画面全屏)、VIDEO_LAYOUT_STRETCH(画面拉伸)、VIDEO_LAYOUT_ZOOM(画面裁剪)、VIDEO_LAYOUT_FIT_PARENT(画面铺满)* 参数aspectRation(宽高比),为0将自动检测*/
public void setVideoLayout(int layout,float aspectRatio);
//Surface是否有效。 参见Surface的isValid方法。
public boolean isValid();
//设置视频路径。
public void setVideoPath(String path);
//设置视频URI。(可以是网络视频地址)
public void setVideoURI(Uri uri);
//停止视频播放,并释放资源。
public void stopPlayback();
/*** 设置媒体控制器。* 参数controller:媒体控制器,注意是io.vov.vitamio.widget.MediaController。*/
public void setMediaController(MediaController controller);
//注册一个回调函数,在视频预处理完成后调用。在视频预处理完成后被调用。此时视频的宽度、高度、宽高比信息已经获取到,此时可调用seekTo让视频从指定位置开始播放。
public void setOnPreparedListener(OnPreparedListener l);
//获取当前播放位置。
public long getCurrentPosition();
//设置播放位置。单位毫秒
public void seekTo(long msec);
//是否正在播放。
public boolean isPlaying();
//获取缓冲百分比。
public int getBufferPercentage();
/*** 设置视频质量。* 参数quality参见MediaPlayer的常量:VIDEOQUALITY_LOW(流畅)、VIDEOQUALITY_MEDIUM(普通)、VIDEOQUALITY_HIGH(高质)*/
public void setVideoQuality(int quality);
//设置视频缓冲大小。默认1024KB,单位byte
public void setBufferSize(int bufSize);
//检测是否缓冲完毕。
public boolean isBuffering();
//设置元数据编码。例如:UTF-8
public void setMetaEncoding(String encoding);

更多方法参见:http://www.cnblogs.com/over140/archive/2012/08/30/2663243.html

Vitamio支持的流

Android RTMP流

Real Time Messaging Protocol (RTMP)是一个Adobe Systems所拥有的一个协议。该协议是Adobe公司拥有的开发音视频流的flash player。后来该协议的部分被公开,供公众使用。这个协议大多用于IPTV和实时视频点播流,但它也用于其他领用。
在android上,标准的VideoView不支持RTMP播放。但WebView可以播放RTMP流。这解决了播放RTMP流的问题,但是我认为web apps 不能提供一个很好的界面和体验。因此这个android RTMP例子中我们将运用第三方库-Vitamio 直播RTMP流的流媒体。

Android RTSP流

实时流协议(RTSP)通过多媒体服务器传输内容,例如YouTube使用RTSP流发布内容。关于RTSP流比较容易的部分是,它可以通过android标准的VideoView来完成。
但是如果你使用Vitamio库,可以更好的播放RTSP流。事实上Vitamio也支持RTSP流的回播。

Android m3u8流

“如何在android上播放m3u8视频”是android开发者最常见的问题之一。通过Http 协议进行视频流直播最简单的办法就是使用标准的 VideoView. 但只能在android3.0以上的设备上播放m3u8流。因为在Android 3.0引入HTTP/ HTTPS直播和HTTP/ HTTPS渐进式流媒体协议,在android3.1完全支持HTTPS。
如果你希望在早期的版本上实现支持android m3u8流的HTTP实时流媒体 (HLS)。应该考虑使用Vitamio库,这个库支持在android API7以上播放m3u8。

Android MMS流

Vitamio库是一个强大的库,还支持Microsoft媒体服务器(MMS)流中的播放。 MMS是网络流媒体协议,主要用于网络广播和电台直播。

注:Vitamio是一个强大的多平台库(ios and android)。通过使用Vitamio库能播放多种类型的视频格式和协议如RTMP, RTSP, HTTP Live, HTTP渐进式流协议。另外一个很好的功能是,vitamio支持字幕和多音轨的播放。Vitamio的唯一的缺点是,它不是完全的开源。您可能需要购买许可证来使用它。

基于Vitamio实现的播放器

下面将Vitamio的视频控制器(MediaController)界面进行自定义,同时支持视频亮度、音量的调节,话不多说,先上效果图。

功能:

  • 使用Vitamio的VideoView进行视频播放
  • 显示加载进度和当前网速
  • 视频左侧界面(左1/4以内)上下滑动调节亮度
  • 视频右侧界面(右3/4以外)上下滑动调节声音
  • 双击播放/暂停
  • 中间播放按钮也可以控制播放/暂停
  • 进度显示,并可以拖动调节当前播放进度

(1)播放视频

public class MainActivity extends Activity {private VideoView mVideoView;private TextView downloadRateView, loadRateView;private ProgressBar pb;private CustomMediaController mCustomMediaController;private String url1 = "http://112.253.22.157/17/z/z/y/u/zzyuasjwufnqerzvyxgkuigrkcatxr/hc.yinyuetai.com/D046015255134077DDB3ACA0D7E68D45.flv";private String url2 = "http://flashmedia.eastday.com/newdate/news/2016-11/shznews1125-19.mp4";private String url3 = "rtsp://184.72.239.149/vod/mp4:BigBuckBunny_115k.mov";private String url4 = "http://42.96.249.166/live/24035.m3u8";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//定义全屏参数int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;//获得当前窗体对象Window window = MainActivity.this.getWindow();//设置当前窗体为全屏显示window.setFlags(flag, flag);//检查vitamio框架是否可用if (!LibsChecker.checkVitamioLibs(this)) {return;}setContentView(R.layout.activity_main);pb = (ProgressBar) findViewById(R.id.probar);downloadRateView = (TextView) findViewById(R.id.download_rate);loadRateView = (TextView) findViewById(R.id.load_rate);mVideoView = (VideoView) findViewById(R.id.buffer);mCustomMediaController = new CustomMediaController(this,mVideoView,this);mCustomMediaController.setVideoName("蓝莲花");mCustomMediaController.show(5000); //5s隐藏//初始化加载库文件if (Vitamio.isInitialized(this)) {mVideoView.setVideoURI(Uri.parse(url1));mVideoView.setVideoQuality(MediaPlayer.VIDEOQUALITY_HIGH);mVideoView.setMediaController(mCustomMediaController);mVideoView.setBufferSize(10240); //设置视频缓冲大小mVideoView.requestFocus();mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {@Overridepublic void onPrepared(MediaPlayer mediaPlayer) {// optional need Vitamio 4.0mediaPlayer.setPlaybackSpeed(1.0f);}});mVideoView.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {@Overridepublic void onBufferingUpdate(MediaPlayer mp, int percent) {loadRateView.setText(percent + "%");}});mVideoView.setOnInfoListener(new MediaPlayer.OnInfoListener() {@Overridepublic boolean onInfo(MediaPlayer mp, int what, int extra) {switch (what) {//开始缓冲case MediaPlayer.MEDIA_INFO_BUFFERING_START:if (mVideoView.isPlaying()) {mVideoView.pause();pb.setVisibility(View.VISIBLE);downloadRateView.setText("");loadRateView.setText("");downloadRateView.setVisibility(View.VISIBLE);loadRateView.setVisibility(View.VISIBLE);}break;//缓冲结束case MediaPlayer.MEDIA_INFO_BUFFERING_END:mVideoView.start();pb.setVisibility(View.GONE);downloadRateView.setVisibility(View.GONE);loadRateView.setVisibility(View.GONE);break;//正在缓冲case MediaPlayer.MEDIA_INFO_DOWNLOAD_RATE_CHANGED:downloadRateView.setText("" + extra + "kb/s" + "  ");break;}return true;}});}}@Overridepublic void onConfigurationChanged(Configuration newConfig) {//屏幕切换时,设置全屏if (mVideoView != null){mVideoView.setVideoLayout(VideoView.VIDEO_LAYOUT_SCALE, 0);}super.onConfigurationChanged(newConfig);}
}

(2)视频界面

<?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"><io.vov.vitamio.widget.CenterLayout
        android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><io.vov.vitamio.widget.VideoView
            android:id="@+id/buffer"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_centerHorizontal="true"android:layout_centerVertical="true" /></io.vov.vitamio.widget.CenterLayout><LinearLayout
        android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:orientation="horizontal"><ProgressBar
            android:id="@+id/probar"style="?android:attr/progressBarStyleLarge"android:layout_width="50dp"android:layout_height="50dp" /><TextView
            android:id="@+id/download_rate"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text=""android:textColor="#FFFFFF" /><TextView
            android:id="@+id/load_rate"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text=""android:textColor="#FFFFFF" /></LinearLayout>
</RelativeLayout>

(3)视频控制器

/*** 自定义视频控制器*/
public class CustomMediaController extends MediaController {//控制提示窗口的显示private static final int HIDEFRAM = 0;private GestureDetector mGestureDetector;//返回按钮private ImageButton img_back;//文件名private TextView mFileName;private VideoView videoView;private Activity activity;private Context context;//视频名称private String videoname;//设置mediaController高度为了使横屏时top显示在屏幕顶端private int controllerWidth = 0;private View mVolumeBrightnessLayout;//提示窗口private ImageView mOperationBg;//提示图片private TextView mOperationTv;//提示文字private AudioManager mAudioManager;//最大声音private int mMaxVolume;// 当前声音private int mVolume = -1;//当前亮度private float mBrightness = -1f;private Handler myHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case HIDEFRAM://隐藏提示窗口mVolumeBrightnessLayout.setVisibility(View.GONE);break;}}};//videoview 用于对视频进行控制的等,activity为了退出public CustomMediaController(Context context, VideoView videoView, Activity activity) {super(context);this.context = context;this.videoView = videoView;this.activity = activity;WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);controllerWidth = wm.getDefaultDisplay().getWidth();mGestureDetector = new GestureDetector(context, new MyGestureListener());}@Overrideprotected View makeControllerView() {//此处的mymediacontroller为我们自定义控制器的布局文件名称View v = ((LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.mymediacontroller, this);v.setMinimumHeight(controllerWidth);//获取控件img_back = (ImageButton) v.findViewById(R.id.mediacontroller_top_back);mFileName = (TextView) v.findViewById(R.id.mediacontroller_filename);if (mFileName != null) {mFileName.setText(videoname);}mVolumeBrightnessLayout = (RelativeLayout) v.findViewById(R.id.operation_volume_brightness);mOperationBg = (ImageView) v.findViewById(R.id.operation_bg);mOperationTv = (TextView) v.findViewById(R.id.operation_tv);//声音控制mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);mMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);//注册事件监听img_back.setOnClickListener(backListener);return v;}//返回监听private View.OnClickListener backListener = new View.OnClickListener() {public void onClick(View v) {if (activity != null) {activity.finish();}}};@Overridepublic boolean dispatchKeyEvent(KeyEvent event) {System.out.println("MYApp-MyMediaController-dispatchKeyEvent");return true;}@Overridepublic boolean onTouchEvent(MotionEvent event) {if (mGestureDetector.onTouchEvent(event))return true;// 处理手势结束switch (event.getAction() & MotionEvent.ACTION_MASK) {case MotionEvent.ACTION_UP:endGesture();break;}return super.onTouchEvent(event);}/*** 手势结束*/private void endGesture() {mVolume = -1;mBrightness = -1f;//隐藏myHandler.removeMessages(HIDEFRAM);myHandler.sendEmptyMessageDelayed(HIDEFRAM, 500);}private class MyGestureListener extends GestureDetector.SimpleOnGestureListener {@Overridepublic boolean onSingleTapUp(MotionEvent e) {return false;}/*** 因为使用的是自定义的mediaController 当显示后,mediaController会铺满屏幕,* 所以VideoView的点击事件会被拦截,所以重写控制器的手势事件,* 将全部的操作全部写在控制器中,* 因为点击事件被控制器拦截,无法传递到下层的VideoView,* 所以原来的单击隐藏会失效,作为代替,* 在手势监听中onSingleTapConfirmed()添加自定义的隐藏/显示,** @param e* @return*/@Overridepublic boolean onSingleTapConfirmed(MotionEvent e) {//当手势结束,并且是单击结束时,控制器隐藏/显示toggleMediaControlsVisiblity();return super.onSingleTapConfirmed(e);}@Overridepublic boolean onDown(MotionEvent e) {return true;}//滑动事件监听@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {float mOldX = e1.getX(), mOldY = e1.getY();int y = (int) e2.getRawY();int x = (int) e2.getRawX();Display disp = activity.getWindowManager().getDefaultDisplay();int windowWidth = disp.getWidth();int windowHeight = disp.getHeight();if (mOldX > windowWidth * 3.0 / 4.0) {//右边滑动 超过屏幕右侧3/4onVolumeSlide((mOldY - y) / windowHeight);} else if (mOldX < windowWidth * 1.0 / 4.0) {//左边滑动 不超过屏幕左侧1/4onBrightnessSlide((mOldY - y) / windowHeight);}return super.onScroll(e1, e2, distanceX, distanceY);}@Overridepublic boolean onDoubleTap(MotionEvent e) {playOrPause();return true;}@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {return super.onFling(e1, e2, velocityX, velocityY);}}/*** 滑动改变声音大小** @param percent*/private void onVolumeSlide(float percent) {if (mVolume == -1) {mVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);if (mVolume < 0)mVolume = 0;// 显示mVolumeBrightnessLayout.setVisibility(View.VISIBLE);}int index = (int) (percent * mMaxVolume) + mVolume;if (index > mMaxVolume) {index = mMaxVolume;} else if (index < 0) {index = 0;}//变更声音mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 0);mOperationTv.setText((int) (((double) index / mMaxVolume) * 100) + "%");if (index >= 10) {mOperationBg.setImageResource(R.drawable.volmn_100);} else if (index >= 5 && index < 10) {mOperationBg.setImageResource(R.drawable.volmn_60);} else if (index > 0 && index < 5) {mOperationBg.setImageResource(R.drawable.volmn_30);} else {mOperationBg.setImageResource(R.drawable.volmn_no);}}/*** 滑动改变亮度** @param percent*/private void onBrightnessSlide(float percent) {if (mBrightness < 0) {mBrightness = activity.getWindow().getAttributes().screenBrightness;if (mBrightness <= 0.00f)mBrightness = 0.50f;if (mBrightness < 0.01f)mBrightness = 0.01f;mVolumeBrightnessLayout.setVisibility(View.VISIBLE);}WindowManager.LayoutParams lpa = activity.getWindow().getAttributes();lpa.screenBrightness = mBrightness + percent;if (lpa.screenBrightness > 1.0f) {lpa.screenBrightness = 1.0f;} else if (lpa.screenBrightness < 0.01f) {lpa.screenBrightness = 0.01f;}//变更亮度activity.getWindow().setAttributes(lpa);mOperationTv.setText((int) (lpa.screenBrightness * 100) + "%");if (lpa.screenBrightness * 100 >= 90) {mOperationBg.setImageResource(R.drawable.light_100);} else if (lpa.screenBrightness * 100 >= 80 && lpa.screenBrightness * 100 < 90) {mOperationBg.setImageResource(R.drawable.light_90);} else if (lpa.screenBrightness * 100 >= 70 && lpa.screenBrightness * 100 < 80) {mOperationBg.setImageResource(R.drawable.light_80);} else if (lpa.screenBrightness * 100 >= 60 && lpa.screenBrightness * 100 < 70) {mOperationBg.setImageResource(R.drawable.light_70);} else if (lpa.screenBrightness * 100 >= 50 && lpa.screenBrightness * 100 < 60) {mOperationBg.setImageResource(R.drawable.light_60);} else if (lpa.screenBrightness * 100 >= 40 && lpa.screenBrightness * 100 < 50) {mOperationBg.setImageResource(R.drawable.light_50);} else if (lpa.screenBrightness * 100 >= 30 && lpa.screenBrightness * 100 < 40) {mOperationBg.setImageResource(R.drawable.light_40);} else if (lpa.screenBrightness * 100 >= 20 && lpa.screenBrightness * 100 < 20) {mOperationBg.setImageResource(R.drawable.light_30);} else if (lpa.screenBrightness * 100 >= 10 && lpa.screenBrightness * 100 < 20) {mOperationBg.setImageResource(R.drawable.light_20);}}/*** 设置视频文件名** @param name*/public void setVideoName(String name) {videoname = name;if (mFileName != null) {mFileName.setText(name);}}/*** 隐藏或显示*/private void toggleMediaControlsVisiblity() {if (isShowing()) {hide();} else {show();}}/*** 播放/暂停*/private void playOrPause() {if (videoView != null)if (videoView.isPlaying()) {videoView.pause();} else {videoView.start();}}
}

(4)视频控制器界面

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><RelativeLayout
        android:layout_width="match_parent"android:layout_height="match_parent"><RelativeLayout
            android:layout_width="match_parent"android:layout_height="34dp"android:background="#77000000"><ImageButton
                android:id="@+id/mediacontroller_top_back"android:layout_width="50dp"android:layout_height="match_parent"android:layout_alignParentLeft="true"android:background="@null"android:src="@drawable/ic_player_close_white" /><TextView
                android:id="@+id/mediacontroller_filename"style="@style/MediaController_Text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginLeft="5dp"android:layout_toRightOf="@+id/mediacontroller_top_back"android:ellipsize="marquee"android:singleLine="true"android:text="file name" /><ImageButton
                android:id="@+id/mediacontroller_share"android:layout_width="50dp"android:layout_height="match_parent"android:layout_alignParentRight="true"android:background="@null"android:src="@drawable/ic_action_share_without_padding" /><ImageButton
                android:id="@+id/mediacontroller_favorite"android:layout_width="50dp"android:layout_height="match_parent"android:layout_toLeftOf="@id/mediacontroller_share"android:background="@null"android:src="@drawable/ic_action_favorites" /></RelativeLayout><ImageButton
            android:id="@+id/mediacontroller_play_pause"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:background="@null"android:src="@drawable/play_selector" /><RelativeLayout
            android:id="@+id/operation_volume_brightness"android:layout_width="150dp"android:layout_height="75dp"android:layout_centerInParent="true"android:background="@drawable/videobg"android:orientation="horizontal"android:padding="0dip"android:visibility="gone"><ImageView
                android:id="@+id/operation_bg"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:src="@drawable/video_volumn_bg" /><TextView
                android:id="@+id/operation_tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBottom="@+id/operation_bg"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:textColor="#ffffff"android:textSize="12sp" /></RelativeLayout><RelativeLayout
            android:layout_width="match_parent"android:layout_height="50dp"android:layout_alignParentBottom="true"android:background="#77000000"><TextView
                android:id="@+id/mediacontroller_time_current"style="@style/MediaController_Text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginLeft="15dp"android:text="33:33:33" /><TextView
                android:id="@+id/mediacontroller_time_total"style="@style/MediaController_Text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:layout_marginRight="15dp"android:text="33:33:33" /><SeekBar
                android:id="@+id/mediacontroller_seekbar"style="@style/MediaController_SeekBar"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_toLeftOf="@id/mediacontroller_time_total"android:layout_toRightOf="@id/mediacontroller_time_current"android:focusable="true"android:max="1000" /></RelativeLayout></RelativeLayout>
</LinearLayout>

(5)Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.hx.vitamio"><application
        android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"android:screenOrientation="sensorLandscape"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><!-- 必须初始化 --><activity
            android:name="io.vov.vitamio.activity.InitActivity"android:configChanges="orientation|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"android:launchMode="singleTop"android:theme="@android:style/Theme.NoTitleBar"android:windowSoftInputMode="stateAlwaysHidden" /></application><uses-permission android:name="android.permission.WAKE_LOCK" /><uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /></manifest>

具体就不一一分析了,大家需要直接看代码吧。

一些电视台的直播地址

下面是我记录的一些电视台的直播地址,奉献给大家:
CCTV: rtmp://203.207.99.19:1935/live/CCTV5
注:后面的数字可以自己修改为中央几台
凤凰卫视:http://zv.3gv.ifeng.com/live/zhongwen800k.m3u8

Demo下载地址
Part1…
Part2…
Part3…

请将三部分全部下载完毕后再进行解压。

Android Vitamio的使用解析相关推荐

  1. 安卓 linux init.rc,[原创]Android init.rc文件解析过程详解(二)

    Android init.rc文件解析过程详解(二) 3.parse_new_section代码如下: void parse_new_section(struct parse_state *state ...

  2. Android init.rc文件格式解析

    /****************************************************************************** Android init.rc文件格式解 ...

  3. android之json解析优化,Android开发之json解析

    目前正在尝试着写app,发现看懂代码和能写出来差距很大,最关键的是java基础比较的差,因为只会python,java基础只学习了一个礼拜就过了.感觉java写出来的代码不如python简单明了. 上 ...

  4. Android网络之数据解析----SAX方式解析XML数据

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  5. Android init.rc文件解析过程详解(三)

    Android init.rc文件解析过程详解(三) 三.相关结构体 1.listnode listnode结构体用于建立双向链表,这种结构广泛用于kernel代码中, android源代码中定义了l ...

  6. Android init.rc文件解析过程详解(二)

    Android init.rc文件解析过程详解(二) 3.parse_new_section代码如下: void parse_new_section(struct parse_state *state ...

  7. Android init.rc文件解析过程详解(一)

        Android init.rc文件解析过程详解(一) 一.init.rc文件结构介绍 init.rc文件基本组成单位是section, section分为三种类型,分别由三个关键字(所谓关键字 ...

  8. Android中三种常用解析XML的方式(DOM、SAX、PULL)简介及区别

    XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能.今天就由我向大家介绍一下在Android平台下几种常见的XML解 ...

  9. Android 插件化原理解析——Activity生命周期管理

    之前的 Android插件化原理解析 系列文章揭开了Hook机制的神秘面纱,现在我们手握倚天屠龙,那么如何通过这种技术完成插件化方案呢?具体来说,插件中的Activity,Service等组件如何在A ...

最新文章

  1. train_test_split()用法
  2. unicode表_Python数据库操作 Mysql数据库表引擎与字符集#学习猿地
  3. 微信小程序中换行,空格(多个空格)写法
  4. 那些在家啃书自学的人,最后都找到工作了吗?
  5. C++学习笔记—srand()和rand()
  6. 腾讯通RTX发送文件出错的解决方法
  7. Nexus3 安装 及 配置 docker 私有、代理 仓库
  8. The jar of this class file belongs to container 'JUnit 4' which does not allow ...
  9. 常见的ASCII码值
  10. linux c++ 时间戳转换,C++时间戳转换成日期时间的步骤和示例代码
  11. 多线程ADSL切换IP
  12. 迅捷pdf转换器完美解决如何将pdf转换成word问题
  13. Celery介绍---手机短信异步发送
  14. 斜线表头html怎么做,Excel三栏斜线表头的完美制作方法
  15. app inventor入门详细教程(音乐播放器)01
  16. 动态规划--资源分配问题
  17. 一个投资者想要的真正的DAO-Revolution DAO
  18. 卷积神经网络(LeNet)——【torch学习笔记】
  19. AHPs——algebraic holographic proofs
  20. 安卓 动画的深入分析

热门文章

  1. python猫狗大战游戏下载_猫狗大战RPG游戏下载-猫狗大战RPG官方版下载v1.1.8-PChome下载中心...
  2. (树状数组+逆元)洛谷P5142 区间方差
  3. 由13位数字组成的中国标准书号校验码计算实例
  4. 初一数学教材人教版_初中数学教材章节-人教版
  5. SRS4.0源码分析-main
  6. 【Pytorch】AWSnet论文解读与实验复现
  7. 量化投资学习——股指期货理论价格说明
  8. 走过冷暖的岁月,感知生命的厚重
  9. Json概述以及python对json的相关操作(至尊宝错过了紫霞仙子,难道你也要错过python对json的相关操作吗?)
  10. 《深入分布式缓存:从原理到实践》