Playing video in Android with VideoView and MediaController
Mobile video has become a default expectation for Android apps across Australia, whether you are building a sports replay tool for the A-League, an educational app for TAFE, or a streaming client for local creators. The platform's stock widgets, VideoView and MediaController, give developers a quick path to a working player without pulling in third-party libraries or writing a custom media engine.
This walkthrough shows how to set up playback from local resources, remote URLs and assets, while covering the event listeners and XML attributes that matter in real projects. The goal is a reliable playback layer you can drop into a list screen, a detail page or a fragment, the kind of component you would find in many of the sample projects hosted on myeasyprojects.net.
How VideoView and MediaController work
VideoView is a thin wrapper around SurfaceView and MediaPlayer that handles rendering, focus and lifecycle for you. It exposes simple methods like setVideoURI, start, pause and seekTo, which keeps the API approachable for beginners building their first media feature.
MediaController is the floating overlay that shows play, pause, scrub and elapsed time. It does not contain playback logic on its own; it forwards taps to whatever MediaPlayerControl implementation is supplied. The cleanest pattern is to call setMediaController on the VideoView and then call show on the controller whenever playback state changes. The default controller already covers the controls most users in Melbourne, Brisbane or Perth expect, including a draggable scrubber that updates as the clip plays.
Adding VideoView to your layout
The XML setup is straightforward and only requires a few attributes to behave well on phones sold in Australia, where 18:9 and 19.5:9 aspect ratios are common. A typical block declares match_parent for width and a fixed height, then enables hardware acceleration at the view level. Centring the view keeps the player stable when the device rotates, which matters if you are following patterns shown in tutorials like the listview index guide where layout responsiveness is a recurring theme.
The widget inherits from SurfaceView, so any z-ordering or overlay you draw above it must use the right translationZ value. Wrapping the VideoView inside a FrameLayout is a common choice when you want to layer a buffering spinner, an error image or an Australian-language "Tap to retry" prompt above the surface.
Choosing a video source
VideoView accepts URIs from res/raw, the assets folder, content providers and remote http or https endpoints. Each source has trade-offs that matter in different scenarios, particularly when you account for the variable latency of the NBN and 4G networks used by Australian households.
| Source | Best Use | Offline Capable | Build Size Impact |
|---|---|---|---|
| res/raw | Short demo clips, splash videos | Yes | Increases APK weight |
| assets folder | Bundled tutorials, sample footage | Yes | Increases APK weight |
| Remote URL | Live streams, Stan-style libraries | No | No APK impact |
| Content Provider | DRM-protected streams | Depends | No APK impact |
If you are building a regional news app for outlets like the ABC, remote URLs are usually the right call, since you want to push updates without shipping a new APK. For a quiz app aimed at HSC or VCE students, bundled assets guarantee a smooth experience on regional school networks where connectivity is patchy. Content providers are the right choice when you need DRM, which suits paid services that follow ACMA guidelines for content classification.
Loading and preparing the clip
In your Activity or Fragment, grab the VideoView with findViewById, attach a MediaController and call setVideoURI or setVideoPath. After that, register an OnPreparedListener to start playback the moment the buffer is ready, which feels much more responsive on entry-level devices like the Nokia handsets Telstra stocks in its prepaid range.
A small Australian-friendly touch is to respect the system dark theme by reading the night qualifier before instantiating the controller. The stock MediaController picks up some accents automatically, but you can force a dark background for users who have enabled dark mode on their Pixel or Samsung handsets.
Listening for playback events
Three listeners cover most of what you need during real-world use. OnPreparedListener signals that buffering is complete and playback can begin. OnErrorListener reports media errors, including unsupported codecs and network failures, which are common when users stream on patchy Telstra or Optus connections in regional Queensland. OnCompletionListener lets you trigger a follow-up action, such as loading the next episode of a series or returning to a previous list.
Wire each one before calling prepareAsync or start, and use the WHAT_EXTRA_CODE constants returned in OnErrorListener to log meaningful diagnostics. Australian developers working under ACMA guidelines should also surface a polite error message in plain English rather than a raw code, particularly when the failure is content-policy related.
Polishing the player experience
Once the basics work, you can move beyond the stock controller by hiding system controls, capturing audio focus and pausing playback when the user receives a call. These small refinements separate a hobby project from something that feels professional, and they are the same touches found in apps like Kayo Sports or Binge that millions of Australians use every weekend.
For longer-term projects, evaluate ExoPlayer as a successor to VideoView. ExoPlayer supports HLS, DASH and adaptive bitrates out of the box, which suits Australian audiences who often switch between home Wi-Fi, hotel networks and 5G mid-stream. Until you need those features, the built-in widgets remain the right tool for prototypes, classroom apps and the kinds of side projects featured on tutorial sites.
Helpful habits for ship-ready playback
- Keep clips under 1080p when shipping in res/raw to control APK size.
- Use setOnTouchListener to dismiss the MediaController after a short delay.
- Request android.permission.INTERNET only when streaming remote media.
- Restore the playback position in onSaveInstanceState for smoother rotations.
Things that catch first-time developers
- Prefer MP4 with H.264 for the broadest Australian device support.
- Test on a low-end Telstra Blue Tick device to catch lag early.
- Avoid setKeepScreenOn unless playback is genuinely full-screen.
- Use Surface type "texture" when overlaying custom controls.