目录
1,概述
DLNA设备、服务的注册及发现(依赖开源库cling),DLNA中设备的注册、发现主要基于UPNP协议实现,这是微软推行的一个标准。Upnp最大的愿景是希望任何设备只要一接入网络,所有网上的设备马上就能知道有新设备加入,这些设备之间就可以彼此通信。
2,render设备启动流程
2.1 AndroidUpnpServiceImpl类
AndroidUpnpServiceImpl类声明如下:
/**
* Provides a UPnP stack with Android configuration as an application service component.
* <p>
* Sends a search for all UPnP devices on instantiation. See the
* {@link AndroidUpnpService} interface for a usage example.
* </p>
* <p/>
* Override the {@link #createRouter(UpnpServiceConfiguration, ProtocolFactory, Context)}
* and {@link #createConfiguration()} methods to customize the service.
*
* @author Christian Bauer
*/
public class AndroidUpnpServiceImpl extends Service {
......
}
提供一个UPnP协议栈,通过android service暴漏服务。我们创建render时候,只需要继承该service便可。
2.2 创建router
在AndroidUpnpServiceImpl类中,创建UpnpService服务,
public void onCreate() {
super.onCreate();
upnpService = new UpnpServiceImpl(createConfiguration()) {
@Override
protected Router createRouter(ProtocolFactory protocolFactory, Registry registry) {
return AndroidUpnpServiceImpl.this.createRouter(
getConfiguration(),
protocolFactory,
AndroidUpnpServiceImpl.this
);
}
@Override
public synchronized void shutdown() {
// First have to remove the receiver, so Android won't complain about it leaking
// when the main UI thread exits.
((AndroidRouter)getRouter()).unregisterBroadcastReceiver();
// Now we can concurrently run the Cling shutdown code, without occupying the
// Android main UI thread. This will complete probably after the main UI thread
// is done.
super.shutdown(true);
}
};
}
走到RouterImpl#enable(),
public boolean enable() throws RouterException {
lock(writeLock);
try {
if (!enabled) {
try {
log.fine("Starting networking services...");
networkAddressFactory = getConfiguration().createNetworkAddressFactory();
startInterfaceBasedTransports(networkAddressFactory.getNetworkInterfaces());
startAddressBasedTransports(networkAddressFactory.getBindAddresses());
// The transports possibly removed some unusable network interfaces/addresses
if (!networkAddressFactory.hasUsableNetwork()) {
throw new NoNetworkException(
"No usable network interface and/or addresses available, check the log for errors."
);
}
// Start the HTTP client last, we don't even have to try if there is no network
streamClient = getConfiguration().createStreamClient();
enabled = true;
return true;
} catch (InitializationException ex) {
handleStartFailure(ex);
}
}
return false;
} finally {
unlock(writeLock);
}
}
完成了多播接收器multicastReceiver初始化和HTTP servers的创建,通过startInterfaceBasedTransports和startAddressBasedTransports完成了本地局域网的组网。
2.3 创建本地设备并注册
在AndroidUpnpServiceImpl继承类的onCreate()方法中,创建本地设备并注册,
override fun onCreate() {
logger.i("DLNARendererService create.")
super.onCreate()
avTransportControl = AVTransportController(applicationContext)
audioControl = AudioRenderController(applicationContext)
try {
localDevice = createRendererDevice(Utils.getHttpBaseUrl(applicationContext))
upnpService.registry.addDevice(localDevice)
} catch (e: Exception) {
e.printStackTrace()
stopSelf()
}
}
至此,完成了render局域网组网和本地设备的注册(设备信息注册到239.255.255.250)。打开control pointer设备(如爱奇艺),点击投屏按钮,就能从组播239.255.255.250那里搜索到render设备信息,为下一步指令交付建立通道。