← Back to list

Playing a UDP Multicast Stream in Android using Media3

create a UDP multicast stream in Android using androidx.media3…

Amitdogra · 2025-01-07 06:59 · 10 claps · 2.9 min read paywalled
#udp #media3 #exoplayer #android #ip-multicast
Open on Medium ↗

Playing a UDP Multicast Stream in Android using Media3

In this guide, we will demonstrate how to create a UDP multicast stream in Android using androidx.media3. https://developer.android.com/jetpack/androidx/releases/media3

File Structure

  1. MainActivity.kt: Handles player binding and UI interactions.
  2. build.gradle.kts: Includes dependencies and setup for the project.
  3. MulticastController.kt: Contains the multicast socket code.
  4. TunerDataSource.kt: Reads data from MulticastController and feeds it to the player.
  5. activity_main.xml: Defines the layout for the player.

MainActivity.kt

package com.example.udpstreaming

import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.PlayerView
import kotlinx.coroutines.launch

class MainActivity : AppCompatActivity() {
    private var player: ExoPlayer? = null
    private lateinit var playerView: PlayerView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        playerView = findViewById(R.id.player_view)

        val multicastTuner = MulticastController("239.0.0.12", 1234)
        // replace with your multicast ip and port 

        lifecycleScope.launch {
            try {
                initializePlayer(multicastTuner)
            } catch (e: Exception) {
                Log.e("MainActivity", "Error initializing player: ${e.message}", e)
            }
        }
    }

    private fun initializePlayer(multicastTuner: MulticastController) {
        player = ExoPlayer.Builder(this).build().apply {
            val tunerDataSource = TunerDataSource(multicastTuner)
            val mediaSource = tunerDataSource.createMediaSource()

            setMediaSource(mediaSource)
            prepare()
            playWhenReady = true

            playerView.player = this
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        player?.release()
    }
}

build.gradle.kts

plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
}

android {
    compileSdk = 33

    defaultConfig {
        applicationId = "com.example.udpstreaming"
        minSdk = 21
        targetSdk = 33
        versionCode = 1
        versionName = "1.0"
    }

    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = "1.8"
    }
}

dependencies {
    val media3_version = "1.5.0"

    // other dependencies
    implementation("androidx.media3:media3-exoplayer:$media3_version")
    implementation("androidx.media3:media3-ui:$media3_version")
}

MulticastController.kt

This file contains the implementation for the multicast socket:

package com.example.udpstreaming

import java.io.IOException
import java.net.DatagramPacket
import java.net.InetAddress
import java.net.MulticastSocket

class MulticastController(private val host: String, private val port: Int) {
    private lateinit var socket: MulticastSocket

    fun start() {
        try {
            val multicastGroup = InetAddress.getByName(host)
            socket = MulticastSocket(port).apply {
                reuseAddress = true
                joinGroup(multicastGroup)
                soTimeout = 5000
            }
        } catch (e: Exception) {
            throw IOException("Failed to initialize multicast socket: ${e.message}")
        }
    }

    fun stop() {
        if (::socket.isInitialized && !socket.isClosed) {
            socket.leaveGroup(InetAddress.getByName(host))
            socket.close()
        }
    }

    fun fetchData(buffer: ByteArray): Int {
        val packet = DatagramPacket(buffer, buffer.size)
        socket.receive(packet)
        return packet.length
    }
}

TunerDataSource.kt

This file connects the MulticastController to the player:

package com.example.udpstreaming

import androidx.media3.exoplayer.source.ProgressiveMediaSource
import androidx.media3.datasource.DataSource
import androidx.media3.datasource.DataSpec
import java.io.IOException

class TunerDataSource(private val tuner: MulticastController) : DataSource {
    private var opened = false

    override fun open(dataSpec: DataSpec): Long {
        tuner.start()
        opened = true
        return DataSpec.LENGTH_UNSET.toLong()
    }

    override fun read(buffer: ByteArray, offset: Int, length: Int): Int {
        if (!opened) throw IOException("DataSource not opened.")
        return tuner.fetchData(buffer.copyOfRange(offset, offset + length))
    }

    override fun close() {
        if (opened) tuner.stop()
        opened = false
    }

    override fun getUri() = null

    fun createMediaSource(): ProgressiveMediaSource {
        return ProgressiveMediaSource.Factory { this }.createMediaSource(null)
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.media3.ui.PlayerView
        android:id="@+id/player_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        android:keepScreenOn="true" />

</RelativeLayout>

Key Interactions:

  • MainActivity → Sets up ExoPlayer and UI interactions.
  • MulticastController → Manages the UDP multicast socket, receiving and handling data.
  • TunerDataSource → Acts as a bridge between the ExoPlayer and the multicast data, feeding the stream data to ExoPlayer.
  • ExoPlayer → Decodes and plays the media content on the UI.

Final Steps:

  1. Network Permissions: Make sure you have the necessary permissions to use the network in your AndroidManifest.xml.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Creating a UDP Stream using VLC or FFmpeg

To create a UDP multicast stream, you can use tools like VLC or FFmpeg. These tools allow you to broadcast media over a network using UDP multicast.

Using VLC:

  1. Open VLC and go to MediaStream.
  2. In the File tab, select the media file you want to stream.
  3. Click Stream and then choose UDP (multicast) as the destination.
  4. Set the Address to your multicast IP (e.g., 239.0.0.12) and the Port to the desired value (e.g., 1234).
  5. Click Stream to start broadcasting.

Using FFmpeg:

To create a UDP multicast stream with FFmpeg, use the following command in the terminal:

ffmpeg -i input_video.mp4 -c:v libx264 -f mpegts udp://239.0.0.12:1234?ttl=64

This command tells FFmpeg to read the input_video.mp4 file, encode it using the libx264 codec, and stream it as an MPEG-TS packet over UDP to the multicast IP 239.0.0.12 on port 1234. The ttl=64 option sets the Time-to-Live for the multicast packets.

Don’t forget to save this article for later reading! A clap 👏 would really motivate me to keep going.

If you’d like the complete working code on GitHub, feel free to leave a comment.


메타데이터
post_id
d13ca69a42ef
slug
playing-a-udp-multicast-stream-in-android-using-media3-d13ca69a42ef
url
https://medium.com/@amitdogra70512/playing-a-udp-multicast-stream-in-android-using-media3-d13ca69a42ef
canonical_url
https://medium.com/@amitdogra70512/playing-a-udp-multicast-stream-in-android-using-media3-d13ca69a42ef
author_url
https://medium.com/@amitdogra70512
status
ok
fetched_at
2026-08-11 15:23:59