Apple TV

Android TV

macOS

Rust

遥控器

智能家居

先说结论如果你和我一样——家里有 Android TV(或者刷了 Android 系统的电视盒子),同时又是 iPhone 用户,一定体验过找遥控器的痛苦。沙发缝、茶几下、甚至被猫叼走……但手机永远在身边。

我做了一个叫 atv-core 的项目,核心功能就一句话:让 iPhone 控制中心自带的 Apple TV 遥控器可以直接操控 Android TV 和 macOS。

不需要安装任何第三方遥控 App,也不需要买 Apple TV。打开 iPhone 控制中心,选择你的设备,即可开始操控。触控板滑动、方向键、音量调节、播放暂停,全都支持。

开源项目

corvofeng/atv-core

Rust 核心 + Android TV 与 macOS 客户端,以 MIT 协议开源。

在 GitHub 查看源码

可能有些朋友还不知道 iPhone 自带了 Apple TV 遥控器。打开控制中心(从屏幕右上角向下滑),找到下图红圈里那个遥控器图标,点一下就能打开。如果控制中心里没有,去 设置 → 控制中心 手动添加即可。

屏幕右上角下滑控制中心Apple TV 遥控器

点进去之后就是遥控器界面,上面是触控板区域,下面是功能按键:

1. 找到遥控器点击图中标出的按钮。

2. 使用遥控器上方滑动,下方点按功能键。

为什么要做这个市面上有不少手机遥控 App,但我总觉得差点意思:

需要单独打开一个 App:操作路径太长,解锁 → 找 App → 等加载 → 开始用。而控制中心的遥控器是系统级的,从任何界面向下一划就能调出来。

触控体验不统一:各家 App 的触控板手感参差不齐,有的延迟大,有的方向识别飘。Apple TV 遥控器的触控手感是苹果自己打磨过的,非常丝滑。

Mac 也需要遥控场景:我的 Mac mini 接在客厅电视上当 HTPC,躺在沙发上调音量、切歌、移动鼠标,全靠这个遥控器。

简单来说,我想要的是:不多装一个 App,用系统原生的交互,同时搞定电视和电脑。

它长什么样Android TV 端在 Android TV 上安装 atv-core 的 APK 后,会看到一个控制面板。它会显示配对 PIN 码(默认 1111)、连接状态、按键注入模式等信息:

Android TV 控制面板连接前可在这里确认 PIN、服务状态和当前输入模式。

连接成功后,你就可以用 iPhone 遥控器在电视上滑动浏览内容了。滑动触控板,焦点会在 Android TV 的卡片之间平滑切换:

焦点在第一个卡片

滑动后焦点移动到下一个

macOS 端Mac 端的体验就更丰富了。atv-core 提供了一个 Web 调试面板,可以实时查看遥控器的所有操作状态——触控轨迹、按键事件、音量、配置参数,一目了然:

macOS 调试面板触控轨迹、按键事件和运行参数会在这里实时更新。

在 Mac 上,触控板的操作会转换成鼠标移动。而且做了动态加速度算法——轻轻划是精准移动几个像素,用力甩一下可以让光标飞过整个 4K 屏幕。这个手感还是调了挺久的。

怎么开始用前置条件

iPhone 和目标设备(Android TV / Mac)在同一个 Wi-Fi 局域网下

路由器没有开启 AP 隔离 / 访客模式(否则 mDNS 广播会被拦截)

Android TV 配置

安装 APK:把编译好的 APK 通过 ADB 安装到电视上

12adb install -r app-debug.apkadb shell am start -n com.corvofeng.fakeatv/.MainActivity

开启无障碍服务:进入电视的 设置 → 无障碍 → 找到 “Apple TV Remote Receiver” → 打开

找到无障碍服务

确认开启权限

如果你的电视系统隐藏了无障碍菜单(某些国产定制系统会这样),可以用 ADB 命令直接开启:

123adb shell settings put secure enabled_accessibility_services \ com.corvofeng.fakeatv/.AtvAccessibilityServiceadb shell settings put secure accessibility_enabled 1

从 iPhone 连接:打开 iPhone 控制中心 → Apple TV 遥控器 → 选择你的设备 → 输入 PIN 1111 → 开始使用!

macOS 配置Mac 端更简单。编译或下载 DMG 后双击安装,启动应用即可。菜单栏会出现一个遥控器图标。

