Android平台投屏Sink端实现的研究
背景与需求
由于日常学习的需求, 手机、平板电脑和电视等设备之间的互联互通对我变得尤为重要, 所以我希望通过Wi-Fi将手机屏幕投射到另一台 Android 大屏设备上,实现同屏显示。由于我对投屏技术还不够熟悉,最初构思了一个方案,即开发两个应用程序,分别安装在手机和 Android 设备上,手机应用实时进行录屏,并将视频数据通过 Wi-Fi 发送到 Android 设备进行播放。然而,这个方案存在一些问题:
每台手机都需安装应用,使用不便。
录屏可能会造成延迟,无法实现实时传输。
从零开始开发这一功能比较复杂。
因此,我决定探索现有的解决方案。经过一番查找,我发现许多手机自带投屏功能。例如,荣耀300用户可以通过以下步骤轻松实现投屏:打开手机设置,进入“连接与共享”中的“投屏”选项即可将手机屏幕投射到支持相关协议的设备上,这种投屏技术主要基于 Miracast。
现有投屏解决方案
目前,主流的投屏技术主要有三种:AirPlay、DLNA 和 Miracast。其中:
AirPlay:通常仅适用于认证的苹果设备,主要支持苹果自家的产品。
DLNA:主要功能为将手机中的照片和视频分享到大屏幕。
Miracast:支持无线分享视频画面,具有类似于 AirPlay 的镜像功能,能够直接将手机屏幕内容投放到高清电视上,此外,该协议还支持反向控制功能。
Miracast技术的选择
综合考虑,Miracast 技术最符合我的需求,它确保大多数 Android 手机都可以顺利实现投屏。为了提前体验 Miracast 的功能,我尝试将手机投屏到 Windows 11 电脑上,因为 Windows 11 本身支持 Miracast。这一过程也相对简单:首先将手机和 Windows 11 电脑连接到同一 Wi-Fi 网络,在电脑上打开自带的“连接”应用程序,然后启动手机的投屏功能进行搜索。如果一切顺利,手机会找到电脑,点击连接即可启动投屏,同时,如果电脑支持蓝牙,还可以将手机的声音通过蓝牙实时传输到电脑,轻松实现在电脑屏幕上观看手机影片的乐趣。
接下来,我们将深入探讨Miracast是如何实现投屏的。
在Miracast的架构中,设备被分为两类:传送端(Source)和接收端(Sink)。传送端负责对视频流进行编码并输出传输流(TS流),而接收端则负责解码并显示这些流媒体内容。在这个框架中,传送端可以被视为服务器(Server),负责提供服务;而接收端则作为客户端(Client),用于进行展示。
在我们的场景中,手机充当传送端,而Android设备担任接收端。因此,我们需要在Android设备上实现Sink功能,以确保其能够有效地接收和展示来自手机的投屏内容。
Wi-Fi Display架构图
实现Miracast Sink端功能
自Android 4.2起,Android系统便支持Miracast投屏协议,用户通常可以通过“设置-投屏”选项将手机屏幕镜像到大屏设备上。在这个过程中,手机作为Miracast协议的传送端(Source),而Android设备则充当接收端(Sink)。需要注意的是,自Android 4.2.2版本后,谷歌移除了原生Sink端的实现,因此我们必须自行开发该功能。
Miracast其实也被称为WiFi Display,这两者的关系可由官方定义概括为:WiFi Display(WFD)是WiFi联盟基于现有技术所提出的新概念,旨在加速视频及音频的传输分享。为此,WiFi联盟设立了Miracast认证项目,用以确认设备是否支持WiFi Display功能。
在Android平台中,虽然提供了操作WFD的相关接口,但SDK中有一些接口被隐藏。为了使用这些功能,我们可以借助反射机制来调用相关代码。
Miracast协议依赖于Wi-Fi P2P,两个设备需要通过Wi-Fi实现直接连接。自Android 4.0版本后,Wi-Fi P2P得到了支持。在这种连接中,Source作为Group Owner,而Sink则扮演Client的角色。
一旦Wi-Fi P2P连接成功,Source和Sink将建立一个Miracast会话,基于TCP连接并使用RTSP协议来进行管理和控制。RTSP协议完成协商后,我们便可以开始传输音视频数据。Sink会建立UDP连接,使用RTP协议,而Source端的音视频数据经过MPEG-2 TS编码后,通过RTP协议发送给Sink,后者将解码接收到的数据并最终在屏幕上显示出来。
实现步骤总结
基于上述原理,实现Android Sink端功能的主要步骤如下:
1. 创建Wi-Fi P2P连接
2. 建立RTSP通信,并处理RTSP协议
3. 创建RTP/RTCP连接,接收音视频数据及数据流控制
4. 播放音视频数据
以上步骤必须按照顺序进行,只有前一步成功处理后,才能进行下一步操作。
详细的实现过程
如下(因代码量较大,此处仅列出关键代码及核心步骤):
一、需要的权限
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_WIFI_STATE
android.permission.CHANGE_WIFI_STATE
android.permission.INTERNET
二、建立Wi-Fi P2P连接
1.WifiP2pManager初始化
Channel initialize(Context srcContext