您的位置:首页 > 移动开发 > Android开发

Android中Vitamio使用解析-电视台直播为例

2017-07-12 18:21 204 查看
先上图,在Android中使用Vitamio播放香港卫视:



第一步,AndroidStudio中导入Vitamio

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:

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

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());
}

@Override
protected 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() {
@Override
public 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;
}

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
return true;
}

@Override
public 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 {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}

@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
toggleMediaControlsVisiblity();
return super.onSingleTapConfirmed(e);
}

@Override
public boolean onDown(MotionEvent e) {
return true;
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return super.onScroll(e1, e2, distanceX, distanceY);
}

@Override
public 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">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp"

d66f
android:background="#77000000">

<ImageButton
android: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" />

<TextView
android: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" />

<ImageView
android: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" />

<TextView
android: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>

<RelativeLayout
android: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">

<ImageView
android: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" />

<TextView
android: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>

<RelativeLayout
android:id="@+id/media_controller_live_progress"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:background="#77000000">

<ImageButton
android: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" />

<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="5dp"
android:layout_toRightOf="@id/mediacontroller_play_pause"
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="5dp"
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>

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() {
@Override
public 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;
}
}
};

@Override
protected 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();//初始化时,就显示LoadingDialog
String 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() {
@Override
public boolean onInfo(MediaPlayer mp, int what, int extra) {
switch (what) {
case MediaPlayer.MEDIA_INFO_BUFFERING_START:
if (mLoadingDialog == null) {
//播放过程中,网络卡,缓冲时,显示LoadingDialog
mLoadingDialog = 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() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
mLoadingDialog.setLoadingMessage("已经缓冲" + percent + "%");
}
});
mMediaController.show(5000);
mVideoView.requestFocus();
registerBoradcastReceiver();
if (mLiveTimer == null) {
mLiveTimer = new LiveTimer();
}
mLiveTimer.start();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
if (mVideoView != null) {
mVideoView.setVideoLayout(VideoView.VIDEO_LAYOUT_SCALE, 0);
}
super.onConfigurationChanged(newConfig);
}

@Override
protected 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() {
@Override
public 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 {
@Override
public void run() {
// TODO Auto-generated method stub
while (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.VideoView
android: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