您的位置:首页 > 理论基础 > 计算机网络

surfaceview+mediaplayerview实现本地网络视频播放

2017-08-01 11:11 731 查看
GitHub地址:https://github.com/JiangAndroidwork/MyMediaPlayer

具体的代码请在github上面查看,我主要记录一下踩过的坑,需要注意的地方。

需要注意的SurfaceHolder.getHolder.addCallback(this)的回调方法surfaceCreated()、surfaceDestoryed()生命周期,surfaceCreated()是初始化的时候加载的,mediaplayerview也是在这个方法内进行创建。当手机按home键返回桌面的时候会调用 surfaceDestoryed()方法,当再点击应用进入播放页面的时候会再次调用surfaceCreated方法,所以有的时候要注意避免方法的重复调用,当再次进入应用的时候要判断mediplayer是否为null,如果为null就是第一次进入执行创建方法,当不为null的时候就不需要创建mediaplayer,直接执行seekTo()
和start()方法即可。
有关Timer 和TimerTask的使用,我是用Timer来实时更新播放的进度条和时间显示,所以在使用的时候要注意timer的创建和cancel,当执行surfaceDestoryed()或者退出界面的时候需要及时的cancel并且将timer置为null,释放资源,也为了保证不出现异

在mediaplayer的prepera方法完成之前最好不要点击播放按钮和进度条,所以就要设定setEnable(false),当完成了之后再setEnable(true)。但是有一个问题,那就是surfaceHolder.callBack(this)回调方法surfaceCreated(),当点击home回到桌面 再点击进入应用还是会调用这个方法的,所以 设定不能点击的方法不能放在surfaceCreated()里面,就会导致每次onResume的时候按钮还是不能点击,因为一般是先调用onResume然后才是surfaceCreated()方法。
网速显示实现原理:获取应用当前使用的流量大小减去1秒之前的流量大小除以这个时间差就是 单位时间的网速。

public class InternetUtils {

/**
* 获取流量
* @param context
* @return
*/
public static long getInternetSpeed(Context context){
long l = 0;
PackageManager pm = context.getPackageManager();
try {
ApplicationInfo ai = pm.getApplicationInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
//转为KB
l = TrafficStats.getUidRxBytes(ai.uid) == TrafficStats.UNSUPPORTED ? 0 : (TrafficStats.getTotalRxBytes() / 1024);

} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();

}
return l;
}

}

/**
* 显示网速
*/
private void showSpeed() {
long nowTotalRxBytes = InternetUtils.getInternetSpeed(context);
long nowTimeStamp = System.currentTimeMillis();
long speed = ((nowTotalRxBytes - lastTotalRxBytes) * 1000 / (nowTimeStamp - lastTimeStamp));//毫秒转换

lastTimeStamp = nowTimeStamp;
lastTotalRxBytes = nowTotalRxBytes;

Message msg = handler.obtainMessage();
msg.what = 100;

if (speed<1){
msg.obj = String.valueOf(speed*1024)+"B/s";
}else if (speed>=1024){
msg.obj = String.valueOf((float) speed/1024).substring(0,3)+"Mb/s";
}else {
msg.obj = String.valueOf(speed) + " kb/s";
}

handler.sendMessage(msg);//更新界面
}

缓冲百分比的实现

首先mediaplayer有个监听方法用来实现整个视频的缓冲百分比:setOnBufferingUpdateListener(this),我是自己设定一个充盈区z,用缓冲好的部分减去当前播放的位置得出的大小 y 和充盈区去比较,当大于充盈区的时候就不用缓冲直接播放,当小于缓冲区的时候直接暂停缓冲,并且缓冲百分比 x 直接用:y/100% = y/x 得出实时的百分比。

@Override
public void onBufferingUpdate(MediaPlayer mediaPlayer, int i) {
mediaplayerPercentage = i;
setLoadingValue = (float) (videoLength * 0.07);//设置充盈区百分比为百分之7
currentPosition = mediaPlayer.getCurrentPosition();
mediaplayerLoading = (videoLength * i) / 100;
y = mediaplayerLoading - currentPosition;
if (y < setLoadingValue) {//如果差值小于 设定的缓存值 则是缓冲状态
//当 mediaplayer的缓冲百分比为100%时就不用考虑自定义缓冲进度,直接隐藏直接显示按钮
if (i==100){
if (this.getVisibility()==GONE) {this.setVisibility(VISIBLE);}
if (ivPlayer.getVisibility()==GONE) ivPlayer.setVisibility(VISIBLE);
if (tvShowPercentage.getVisibility()==VISIBLE) tvShowPercentage.setVisibility(GONE);
if (progressBar.getVisibility()==VISIBLE) progressBar.setVisibility(GONE);
if (tvInternetSpeed.getVisibility()==VISIBLE) tvInternetSpeed.setVisibility(GONE);
}else {
initLoading();

}
} else if (y>=setLoadingValue&&PlayerContent.PLAY_STATE==1){

initPause();

}else if (PlayerContent.PLAY_STATE==0){
initPlaying();
}
float v =  (currentPosition / videoLength);
percentageOfLoading = (int) ((100*y)/setLoadingValue);

if (percentageOfLoading>100){
percentageOfLoading=100;
}else if (percentageOfLoading<0){
percentageOfLoading = 0;
}

tvShowPercentage.setText(percentageOfLoading +"%");
//        Log.i(TAG,"已经缓冲的大小=="+i+"\n"+"视频播放的百分比=="+v+"\n"+"设置的缓冲百分比=="+7);
initShowOrHind();
}

要注意mediaplayerview的一些状态 避免出现异常,比如,只有当prepared成功回调之后才能 start(),当播放完了之后要released()回收资源http://blog.csdn.net/u014434080/article/details/71305727
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: