环境配置
安卓模拟器
强烈推荐:Genymotion,个人用户可以下载免费版(但需要注册)【官网下载】
Genymotion号称最快的安卓模拟器,它是通过VirtualBox实现的。如果你的电脑上已经安装了VirtualBox虚拟机,可以下载独立的Genymotion(约44MB)版本,完成软件安装。
注意:这里仅仅是安装Genymotion软件,而Android虚拟机则是在Genymotion运行时,需要联网下载的。
注意,如果没有打包安装VirtualBox,需要在配置中指定VirtualBox在本机的安装目录
安装Android虚拟机
有可能安装不成功,我在安装Android 8.0的时候就失败了,于是退回到Android7.1版本,成功!
启动虚拟机
此时,打开VirtualBox,可以看到增加了虚拟机,并默认提供了出厂备份(不过无法通过VBox直接打开该Android系统)
安装SDK Platform Tools
官网地址:https://developer.android.google.cn/studio/releases/platform-tools
解压到任何目录,直接执行adb程序即可运行
通过ADB连接到Genymotion安卓虚拟机
Genymotion对ADB有两种支持方式,我直接使用的默认形式,如图:
但此时,运行adb,却无法检测到设备……提示版本不匹配
于是,在我更新SDK Platform Tools之后,正常运行了……
但我很好奇,adb命令只启动了对应版本的client,而同样运行在PC端的ADB-Server却是40版本,说明Server的程序并不在SDK Platform Tools工具包之中,而是随安卓系统而运行的。看来adb的启动原理还得继续探索学习……
ADB 架构
详见:《adb概览及协议参考》
简单来说,就是两层 C/S 结构,构件包括了:
- Client
- Server
- ADB Daemon
架构图如下:
本人看来,ADB的概念有点凌乱——Client 作为客户端,与Server却是同一个程序(adb.exe),都运行在PC端。实际上,所谓的ADB-Server,更像是一个集成在客户端的多路路由(Router, or Dispatcher),负责将来自于 Console、IDE 等各处ADB的调试命令转发到设备端。
设备作为终端,需要响应客户端的调试请求,这个任务由 ADB Daemon 完成:它具备root权限,用于调用Android系统底层shell,添加、修改文件或程序,或是将请求转发给其他的Android-APP。然后,在通过TCP网络将数据反馈给客户端(PC)。
这样,ADB中至少存在着两组TCP连接:
- Client-Server的连接,主要用于实现PC上多个客户端的调用模式;
- Server-Daemon的连接,用于 PC-Andorid 设备间通信。
对于 adb forward 模式,则还会有第三组TCP连接,Daemon将作为一个端口的数据转发中间件,将数据转发到指定的端口。
思考:
但有一点我目前还不能理解——既然 Server 通过5037端口监听着 Client 的连接,并保持着与 Device-Daemon 的连接(例如,通过与5555端口),为何还要动态分配 5554-5585 这些端口?这个设计既笨重,又丑陋,还限制了能否连接Devices的数量(16个)。而实际上,Device-Daemon 可以固定使用一个端口监听,通过Msg Head指定消息的发送源,ADB-Server 完全有能力实现对不同线路消息的区分……
ADB forward 转发模式
在PC端执行以下命令:
adb forward tcp:6100 tcp:7100
可以将 PC-Client 发送向 127.0.0.1:6100 的消息,传送给监听着 127.0.0.1:7100 的设备端程序。但注意,无论是 PC-Client,还是设备端的 Application,他们的通信的对象都是本机运行的中间件,而不是二者直接点对点连接。由于127.0.0.1内通讯完全不受网络干扰,所以 PC-Client 的连接一定是成功的(它连接的对象是 PC-Server),但并不能保证 Server-Daemon 之间的通讯环境稳定,获取消息并转发给 Device-Application。
注意:这是一个非常显著的区别——你甚至无法通过TCP-API判断是否连接成功,验证方式只能是接受到真正来自于 App 的 Response。
这种区别,也将导致我们在 socket 的连接时,修改代码的验证方式。
利用ADB转发,通过USB让Android访问PC端服务
首先,这是一个本不该使用ADB实现的需求——Android可以利用USB共享网络,与PC建立局域网,何必非要ADB?
其次,ADB本身也是为了从PC端下发调试信息,设备是作为服务端响应PC请求的……与Android向PC请求的节奏完全不符。
尽管如此,如果就遇到了这么一个“反人类”的需求,能不能完成呢?(不考虑PC端轮询的丑陋方式)
既然 ADB forward tcp2tcp 中,是三组TCP网络连接,而TCP是全双工的连接,建立连接后,请求端和应答端的地位是对等的。也就是说,ADB-Server-Appliaction 作为Server的唯一要点,仅仅是在建立连接时。而一旦完成了连接,则由 PC-Client 进入recv阻塞,直到 Request 到来……看上去,只是节奏稍有不同,但一切并不与技术框架相违背。