切换活动时,VideoView会丢失缓冲部分

时间:2015-05-29 09:01:17

标签: java android reflection android-videoview

我希望保留在VideoView中播放的视频的缓冲部分。我发现VideoView SurfaceDestroyed release(true);mMediaPlayer次调用,导致根据此问题释放SurfaceHolder.Callback个实例 VideoView onResume loses buffered portion of the video

我不想破解内部API,因此我决定重写mSHCallback并将其替换为release(true);字段,以避免使用反射调用VideoView.start()

但是当我在SurfaceCreated覆盖中调用package com.tirkx.aos; import android.util.Log; import android.widget.MediaController; import android.media.MediaPlayer; import android.view.SurfaceHolder; import android.widget.VideoView; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; public class CustomVidViewCallbackLoader implements SurfaceHolder.Callback { private final String TAG = "CustomCallbackLoader"; private Map<String, Field> PrivateFields; private Map<String, Method> PrivateMethods; private VideoView VideoView; boolean VideoOpened; public CustomVidViewCallbackLoader(VideoView videoView) { VideoView = videoView; PrivateFields = new HashMap<String, Field>(); PrivateMethods = new HashMap<String, Method>(); Class VideoViewClass = videoView.getClass(); //Reflection things try { PrivateFields.put("mSHCallback", VideoViewClass.getDeclaredField("mSHCallback")); PrivateFields.put("mSurfaceHolder", VideoViewClass.getDeclaredField("mSurfaceHolder")); PrivateFields.put("mMediaController", VideoViewClass.getDeclaredField("mMediaController")); PrivateFields.put("mMediaPlayer", VideoViewClass.getDeclaredField("mMediaPlayer")); PrivateFields.put("mSurfaceWidth", VideoViewClass.getDeclaredField("mSurfaceWidth")); PrivateFields.put("mSurfaceHeight", VideoViewClass.getDeclaredField("mSurfaceHeight")); PrivateFields.put("mTargetState", VideoViewClass.getDeclaredField("mTargetState")); PrivateFields.put("mVideoWidth", VideoViewClass.getDeclaredField("mVideoWidth")); PrivateFields.put("mVideoHeight", VideoViewClass.getDeclaredField("mVideoHeight")); PrivateFields.put("mSeekWhenPrepared", VideoViewClass.getDeclaredField("mSeekWhenPrepared")); PrivateMethods.put("openVideo", VideoViewClass.getDeclaredMethod("openVideo")); for(Map.Entry<String, Method> m : PrivateMethods.entrySet()) m.getValue().setAccessible(true); for(Map.Entry<String, Field> f : PrivateFields.entrySet()) f.getValue().setAccessible(true); } catch(Exception ex) { ex.printStackTrace(); } try { SurfaceHolder.Callback SHCallback = (SurfaceHolder.Callback) PrivateFields .get("mSHCallback").get(videoView); if (SHCallback != null) { videoView.getHolder().removeCallback(SHCallback); PrivateFields.get("mSHCallback").set(videoView, this); videoView.getHolder().addCallback((SurfaceHolder.Callback) PrivateFields .get("mSHCallback").get(videoView)); } } catch(Exception ex) { ex.printStackTrace(); } } @Override public void surfaceCreated(SurfaceHolder holder) { try { PrivateFields.get("mSurfaceHolder").set(VideoView, holder); if(!VideoOpened) { PrivateMethods.get("openVideo").invoke(VideoView); VideoOpened = true; } else { VideoView.start(); } } catch(Exception ex) { ex.printStackTrace(); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { try { //PrivateFields.get("mSurfaceHolder").set(VideoView, holder); int mVideoWidth = (int) PrivateFields.get("mVideoWidth").get(VideoView); int mVideoHeight = (int) PrivateFields.get("mVideoHeight").get(VideoView); int mTargetState = (int) PrivateFields.get("mTargetState").get(VideoView); int mSeekWhenPrepared = (int) PrivateFields.get("mSeekWhenPrepared").get(VideoView); MediaPlayer mMediaPlayer = (MediaPlayer) PrivateFields.get("mMediaPlayer").get(VideoView); PrivateFields.get("mSurfaceWidth").set(VideoView, width); PrivateFields.get("mSurfaceHeight").set(VideoView, height); boolean isValidState = (mTargetState == 3); boolean hasValidSize = (mVideoWidth == width && mVideoHeight == height); if(mMediaPlayer != null && isValidState && hasValidSize) { if(mSeekWhenPrepared != 0) VideoView.seekTo(mSeekWhenPrepared); VideoView.start(); } } catch(Exception ex) { ex.printStackTrace(); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { try { PrivateFields.get("mSurfaceHolder").set(VideoView, null); MediaController mediaController = (MediaController) PrivateFields.get("mMediaController") .get(VideoView); if(mediaController != null) mediaController.hide(); VideoView.pause(); } catch(Exception ex) { ex.printStackTrace(); } } public void setMediaPlayerOnBufferedChanged(MediaPlayer mediaPlayer) { if (mediaPlayer != null) { mediaPlayer.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() { @Override public void onBufferingUpdate(MediaPlayer mp, int percent) { Log.i(TAG, "-->" + percent); } }); } } } 时似乎很奇怪,我有多次“无法播放此视频”消息,但音频会一直播放到最后切换到其他活动。

这是我的自定义回调

Int32

0 个答案:

没有答案