cover
前言
又来到了源码分析,说实话在写文章之前 我并没有很仔细的阅读过 Cling 的源码,所以说 我也只是个菜比。但我会竭尽所能的把我所了解的东西分享出来,我希望对那些做 DLNA 的童鞋有所帮助。阅读源码的好处,首先就是能够更了解它的原理,这能帮助我们更好的使用它。同时,阅读源码可以能提升我们逻辑思维能力,以及设计能力,让我们能够设计出更简洁的代码。
其实我并不喜欢看别人写的源码分析,我更喜欢自己去看源码。
所以,我一直在想,
为什么要看别人写的源码分析?
这样做是不是能更快速的了解源码?
是不是源码难懂?
所以。。。
这篇文章会把 Cling 库控制设备流程大致讲一下,同时我会告诉你 我阅读 Cling 源码的过程,这样 你以后看源码的思路会更清晰一点 (多好的人啊,我都被自己感动了)。
先从控制设备流程开始说起,然后根据这个流程一一展开,介绍整体结构。这个过程也保持之前的模式:带着问题 一步一步的寻找答案。
关于 android 投屏技术系列:
一、知识概念
这章主要讲一些基本概念, 那些 DLNA 类库都是基于这些概念来做的,了解这些概念能帮助你理清思路,同时可以提升开发效率,遇到问题也能有个解决问题的清晰思路。
二、手机与tv对接
这部分是通过Cling DLNA类库来实现发现设备的。
内容包括:
抽出发现设备所需接口
发现设备步骤的实现
原理的分析
三、手机与tv通信
这部分也是通过Cling DLNA类库来实现手机对tv的控制。
内容包括:
控制设备步骤
控制设备代码实现
手机如何控制tv
tv将自己的信息如何通知手机
原理的分析
关于控制设备
上篇文章解释了 什么是控制设备;控制设备过程是怎样的;以及代码的实现。
那么,Cling 源码 是怎么实现这个过程的呢?
为了简单明了,我们先忽视那些底层的东西,从最简单的开始看。
为什么要这样?
因为如果不忽视这些底层的东西,你会很容易陷入迷茫的状态。而先把外层简单的逻辑梳理清楚以后,再深入了解底层的就更容易看懂一点。
我们理一下控制设备相关的类和方法有哪些?
是否记得 控制设备 使用的三步曲?(不记得的可以翻上面的链接看,不看也不要紧)
获取tv设备控制服务:通过选中的设备执行 device.findService(serviceType);
获取控制点:通过执行 UpnpService.getControlPoint()
执行指定控制命令:通过执行 ControlPoint.execute(命令)
于是,我们可以根据这些入手,看它们之间是如何连接起来的,然后它们分别做了什么事情。
Service service = device.findService(serviceType);
这段代码 返回的是 服务 Service
serviceType 就是服务类型,比如 AVTransport ...
我们知道,控制设备 是通过 控制点 执行控制命令。
下面就是控制设备播放的操作:
Service avtService = device.findService(new UDAServiceType("AVTransport"));
ControlPoint controlPoint = UpnpService.getControlPoint();
controlPoint.execute(new Play(avtService) {
@Override
public void success(ActionInvocation invocation) {
super.success(invocation);
// to do success
}
@Override
public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {
// to do failure
}
}
});
可见,controlPoint.execute(new Play(avtService) 这一句很关键。
它告诉我们
ControlPoint 有一个 execute 方法
执行命令时 传入了一个 Play ,Play(服务)
在分析 发现设备 源码的时候,我们得出 controlPoint.execute(..) 是通过 ExecutorService.submit(...) 执行的。 最后的执行者是 ClingExecutor。
我们复习一下,来看看 ClingExecutor:
public static class ClingExecutor extends ThreadPoolExecutor {
public ClingExecutor() {
this(new ClingThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy() {
// The pool is unbounded but rejections will happen during shutdown
@Override
public void rejectedExecution(Runnable runnable, ThreadPoolExecutor threadPoolExecutor) {
// Log and discard
log.info("Thread pool rejected exe