使用GSYVideoPlayer增加显示实时网速
先看效果图
问题来源
项目中接入了这个视频播放框架,GitHub中start中相对比较多,作者修复的频率不低,每层可扩展性高,果断接入。在做项目的时候发现播放器在加载视频的时候只有一个Loading加载动画,并没有显示网速或者百分比,用户体验较差,参考了作者的几个demo中,都没有显示实时网速的功能。查阅他的文档,有发现到player中ExoPlayer内核有提供getNetSpeedText()方法来获取实时的网速,有能获取网速的接口就好办了。
解决思路
- 自定义播放器UI在加载动画下方增加一个TextView来显示实时网速
- 查询开始缓冲中的回调
- 重写在开始缓冲中的回调 开启一个定时任务去获取网速再显示更新到UI上
- 查询缓冲结束或者准备播放的回调
- 重写在缓冲结束的时候关闭查询网速的定时任务
思路有了,那么就是实际的代码操作了
//继承标准的播放器
public class SampleCoverVideo extends StandardGSYVideoPlayer {}
//重写getLayoutId 设置自定义的布局
@Override
public int getLayoutId() {
return R.layout.video_layout_cover;
}
//布局的xml 在动画下面加上显示网速的文本框就好了
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center">
<moe.codeest.enviews.ENDownloadView
android:id="@+id/loading"
android:layout_width="28dp"
android:layout_height="28dp"
android:visibility="invisible" />
<TextView
android:id="@+id/tv_netSpeed"
android:visibility="invisible"
android:textColor="@color/colorWhite"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
//重写init方法 在init方法中findviewbyid
tvNetSpeed=(TextView)findViewById(R.id.tv_netSpeed);
//重写缓冲中显示缓冲布局的方法
protected void changeUiToPlayingBufferingShow() {
super.changeUiToPlayingBufferingShow();
//显示网速控件
setViewShowState(tvNetSpeed,VISIBLE);
//定时任务1秒钟获取实时网速,显示在UI上
disposable=Observable.interval(0, 1000, TimeUnit.MILLISECONDS)
.map(new Function<Long, String>() {
@Override
public String apply(Long aLong) throws Exception {
return getNetSpeedText();//获取网速的方法
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
//在主线程更新UI
tvNetSpeed.setText(s);
}
});
}
//重写正在播放显示播放中的布局的方法
protected void changeUiToPlayingShow() {
super.changeUiToPlayingShow();
//隐藏网速
setViewShowState(tvNetSpeed,INVISIBLE);
//取消定时任务
closeNetSpeedDisposable();
}
//写个取消任务的方法,记得在这个播放器的生命周期中最后也要执行这个方法取消任务,不然会导致内存泄露哦
private void closeNetSpeedDisposable(){
if (disposable!=null && !disposable.isDisposed()) {
disposable.dispose();
}
}
我设置的是Exo2Player内核,根据getNetSpeedText扒拉下去看,发现是使用TrafficStats类来获取应用当前网速的,这个类是流量监控的类。这边原理是根据两次接收数据总量的差除以两次接收时间差来算出网速的。如果使用其他播放器内核没有获取网速的方法,你可以参考这个方法来实现他。来,咱们看看具体实现方法我给加上注释:
private long getNetSpeed(Context context) {
//这里的context是获取getApplicationContext的
if (context == null) {
return 0;
}
//先使用getUidRxBytes方法获取该进程总接收量,如果没获取到就把当前接收数据总量设置为0,否则就获取接收的总流量并转为kb
long nowTotalRxBytes = TrafficStats.getUidRxBytes(context.getApplicationInfo().uid) == TrafficStats.UNSUPPORTED ? 0 : (TrafficStats.getTotalRxBytes() / 1024);//转为KB
//记录当前的时间
long nowTimeStamp = System.currentTimeMillis();
//上一次记录的时间-当前记录时间算出两次记录的时间差
long calculationTime = (nowTimeStamp - lastTimeStamp);
//如果时间差不变,直接返回0
if (calculationTime == 0) {
return calculationTime;
}
//两次的数据接收量的差除以两次数据接收的时间,就计算网速了。这边的时间差是毫秒,咱们需要转换成秒。
long speed = ((nowTotalRxBytes - lastTotalRxBytes) * 1000 / calculationTime);
//当前时间存到上次时间这个变量,供下次计算用
lastTimeStamp = nowTimeStamp;
//当前总接收量存到上次接收总量这个变量,供下次计算用
lastTotalRxBytes = nowTotalRxBytes;
return speed;
}
这种计算网速方式,需要时间的间隔越小,实时网速越准确。
好了 代码基本就是这样了。只要熟悉播放器的各个回调,就可以自定义在什么时候显示什么内容了
先发到掘金的,现在移到简书来