In Part 1 of this series, we developed a simple video player using Android’s VideoView, and in Part 2 we improved upon it by adding media controls to enable users to rewind, fast forward, pause and resume video. When testing the application, it’s easy to see there are still some loose ends to tie up in order to ensure a great user experience.
Why does the video restart when the orientation changes?
Run the application as it is, and as the video is playing change the device orientation. What do you notice? The video starts over from the beginning. This is annoying, right? I personally think so. It would be ideal to have the video pick up from where it left off when the user rotates the device. Also, what will happen if a phone call comes in and the application is moved to the background? When the user returns, the video restarts from the beginning. Again, the user is expecting that the video picks up from where it left off when returning to the application. So how do we accomplish that?
Activity provides an override method, OnSaveInstanceState, which allows you to store the current state of the activity before it is destroyed and recreated through the actions we discussed above. OnSaveInstanceState provides a Bundle which we can use to add in values that we will use to restore the activity’s state when it is recreated. In this case, we will use this method to check if a video is playing, and store its current playback position in the Bundle. This is straightforward since the VideoView exposes properties, IsPlaying and CurrentPosition, which makes light work of this:
Now, we need to retrieve that value from the Bundle when the Activity is recreated and when the application is restored. We can do this within the OnCreate and OnRestoreInstanceState methods respectively.
Notice that we also ensure that the video player is launched when the application is resuming from the background.
Now that we have a starting position for the playback to resume from, we will pass it into the VideoView’s SeekTo method, which sets the current position of the video. Note that the time is in milliseconds. We still need to call the VideoView’s Start method to trigger the playback. The following lines must be added to the LaunchVideo method:
How can I show an indicator while the video is loading?
While testing out the application, you may have noticed there is a delay within the application as the video is loading, moreso because we are loading from a URL. Ideally, we want to display a progress indicator until the video is loaded and ready to play. This will provide a better user experience rather than just displaying a blank screen. We will add a ProgressBar to the layout, which will display by default and then will be removed from the view when the video is ready.
In the Activity’s layout file, add the ProgressBar to the layout, after the VideoView, as follows:
Next, we need to obtain a handle to the ProgressBar in the Activity’s code file, just as we did with the video player and media controller. While I’m at it, I’m going to refactor the code to move these calls to a private method, called InitializeVideoPlayer, which will be called from the OnStart method rather than from OnCreate. This will ensure we will retrieve a handle to the controls even when our app is resumed from being placed in the background.
Now that we have a handle to the ProgressBar, this allows us to set the its Visibility to appear whenever the Activity’s orientation changes (ie. when the user rotates the device to view the video in either portrait or landscape mode), and to disappear when the video is ready to play.
Since we want to hide the ProgressBar when the video is ready to play, we can make use of the OnVideoPlayerPrepared event handler. Within this event, set the ProgressBar’s Visibility state to ViewStates.Gone as follows:
videoProgressBar.Visibility = ViewStates.Gone;
If you’re wondering why we are using Gone instead of Invisible, it has to do with a difference in the way the layout space is handled when the view is hidden. The ViewStates.Gone value will ensure that the ProgressBar does not take up any layout space when hidden, whereas ViewStates.Invisible will still continue to take up the layout space when hidden.
Finally, we want to ensure the ProgressBar is displayed when the orientation changes, we can override the OnConfigurationChanged event and set the ProgressBar’s Visibility as follows:
videoProgressBar.Visibility = ViewStates.Visible;
In this post, we improved upon our basic VideoPlayer application by adding a progress indicator as the video reloads when the device is rotated, and ensuring that the video playback resumes at the same position it left off.
Since our application depends on a network connection, we need to perform due diligence and verify that the device is connected to the carrier network or WiFi before attempting to load the video. In this way, we can display a relevant error message when no connection is present. In my next post, we will build on this example and include the proper checks to handle cases where no network connection is present, as well as how to listen for changes in the network connection while the application is running.
Source: GeekswithBlogs – Lori Lalonde