再谈 Carplay 播放视频

在去年的时候,我曾经研究过如何在苹果的carplay播放视频的问题。之所以研究这个,纯粹也是闲的蛋疼,并不是真的有那么大的需求要在车机上看视频。
至于在车机播放视频,今年早些时候在安卓的车机上测试过是可以播放的,甚至能用方向盘的多功能按键进行切换,在车机上通过zlink连接的华为的hi car,之前的文章可以点击这里查看。
去年研究的时候主要是基于https://github.com/thomasdye12/TDS-Carplay这个开源项目,实现方式也比较简单,调用私有api创建一个车机上的全屏窗口,去年的时候申请apple的communication权限始终没通过,直到前几天终于通过了。

也不知道苹果是什么处理逻辑,有时候真的答非所问,问就是已经有了drive task权限,翻来覆去就是要么说权限已经有了要么就是没反应了,开发者论坛,工单都提过,甚至电话支持也申请过,问就是帮忙反馈,反馈了就没动静了。
这次也不知道是哪路神仙想起来了,竟然顺利通过了。此时又想起来这个项目,重新跑起来:

iOS26 is not supported,这比49年入国军还惨,这依然是50年了,毛都没有了。就离谱,当然,主要原因按照自己的分析以及ai分析给出的结论在于苹果收紧了carplay端的权限管理:
提示信息来源:
Section(header: Text("Getting Started")) {
Text("IOS 26 IS NOT SUPPORTED")
.tint(.red)
.fontWeight(.bold)
NavigationLink(destination: Help()) {
Label("Help", systemImage: "questionmark.circle")
TDS实现逻辑:
1.Hook 私有方法,强制创建全屏车机窗口
_shouldCreateCarWindow → 永远 YES
__supportsCarFullScreen → 永远 YES
2.拿到系统的 CPWindow,把 UIImageView / AVPlayer / WKWebView 直接贴上去播画面
3.表面挂一个 CPMapTemplate(地图模板) 当“合法壳”,实际内容是自定义全屏 UI
再绕过 clientPushedIllegalTemplateOfClass:(非法模板检查)针对iOS26的系统库分析:

当然,更主要可能是来自于这个问题,新的权限判断是通过hasNavigationEntitlement而不是__supportsCarFullScreen,单独这一项就足够让当前这个app彻底崩溃了。
那么,事情到这里,似乎已经是无解了,但是事实真的如此吗?感觉并不是,去苹果应用商店搜索carplay能找到一堆播放视频的东西,下载了两个,一个只能添加网络视频地址,我没有,所以没法测试,另外一个cartv集成了视频播放功能,在车机上竟然成功了:
手机端界面:

播放页面投屏:
屏幕镜像方式:
那么基于这两种方式也就实现了:
1.app直接在车机播放视频
2.通过屏幕镜像录屏流的方式实现屏幕镜像。
不得不说,第一个发现在这个东西的还真特娘的是个天才。
既然知道了原理,那么要实现这个东西也就简单了,之前已经有了communication权限,那么就可以向车机传送数据,能传送数据那么在创建出对应的窗口来应该就可以了。说干就干,直接上手开撸,当然,主要还是靠ai撸,参考项目目前已经没有什么参考意义了,直接起个新的xcode项目开始实现这些功能。
有了思路之后,写代码其实没什么困难,困难的是代码之外的问题该如何解决,投屏镜像完成之后,兴冲冲的跑到车上测试:
纳尼,怎么跟我想象的不一样呢,这是为虾米啊,苍天啊大地啊,怎么可以酱紫呢。
这,只能说,开头很顺利,失败的也很迅速。当然,这个东西的根源要找起来也简单,就是前面提到的hasNavigationEntitlement,也就是mobileprovision里面对应的com.apple.developer.carplay-maps权限,完整权限列表:
com.apple.developer.carplay-communication com.apple.developer.carplay-driving-task com.apple.developer.carplay-maps
而申请com.apple.developer.carplay-maps这个权限,要求app必须要有导航功能,并且是 turn-by-turn的导航才可以,需要提供的资料也比较多,包括app截图,规划,语音播报信息等等。
等拿到权限之后就可以创建一个CPMapTemplate至于里面塞什么东西,那就全看自己的意愿了。这也是cartv之类的视频播放实现方式。
简单视频播放,可以通过推送视频流的方式来实现,同样也是cartv的实现方式,最终app实现效果:
车机等待界面:
视频效果:
至于为什么要做这个东西?
那肯定是,因为姐姐我可以做,我能做,我还做出来了!