先上图,在Android中使用Vitamio播放香港卫视:

第一步,AndroidStudio中导入Vitamio

1 Vitamio源码下载,源码下载下来后,我们将vitamio导入AndroStudio中。

2 File->new->Import Module,导入vitmio文件夹。

3 vitamio目录下的build.gradle中下图配置,要和app目录下的build.gradle中的配置相同:

4 app目录下的build.gradle,在dependencies 中添加依赖 compile project(‘:vitamio’) ,如果你导入module中更改过名字的话 要改成修改后的名字,如下图:

上述步骤完成后,rebuild即可导入。

第二步,配置vitamio

导入vitamio后,我们还要进行如下配置:

1 在AndroidManifest中,注册io.vov.vitamio.activity.InitActivity:

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

2 在AndroidManifest中,添加权限:

<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

vitamio中常用的两个组件是:VideoView和MediaController。

VideoView是播放器组件,继承了SurfaceView。VideoView可以加载各种来源的图像,还可以计算视频尺寸,以便在任意布局管理器中使用,它还提供了诸如缩放等显示选项。VideoView也提供封装了许多MediaPlayer的方法,例如getVideoWidth、setSubShown。常用API如下:

/*** 获取扫描视频的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);

MediaController用于加载一个布局文件,在makeControllerView中返回布局对应的View。

第四步,使用vitamio实现播放器,直播香港卫视。

1 自定义MediaController:

package com.xi.liuliu.topnews.controller;import android.app.Activity;
import android.content.Context;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;import com.xi.liuliu.topnews.R;import io.vov.vitamio.widget.MediaController;
import io.vov.vitamio.widget.VideoView;public class LiveMediaController extends MediaController {private GestureDetector mGestureDetector;private ImageButton mGoBack;private ImageView mBattery;private TextView mTime;private TextView mBatteryPercent;private VideoView mVideoView;private Activity mActivity;private Context mContext;private int mControllerWidth = 0;public LiveMediaController(Context context, VideoView videoView, Activity activity) {super(context);this.mContext = context;this.mVideoView = videoView;this.mActivity = activity;WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);mControllerWidth = wm.getDefaultDisplay().getWidth();mGestureDetector = new GestureDetector(context, new MyGestureListener());}@Overrideprotected View makeControllerView() {View v = LayoutInflater.from(mContext).inflate(R.layout.live_media_controller, null);v.setMinimumHeight(mControllerWidth);mGoBack = (ImageButton) v.findViewById(R.id.media_controller_top_back);mBattery = (ImageView) v.findViewById(R.id.media_controller_battery);mGoBack.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {if (mActivity != null) {mActivity.finish();}}});mBatteryPercent = (TextView) v.findViewById(R.id.media_controller_battery_percent);mTime = (TextView) v.findViewById(R.id.media_controller_current_time);return v;}@Overridepublic boolean dispatchKeyEvent(KeyEvent event) {return true;}@Overridepublic boolean onTouchEvent(MotionEvent event) {if (mGestureDetector.onTouchEvent(event)) return true;switch (event.getAction() & MotionEvent.ACTION_MASK) {case MotionEvent.ACTION_UP:break;}return super.onTouchEvent(event);}private class MyGestureListener extends GestureDetector.SimpleOnGestureListener {@Overridepublic boolean onSingleTapUp(MotionEvent e) {return false;}@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) {return super.onScroll(e1, e2, distanceX, distanceY);}@Overridepublic boolean onDoubleTap(MotionEvent e) {playOrPause();return true;}}public void setTime(String time) {if (mTime != null)mTime.setText(time);}public void setBattery(String stringBattery) {if (mTime != null && mBattery != null) {mBatteryPercent.setText(stringBattery + "%");int battery = Integer.valueOf(stringBattery);if (battery < 15)mBattery.setImageDrawable(getResources().getDrawable(R.drawable.media_controller_battery_15));if (battery < 30 && battery >= 15)mBattery.setImageDrawable(getResources().getDrawable(R.drawable.media_controller_battery_15));if (battery < 45 && battery >= 30)mBattery.setImageDrawable(getResources().getDrawable(R.drawable.media_controller_battery_30));if (battery < 60 && battery >= 45)mBattery.setImageDrawable(getResources().getDrawable(R.drawable.media_controller_battery_45));if (battery < 75 && battery >= 60)mBattery.setImageDrawable(getResources().getDrawable(R.drawable.media_controller_battery_60));if (battery < 90 && battery >= 75)mBattery.setImageDrawable(getResources().getDrawable(R.drawable.media_controller_battery_75));if (battery > 90)mBattery.setImageDrawable(getResources().getDrawable(R.drawable.media_controller_battery_90));}}private void toggleMediaControlsVisiblity() {if (isShowing()) {hide();} else {show();}}private void playOrPause() {if (mVideoView != null)if (mVideoView.isPlaying()) {mVideoView.pause();} else {mVideoView.start();}}}

2 LiveMediaController加载的布局文件:

<?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"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="40dp"android:background="#77000000"><ImageButtonandroid:id="@+id/media_controller_top_back"android:layout_width="50dp"android:layout_height="match_parent"android:layout_alignParentLeft="true"android:background="@null"android:src="@drawable/media_controller_go_back" /><TextViewandroid:id="@+id/media_controller_current_time"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_centerVertical="true"android:layout_marginRight="5dp"android:text="17:22"android:textColor="#ffffff"android:textSize="15sp" /><ImageViewandroid:id="@+id/media_controller_battery"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginRight="5dp"android:layout_toLeftOf="@+id/media_controller_current_time"android:gravity="center_vertical"android:src="@drawable/media_controller_battery" /><TextViewandroid:id="@+id/media_controller_battery_percent"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginRight="-3dp"android:layout_toLeftOf="@+id/media_controller_battery"android:gravity="center_vertical"android:text="45%"android:textColor="@color/white"android:textSize="15sp" /></RelativeLayout><RelativeLayoutandroid:id="@+id/volume_rlt"android:layout_width="150dp"android:layout_height="75dp"android:layout_centerInParent="true"android:background="@drawable/media_controller_volumn_bg"android:orientation="horizontal"android:padding="0dip"android:visibility="gone"><ImageViewandroid:id="@+id/media_controller_volumn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:src="@drawable/media_controller_volumn" /><TextViewandroid:id="@+id/media_controller_volumn_percent"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignBottom="@+id/media_controller_volumn"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:text="32:22/45:00"android:textColor="@color/white"android:textSize="10sp"android:visibility="gone" /></RelativeLayout><RelativeLayoutandroid:id="@+id/media_controller_live_progress"android:layout_width="match_parent"android:layout_height="50dp"android:layout_alignParentBottom="true"android:background="#77000000"><ImageButtonandroid:id="@+id/mediacontroller_play_pause"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_marginLeft="5dp"android:background="@drawable/mediacontroller_button"android:contentDescription="@string/mediacontroller_play_pause"android:src="@drawable/mediacontroller_pause" /><TextViewandroid: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="5dp"android:layout_toRightOf="@id/mediacontroller_play_pause"android:text="33:33:33" /><TextViewandroid: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="5dp"android:text="33:33:33" /><SeekBarandroid: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>

3 直播Activity:

package com.xi.liuliu.topnews.activity;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Window;
import android.view.WindowManager;import com.xi.liuliu.topnews.R;
import com.xi.liuliu.topnews.controller.LiveMediaController;
import com.xi.liuliu.topnews.dialog.LoadingDialog;import java.text.SimpleDateFormat;
import java.util.Date;import io.vov.vitamio.MediaPlayer;
import io.vov.vitamio.widget.VideoView;public class LiveActivity extends AppCompatActivity {private VideoView mVideoView;private LiveMediaController mMediaController;private static final int MESSAGE_TIME = 10010;private static final int MESSAGE_BATTERY = 10011;private LiveTimer mLiveTimer;private LoadingDialog mLoadingDialog;private static final String TAG = "LiveActivity";private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MESSAGE_TIME:mMediaController.setTime(msg.obj.toString());break;case MESSAGE_BATTERY:mMediaController.setBattery(msg.obj.toString());break;}}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);int flag = WindowManager.LayoutParams.FLAG_FULLSCREEN;Window window = LiveActivity.this.getWindow();window.setFlags(flag, flag);if (!io.vov.vitamio.LibsChecker.checkVitamioLibs(this))return;setContentView(R.layout.activity_live);if (mLoadingDialog == null) {mLoadingDialog = new LoadingDialog(this).setCancelable(true).setLoadingMessage("已经缓冲0%");}mLoadingDialog.show();//初始化时,就显示LoadingDialogString liveUrl = getIntent().getStringExtra("live_url");mVideoView = (VideoView) findViewById(R.id.video_view_live_activity);mVideoView.setVideoPath(liveUrl);mMediaController = new LiveMediaController(this, mVideoView, this);mVideoView.setMediaController(mMediaController);mVideoView.setBufferSize(500 * 1024);//0.5MB缓冲区mVideoView.setVideoQuality(MediaPlayer.VIDEOQUALITY_HIGH);mVideoView.setOnInfoListener(new MediaPlayer.OnInfoListener() {@Overridepublic boolean onInfo(MediaPlayer mp, int what, int extra) {switch (what) {case MediaPlayer.MEDIA_INFO_BUFFERING_START:if (mLoadingDialog == null) {//播放过程中,网络卡,缓冲时,显示LoadingDialogmLoadingDialog = new LoadingDialog(getApplicationContext()).setCancelable(true).setLoadingMessage("已经缓冲0%");mLoadingDialog.show();} else {if (!mLoadingDialog.isShowing()) {mLoadingDialog.show();}}mp.pause();break;case MediaPlayer.MEDIA_INFO_BUFFERING_END:mLoadingDialog.dissmiss();mp.start();break;case MediaPlayer.MEDIA_INFO_DOWNLOAD_RATE_CHANGED:Log.i(TAG, "当前网速:" + extra + "kb/s");break;}return true;}});mVideoView.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {@Overridepublic void onBufferingUpdate(MediaPlayer mp, int percent) {mLoadingDialog.setLoadingMessage("已经缓冲" + percent + "%");}});mMediaController.show(5000);mVideoView.requestFocus();registerBoradcastReceiver();if (mLiveTimer == null) {mLiveTimer = new LiveTimer();}mLiveTimer.start();}@Overridepublic void onConfigurationChanged(Configuration newConfig) {if (mVideoView != null) {mVideoView.setVideoLayout(VideoView.VIDEO_LAYOUT_SCALE, 0);}super.onConfigurationChanged(newConfig);}@Overrideprotected void onDestroy() {super.onDestroy();if (mLiveTimer != null && !mLiveTimer.isInterrupted()) {mLiveTimer.interrupt();mLiveTimer = null;Log.i(TAG, "mLiveTimer interrupt");}if (mVideoView != null) {mVideoView.stopPlayback();//停止播放,并释放资源}try {unregisterReceiver(batteryBroadcastReceiver);} catch (IllegalArgumentException ex) {}}private BroadcastReceiver batteryBroadcastReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {int level = intent.getIntExtra("level", 0);int scale = intent.getIntExtra("scale", 100);Message msg = new Message();msg.obj = (level * 100) / scale + "";msg.what = MESSAGE_BATTERY;mHandler.sendMessage(msg);}}};public void registerBoradcastReceiver() {IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);registerReceiver(batteryBroadcastReceiver, intentFilter);}class LiveTimer extends Thread {@Overridepublic void run() {// TODO Auto-generated method stubwhile (true) {SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");String str = sdf.format(new Date());Message msg = new Message();msg.obj = str;msg.what = MESSAGE_TIME;mHandler.sendMessage(msg);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}
}

4 LiveActivity加载的布局:

<?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.VideoViewandroid:id="@+id/video_view_live_activity"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_centerHorizontal="true"android:layout_centerVertical="true" />
</RelativeLayout>

Android中Vitamio使用解析-电视台直播为例相关推荐

  1. Android中XML数据解析

    转载请注明出处:http://blog.csdn.net/yegongheng/article/details/38296207 XML初步 今天我们来学习另一种非常重要的数据交换格式-XML.XML ...

  2. Android中Json数据解析

    Android学习系列(20)--App数据格式之解析Json (很基本基础的入门,对json的基础讲的很好) http://my.eoe.cn/874311/archive/1936.html An ...

  3. Android JSONObject – Android中的JSON解析

    Android JSONObject is used for JSON parsing in android apps. In this tutorial we'll discuss and impl ...

  4. android Java开发设计模式及在android中的应用解析

    android Java开发设计模式及在android中的应用解析 什么是设计模式: 可以用一句话概括设计模式---设计模式是一种利用OOP的封闭.继承和多态三大特性,同时在遵循单一职责原则.开闭原则 ...

  5. Android中Vitamio视频框架学习

    概述 开发公司一个乐视TV项目时,本来有个播放视频广告的功能,到最后不了了之.虽然没有在项目中做要求,但是这个点子还是激起了我研究多媒体的好奇心.刚好后面遇到一款比较喜欢的视频APP魔力盒,上面视频播 ...

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

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

  7. Android 中的Json解析工具fastjson 、序列化、反序列化

    Android中通常需要访问服务器,然而服务器返回的数据很多时候都是Json格式 1.fastjson简介 阿里巴巴FastJson是一个Json处理工具包,包括"序列化"和&qu ...

  8. Android中的JSON解析方式:json; Gson ; Fastjson

    本文主要介绍Json数据的解析 ----a,json数据的介绍 ----b,json数据的解析 ----c,gson数据的解析,谷歌公司的一种格式 ----d,fastjson数据的解析,阿里巴巴的一 ...

  9. Android中使用apk-parser解析apk

    一.前言 Apk Parser是一个优秀的解码二进制文件与获取apk各种信息的开源库,具备众多实用的特性: 获取apk各种元数据信息,比如应用名.图标.包名.版本号等 解析二进制XML文件并将其转换为 ...

最新文章

  1. 移动应用发展远超Web 谷歌苹果将主导世界?联网的发展才刚刚开始
  2. 干货 | 图解 https 单向认证和双向认证!
  3. anddroid异常处理之UncaughtException
  4. eclipse无法创建java虚拟机_2020年哪些IDE是最适合Java开发人员的?
  5. 设计模式(六)------设计模式六大原则(5):迪米特法则
  6. Halcon例程(基于多个标定图的单目相机标定)详解—— Camera_calibration_multi_image.hdev
  7. Android官方开发文档Training系列课程中文版:通知用户之在通知中显示进度
  8. 【ElasticSearch】Es 源码之 SearchTransportService 源码解读
  9. 【LeetCode】49. Group Anagrams
  10. 28.类型提示的实现
  11. 【腾讯内部干货分享】分析Dalvik字节码进行减包优化
  12. vue实现60秒倒计时
  13. oracle 人民币符号,人民币的符号的正确表示法?一杠?两杠?
  14. 主引导记录MBR详解
  15. JDK版本对应其major.minor version,看这一篇就够啦(附java历史版本下载地址)
  16. Zero-Shot Learing与Attention Machinism
  17. 京东登陆界面(静态)
  18. nacos的配置管理
  19. 简易的应变测量系统实现(一) 直流放大器
  20. 中国的女人到底有多好色?

热门文章

  1. 计算机应届毕业生必须要培训吗?
  2. 模糊字符串匹配:双音素算法
  3. MMDetection3d对KITT数据集的训练与评估介绍
  4. 优化着色器信息加载,或查看Yer数据!
  5. MySql CHECK使用方法
  6. 第4章第10节:如何制作一个模拟手机解锁的动画 [SwiftUI快速入门到实战]
  7. OOP_多态(C#)
  8. 基于单片机智能安全服药提醒药盒系统设计(毕设资料)
  9. html右侧有白边,html5有白边解决办法
  10. devexpress表格控件gridcontrol设置隔行变色、焦点行颜色、设置(改变)显示值、固定列不移动(附源码)...