I am having an Activity in which there is
VideoView -- Streams a video from a webserver.
Button -- Takes the user to the next activity to be shown.
When the application starts, VideoView is made to play the Video from a webserver.
Now assume
Total Video length is 60 Minutes
Current Video progress is 20 Minutes
Current Buffered progress 30 Minutes
Now when I click on the above mentioned Button which takes user to the next activity.
From that Activity if i press the back button, Previous Activity(with VideoView and Button) appears in front of the user. But when resumed all the Buffered Portion of the video is lost and hence the VideoView starts playing the video from the beginning which is really bad. <-- Actual Problem
Problem
When Activity is resumed back, the buffered portion of the video is lost and hence starts buffering it again. So how to overcome re-buffering the buffered portion of the Video ?
Even official Youtube android app. has the same problem.
Edit 1 :
I tried the below code in Activity but its not working.
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
videoView.suspend();
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
videoView.resume();
}
Can anyone guide me regarding this problem ?. Or am I missing something to make this work perfectly ?
Current Workaround
I have saved the current playing position of the video in onPause()
method and in onResume()
method I have used that position to seek the video to that duration. This works fine. But the video buffering starts from the beginning tho it starts the video from the seek position.
Any help is deeply appreciated.
Have you tried seekto()
I've spent several hours trying to hack the original VideoView source code and Now I can confirm VideoView can be hacked to behavior what you want - retain buffering after surface destroyed. I've tested on my Samsung Galaxy S2, which works as expected, in my case, the video buffering (streaming m4v video from remote http server) is successfully retained when I open a new activity and go back.
Basically, the workaround is create you own VideoView class (by copying the source code), and hack the SurfaceHolder.Callback() implementation. Bear in mind that VideoView use some internal/hide API, so if you want to create a copy of VideoView in your own project, you have to follow the inazaruk's article to enable using internal/hide API. As a quick hack, I just download inazaruk's build from here and use inazaruk-android-sdk-dbd50d4/platforms/android-15-internals/android.jar replace my original android.jar in my android-sdk/platforms/android-15/.
VideoView source code can be downloaded from GrepCode. Once you successfully create you own copy without compile error, change SurfaceHolder.Callback() to something like this:
And make sure you don't call videoView.resume(), videoView.setVideoURI(), videoView.suspend() and videoView.stopPlayback() explicitly in you MediaPlayerActivity like this:
Note that I have just done a dirty hack to prove the feasibility, You should design and implement your VideoView class properly to avoid any side-effect.
Update:
As an alternative, you should able to achieve same effect using plain MediaPlayer create your MediaPlayerActivity if you don't want to do the interal/hide API stuff You can start with the MediaPlayerDemo_Video.java in ApiDemos sample. The key point is make sure prepare (result buffering) and release method is properly handled in both SurfaceHolder Callback methods and Activity life cycle method to avoid prepare/release video every time surface is created/destroyed, and Activity is started,resumed/paused,stopped. I've created a dummy BufferedMediaPlayerActivity (highly simplified for posting here) which contains only key parts and can be used for quick demonstration, it doesn't have MediaController, however, you can check from Logcat to see that the buffer percentage is actually keep increasing instead of rolling over from 0 every time you open new activity and go back.
BufferedMediaPlayerActivity.java:
buffered_media_player.xml:
As the buffer is lost when the video view goes to the background(change in visibility), you should try blocking this behavior by overriding the
onWindowVisibilityChanged
method ofVideoView
. Call super only if the video view is becoming visible. May have side-effects.