12# 如果从源码编译./scripts/build_dmg.sh

如果系统提示”无法验证开发者”,运行:

1xattr -dr com.apple.quarantine /Applications/AppleTVRemote.app

技术上是怎么实现的这部分稍微深入一点,感兴趣的朋友可以看看。

核心思路Apple TV 遥控器通过一个叫 Companion Link 的私有协议与 Apple TV 通信。这个协议基于 mDNS 服务发现 + SRP 加密握手 + OPACK 消息编码。atv-core 做的事情就是在 Android TV 和 Mac 上模拟一个 Apple TV 的 Companion Link 服务端,让 iPhone 以为它在跟一台真的 Apple TV 对话。

整个数据流大概是这样的:

1234567891011121314151617iPhone 控制中心遥控器 │ │ Companion Link / MRP 协议 │ (ChaCha20-Poly1305 加密) │ ▼atv-core 事件分发引擎 │ ├─ 解密 OPACK 消息 (_touchMove / _hidEvent) │ ├─ 模式解析 │ ├─ 方向键模式: dy < -25px => DPAD_UP │ └─ 鼠标模式: 动态加速度曲线 │ └─ 双端分发 ├─ Android TV: LocalADB / 无障碍服务 → KEYCODE_DPAD_* └─ macOS: CGEvent → 光标移动 / NX_KEYTYPE → 媒体键

手势识别与累加器iPhone 遥控器的触控板会以很高的频率发送微小的坐标偏移量(dx, dy)。直接把每个偏移量转换成按键的话,手指稍微动一下就会触发好几次方向键,体验很差。

所以 atv-core 里做了一个 零抖动累加器:持续收集这些微位移,直到累积量超过阈值才触发一次方向键事件。同时还有方向死区过滤——斜向滑动时只识别主方向,避免同时触发上+右这种尴尬操作。

按键注入的两条通道在 Android TV 上,atv-core 有两种方式把按键”注入”到系统里:

通道

原理

延迟

适用场景

本地 ADB (Dadb)

通过 127.0.0.1:5555 直接发送 Linux 输入事件

< 8ms

方向键、确认键、媒体键

无障碍服务 (Accessibility)

Android 系统级全局操作

~15ms

返回、Home、电源等系统键

两者互为补充。ADB 通道速度极快但无法触发系统级动作(比如返回键),无障碍服务可以做到但延迟稍高。atv-core 会根据按键类型自动选择最优通道。

按键映射一览最后附一张完整的按键映射表,方便查阅:

Apple TV 遥控器操作

Android TV

macOS

触控板滑动 (方向键模式)

DPAD_UP / DOWN / LEFT / RIGHT

方向键 ↑↓←→

触控板滑动 (鼠标模式)

触摸拖拽模拟

平滑光标移动

点按 / SELECT

DPAD_CENTER

Enter / 鼠标左键

返回 <

系统返回

Escape

主屏幕 📺

系统 Home

显示桌面

播放暂停 ⏯ 单击

MEDIA_PLAY_PAUSE

播放 / 暂停

播放暂停 ⏯ 双击

快进 / 下一集

下一曲 ⏭

播放暂停 ⏯ 三击

快退 / 上一集

上一曲 ⏮

音量 +/-

VOLUME_UP / DOWN

系统音量 + 原生 HUD

静音

VOLUME_MUTE

系统静音

Siri 键

语音搜索

切换 鼠标/方向键 模式

电源键

电源菜单

息屏 / 唤醒

项目地址与后续计划项目使用 Rust 编写核心逻辑(atv-core),Android 端通过 JNI 桥接,Mac 端通过 Swift 包装。代码以 MIT 协议开源:

GitHub:corvofeng/atv-core

反馈问题:Issues

如果你想从源码开始,可以直接克隆仓库:

1git clone https://github.com/corvofeng/atv-core.git

后续还有一些想做的事情:

支持文字输入(iPhone 键盘直接输入到 Android TV 的搜索框)

支持更多手势(长按、双击等)

提供预编译的 APK 和 DMG 下载,降低使用门槛

如果你也有类似的需求,欢迎尝试。有问题可以在 GitHub 提 Issue,或者在评论区交流。

参考资料

pyatv - Python library for Apple TV

MediaRemote.framework 逆向分析

Companion Link Protocol 文档