Android SharedPreferences Tutorial and Example

Building Video Streaming Features with ExoPlayer in Android Apps

ExoPlayer has become the default media playback library for Android developers who need to stream video reliably across devices and network conditions. Unlike the older MediaPlayer API, ExoPlayer supports adaptive bitrate streaming, DRM, and modern formats out of the box. For anyone building a media-heavy application, learning how to use ExoPlayer for video streaming is an investment that pays off quickly.

Australian users consume more video on mobile than ever, whether they are catching Kayo Sports during a Friday night NRL match in Brisbane or streaming a Stan original while commuting on the Sydney train network. Because mobile plans in Australia often come with data caps and variable NBN speeds at home, the playback experience needs to handle fluctuating bandwidth gracefully. A well-configured ExoPlayer setup can adjust stream quality automatically and keep viewers watching without frustrating buffering pauses.

What ExoPlayer Is and How It Differs from MediaPlayer

ExoPlayer is an open source media player built on top of Android's lower-level media APIs, but it exposes a friendlier and more flexible interface. It was originally developed by Google and is now maintained as part of the AndroidX Media3 library. The architecture is modular, meaning you can swap in custom renderers, extractors, and data sources depending on what your application needs.

The main advantage of using ExoPlayer for video streaming is its native support for adaptive formats like DASH, HLS, and SmoothStreaming. These protocols allow the player to switch between quality levels on the fly, which matters greatly in a country where users stream from urban centres like Melbourne and Perth as well as regional towns with patchier connections. With MediaPlayer, you would have to write significant custom code to achieve the same behaviour.

Setting Up ExoPlayer in Your Android Project

Before you write any playback code, you need to add the right dependencies to your module-level build.gradle file. The current recommended packages are part of AndroidX Media3, so you include media3-exoplayer, media3-ui, and media3-dash if you plan to stream DASH content. After syncing Gradle, the classes become available across your project.

Your MainActivity or hosting Fragment needs a PlayerView in its layout XML file. This view renders video frames and overlays the default playback controls. Make sure the view has a fixed aspect ratio or use resizeMode attributes such as FIT or FILL to control how the video fills the available space. If you want to learn how to combine this with list-based interfaces, the side index listview example shows how a scrolling catalogue can be paired with a detail screen hosting the player.

Preparing Video Sources and Streaming URLs

A Player needs MediaItem instances that describe what to play. For progressive MP4 files, you create a MediaItem from a direct URI. For adaptive streams, you pass the manifest URL along with a MIME type like application/dash+xml or application/x-mpegURL so ExoPlayer knows which extractor to use. Constructing these items correctly is the difference between a player that starts in two seconds and one that hangs on a black screen.

When choosing streaming sources, prefer a CDN that has Australian edge nodes. Services like Akamai, Cloudflare, and Fastly all maintain points of presence in Sydney, which reduces the time it takes to retrieve the first byte of your manifest. If you are building an app for local audiences streaming AFL replays or Big Bash League highlights, hosting your content on a regional CDN will cut initial buffering noticeably for viewers in Adelaide and Hobart.

Configuring the Player UI and Controls

ExoPlayer comes with a ready-made PlayerView that includes play, pause, seek, and fullscreen controls. You can toggle these controls on or off, change their styling, or hide them entirely if your design calls for custom buttons. The setControllerShowTimeoutMs method is handy for keeping controls visible longer in a tutorial-style app, or hiding them quickly when content should fill the screen.

Below the surface, you can also attach a TrackSelector to give viewers manual control over resolution and audio track selection. This is a popular feature in apps aimed at power users who want to force a lower quality to save mobile data, which can be a real concern for Australians on mid-tier prepaid plans. Allowing users to pick captions or alternate audio tracks is also straightforward through the Player's getCurrentTracks method, which exposes all available track information in a structured list.

Common player configuration options worth knowing:

  • Default load control settings — start with the defaults, then tune buffer durations after measuring real performance.
  • Repeat and shuffle modes — useful for short looping clips such as news headlines or product showcases.
  • Playback speed — supports values from 0.5x to 2x, handy for tutorial or sports analysis apps.
  • Volume and brightness gestures — not built in but can be added with a small touch listener.

Handling Playback Events and the Activity Lifecycle

A video player is one of the most lifecycle-sensitive components in any Android app. When the user navigates away, the player should pause and release its resources to avoid leaking codecs and draining the battery. ExoPlayer exposes simple methods like pause, stop, and release that should be called in the appropriate lifecycle callbacks.

The recommended approach is to keep a single ExoPlayer instance scoped to the Activity or Fragment, then call pause in onPause and either stop or release in onStop. You can also wire up playback resumption by saving the current position in onSaveInstanceState and seeking back to it after the view is recreated, the same pattern used in popular Australian news apps to let readers pick up a video clip where they left off after a notification interruption.

Listening to Player events is just as important. The addListener API lets you react to state changes, errors, and track selection updates. For a streaming app, capturing onPlayerError is especially valuable because you can show a friendly retry button, log the failure to your analytics dashboard, or fall back to a lower-quality rendition automatically.

Signals to monitor during playback:

  • STATE_READY and STATE_BUFFERING transitions — good for showing or hiding a loading indicator.
  • onPlayerError events — show a retry option and capture diagnostic information.
  • onPositionDiscontinuity callbacks — detect ad insertions or manifest refreshes.
  • Audio focus changes — pause the stream when the user receives a call.

Performance Tips and Common Pitfalls

A few habits separate a smooth ExoPlayer integration from one that frustrates users. Always build the player on the main thread but prepare MediaSources ahead of time on a background thread when possible. Use ProGuard rules supplied by the Media3 documentation to keep your release builds from stripping classes the player needs at runtime.

If you are deploying to a wide Australian audience, test on entry-level devices that reflect the most common Android handsets sold through carriers like Telstra, Optus, and Vodafone. ExoPlayer handles hardware acceleration differently across chipsets, and bugs often only surface on older Adreno or Mali GPUs. Running automated tests on Firebase Test Lab with a mix of API levels helps catch regressions before they reach real users in cities like Geelong or the Gold Coast.

Finally, do not forget analytics. Logging playback start, pause, completion, and error events gives you the data you need to improve the experience. If you are looking for sample projects to kickstart your work, the resources at https://myeasyprojects.net/ include open source examples that pair ExoPlayer with REST APIs and local caching. Combined with the patterns covered above, you will be ready to ship a production-ready streaming experience in your next Android application.