版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jhl122/article/details/76491178
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