Videos allow complex information to be presented to a user. This can just be a background, or it can be an information animation. Regardless of the exact reason, videos can enhance apps.
One of the simplest ways to display a video is to use a VideoView
instance, which wraps an underlying SurfaceView
and a MediaPlayer
:
VideoView
instance, using either code or the layout resources:<VideoView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:id="@+id/videoView" />
VideoView
from the layout:var videoView = FindViewById<VideoView>(Resource.Id.videoView);
VideoView
property, we can set the source of the video. This can either be from a remote source, or from a local resource, such as one of the app resources:var path = string.Format( "android.resource://{0}/{1}", PackageName, Resource.Raw.big_buck_bunny); videoView.SetVideoPath(path);
MediaController
instance:videoView.SetMediaController(new MediaController(this));
Start()
method:videoView.Start();
SeekTo()
method:videoView.SeekTo(position);
When the activity is recreated for some reason, for example following a rotate, we have to ensure that the player is returned to its previous position. These set of steps shows one way in which to preserve the playback position following an activity re-creation:
OnSaveInstanceState()
method and add the video player's state to the Bundle
object:outState.PutBoolean("isPlaying", videoView.IsPlaying); outState.PutInt("position", videoView.CurrentPosition);
OnCreate
, we restore the state from the Bundle
object:if (savedInstanceState != null) { if (savedInstanceState.GetBoolean("isPlaying", false)) { var pos = savedInstanceState.GetInt("position", 0); videoView.SeekTo(pos); } }
ConfigurationChanges
property of the [Activity]
attribute:[Activity( ..., ConfigurationChanges = ConfigChanges.Orientation)]
The ability to play a video in an app is very useful. We can just be providing a beautiful snippet as a background or header, or we can be playing a longer video as part of the app's core functionality.
Similar to playing audio, playing video is also straightforward. Instead of creating a MediaPlayer
object, we use a VideoView
control. The control can be created and added from code or it can be placed in the layout resource files.
Once we have the video view, we can set it up to play the video. All we need to do is set the location to the actual video that we want to play. To do this, we pass a string path to the SetVideoPath()
method or a URI to the SetVideoURI()
method. This location can be a local path, such as a resource or the local filesystem, or a remote path to a server. If we are using a URI, we can even provide additional headers in the request to the server.
As soon as we set the video source, the underlying media player will be automatically prepared. This means that we can invoke the Start()
method as soon as we wish to. The playback can be controlled using the Pause()
, Resume()
, and StopPlayback()
methods. We can also use the SeekTo()
method to jump to a specific location in the video.
We may choose to present media controls on a VideoView
but are not required to do so. These controls will allow the user to directly control the playback. They include: a seek bar, a play/pause button, and skip buttons. If the video is streamed, a buffer progress will also be shown. To display these controls, we can provide the view with an instance of MediaController
using the SetMediaController()
method.
If a VideoView
goes into the background or is destroyed, it will not restore its state when it is recreated, we have to do this manually. The simplest way is to record the states, for example IsPlaying
and CurrentPosition
, when the view is about to be destroyed. We can do this in the OnSaveInstanceState()
or OnPause()
methods, and then when the view is reconstructed, we can restore the state in the OnRestoreInstanceState()
or OnCreate()
methods.
If the device is rotated, the activity is usually destroyed and recreated. This presents a problem as the video will have to be prepared again and this may cause a delay in the playback. This is even more a problem when the video comes from a remote source, as it will have to buffer again.
Another way to get around this is to ensure that the activity is not destroyed when the device orientation changes. We add the ConfigChanges.Orientation
flag to the ConfigurationChanges
property on the [Activity]
attribute. By setting this property, the activity is not destroyed, but it also means that the usual orientation-specific layouts will not be switched automatically. We will now have to take care of this ourselves in the OnConfigurationChanged()
method of the activity.