Using cling 2.1.1 and based on the DLNA Cast project by Devin1014, I wrote the following kotlin android code that implements the AndroidUpnpServiceImpl service, also the bind and onServiceConnected methods, to discover mediaRender devices and display them in a lazyColumn. The goal now is that when clicking on a device (item), a function is executed that sends a url stream to the selected mediaRender device through the AVTransportURI service.
import org.fourthline.cling.android.AndroidUpnpService
import org.fourthline.cling.android.AndroidUpnpServiceImpl
import org.fourthline.cling.model.meta.Device
import org.fourthline.cling.model.meta.RemoteDevice
import org.fourthline.cling.registry.DefaultRegistryListener
import org.fourthline.cling.registry.Registry
import org.fourthline.cling.registry.RegistryListener

class MainActivity : ComponentActivity() {
    private var upnpService: AndroidUpnpService? = null
    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
            val upnpServiceB = p1 as AndroidUpnpService
            if (upnpService !== upnpServiceB) {
                upnpService = upnpServiceB
                upnpService?.registry?.addListener(deviceListRegistryListener)
                upnpService?.controlPoint?.search()
            }
        }

        override fun onServiceDisconnected(p0: ComponentName?) {
            upnpService = null
        }
    }

    // Using mutable state list to track discovered devices
    private val devicess = mutableStateListOf<RemoteDevice>()

    private val deviceListRegistryListener: RegistryListener = object : DefaultRegistryListener() {
        override fun remoteDeviceAdded(registry: Registry?, device: RemoteDevice?) {
            device?.let {
                if (isMediaRendererDevice(it)) {
                    Log.i("DLNA", "MediaRenderer Device Found: ${it.details.friendlyName}")
                    devicess.add(it)
                }
            }
        }
        override fun remoteDeviceRemoved(registry: Registry?, device: RemoteDevice?) {
            device?.let {
                if (isMediaRendererDevice(it)) {
                    Log.i("DLNA", "MediaRenderer Device Removed: ${it.details.friendlyName}")
                    devicess.remove(it)
                }
            }
        }
    }
    private fun isMediaRendererDevice(device: Device<*, *, *>): Boolean {
        // You can further refine this check based on specific device types or services if needed
        return device.type.type == "MediaRenderer"
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            MyClingDlnaTheme {
                Surface() {
                    DeviceListScreen(devicess)
                }
            }
        }
    }

    override fun onStart() {
        super.onStart()
        bindService(Intent(this,
            AndroidUpnpServiceImpl::class.java),
            serviceConnection,
            Service.BIND_AUTO_CREATE
        )
    }

    override fun onStop() {
        super.onStop()
        unbindService(serviceConnection)
        upnpService?.registry?.removeListener(deviceListRegistryListener)
    }
}
@Composable
fun DeviceListScreen(devices: List<RemoteDevice>) {
    //val devices = remember { mutableStateListOf<Device<*, *, *>>() }
    //val context = LocalContext.current
    //val serviceConnection = remember { MyServiceConnection { device -> devices.add(device) } }

    // En un hilo de fondo, buscar dispositivos y actualizar la lista
//    LaunchedEffect(Unit) {
//        context.bindService(
//            Intent(context, MyUpnpService::class.java),
//            serviceConnection,
//            Context.BIND_AUTO_CREATE)
//    }

    LazyColumn(modifier = Modifier.fillMaxSize().padding(top = 36.dp)) {
        items(devices) { device ->
            DeviceItem(device)
        }
    }
}
@Composable
fun DeviceItem(device: Device<*,*,*>){
//    Card (modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp),
//        elevation = CardDefaults.cardElevation(defaultElevation = 4.dp) ) {
//        Column(modifier = Modifier.padding(16.dp)) {
//            Text(text = "Nombre: ${device.details.friendlyName}")
//            Text(text = "Tipo: ${device.type}")
//        }
//    }
    Row(modifier = Modifier
        .fillMaxWidth()
        .padding(8.dp)) {
        Text(text = device.details.friendlyName, modifier = Modifier.weight(1f))

    }

}