背景介绍
作为一名Rokid Glasses开发者,我最近在开发一个需要AR录屏功能的应用。然而,Rokid官方提供的CXR SDK中并没有直接封装AR录屏的功能。在查阅官方文档和API后,我意识到需要自己探索实现方案。
经过深入研究,我发现了通过蓝牙HCI数据包分析并结合CXR API的方法,成功实现了AR录屏功能。本文将详细介绍我的探索过程和最终解决方案。
问题分析
1. 官方SDK的限制
Rokid CXR SDK提供了丰富的AR眼镜控制功能,但在录屏方面存在以下限制:
- 没有直接的AR录屏API
- 现有API主要面向常规应用控制
- 文档中未提及录屏相关功能
2. 技术思路
由于没有直接的API,我决定从以下角度入手:
- 分析官方应用:Rokid AI App如何实现AR录屏?
- 蓝牙通信分析:眼镜与手机之间通过蓝牙传输哪些控制指令?
- 协议逆向:能否找到录屏的控制协议?
技术探索过程

步骤1:蓝牙HCI数据包抓取
首先,我开启了Android设备的蓝牙HCI日志功能:
bash
# 开启蓝牙HCI日志
adb shell setprop persist.bluetooth.btsnoopenable true
adb shell setprop persist.bluetooth.btsnooplogmode full
adb shell stop bluetooth
adb shell start bluetooth
# 从设备拉取日志
adb pull /data/misc/bluetooth/logs/btsnoop_hci.log
步骤2:使用Wireshark分析数据包
将抓取到的HCI日志用Wireshark打开,并使用过滤器查看关键数据:
wireshark
# 过滤RFCOMM协议
btrfcomm
# 查看Scene_Control相关的包
frame contains "Scene_Control"
步骤3:发现关键数据包
经过仔细分析,我发现了录屏控制的关键数据包:
开始录屏指令:
02 33 00 52 00 4e 00 53 00 23 ff 93 01 00 00 00 49 05 04 75 75 53 4f 81 20 41 03 53 79 73 00 00 00 38 05 02 53 53 0d 53 63 65 6e 65 5f 43 6f 6e 74 72 6f 6c 21 7b 22 6e 61 6d 65 22 3a 22 6d 69 78 5f 72 65 63 6f 72 64 22 2c 22 6f 70 65 6e 22 3a 74 72 75 65 7d 46
停止录屏指令:
02 33 00 52 00 4e 00 53 00 23 ff 93 01 00 00 00 49 05 04 75 75 53 4f 81 20 41 03 53 79 73 00 00 00 38 05 02 53 53 0d 53 63 65 6e 65 5f 43 6f 6e 74 72 6f 6c 21 7b 22 6e 61 6d 65 22 3a 22 6d 69 78 5f 72 65 63 6f 72 64 22 2c 22 6f 70 65 6e 22 3a 66 61 6c 73 65 7d 46
步骤4:解析协议格式
通过分析数据包,我发现了协议的结构:
Scene_Control!{"name":"mix_record","open":true/false}
这是一个简单的JSON格式控制指令:
name: 场景名称,AR录屏对应mix_recordopen: 控制开关,true开始录屏,false停止录屏
解决方案实现
基于以上分析,我利用CXR SDK现有的CxrApi构建了AR录屏控制功能:
1. 核心场景控制函数
kotlin
fun controlScene(sceneType: String, enable: Boolean, extraArgs: String = ""): ValueUtil.CxrStatus {
Log.i("CxrApi", "controlScene sceneType:$sceneType, enable:$enable, extraArgs:$extraArgs")
var status = ValueUtil.CxrStatus.REQUEST_FAILED
return try {
// 构建JSON参数
val json = JSONObject().apply {
put("name", sceneType)
put("open", enable)
if (extraArgs.isNotBlank()) {
put("param", extraArgs)
}
}
val jsonString = json.toJSONString()
Log.i("CxrApi", "sceneJson: $jsonString")
// 创建Caps对象并写入数据
val caps = Caps().apply {
write("Scene_Control")
write(jsonString)
}
// 发送控制请求
status = CxrController.getInstance().request(CxrApi.getInstance().w, "Sys", caps, null)
status
} catch (e: Exception) {
Log.e("CxrApi", "controlScene error: ${e.message}")
ValueUtil.CxrStatus.REQUEST_FAILED
}
}
2. 封装的AR录屏功能
kotlin
// 封装的AR录屏功能
fun controlSystemMixRecord(toOpen: Boolean) {
when(controlScene("mix_record", toOpen)) {
ValueUtil.CxrStatus.REQUEST_SUCCEED -> {
Log.d(TAG, "Video record ${if (toOpen) "started" else "stopped"}")
}
ValueUtil.CxrStatus.REQUEST_FAILED -> {
Log.e(TAG, "Failed to ${if (toOpen) "start" else "stop"} video record")
}
ValueUtil.CxrStatus.REQUEST_WAITING -> {
Log.e(TAG, "Requested but Glasses is not ready")
}
else -> {
Log.e(TAG, "Unknown error")
}
}
}
// 启动AR录屏
fun startARRecording() {
controlSystemMixRecord(true)
}
// 关闭AR录屏
fun stopARRecording() {
controlSystemMixRecord(false)
}
3. 完整的使用示例
kotlin
class ARRecordingActivity : AppCompatActivity() {
private lateinit var arRecordingController: ARRecordingController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_ar_recording)
arRecordingController = ARRecordingController()
// 开始AR录屏
findViewById<Button>(R.id.btn_start_record).setOnClickListener {
arRecordingController.startARRecording()
}
// 停止AR录屏
findViewById<Button>(R.id.btn_stop_record).setOnClickListener {
arRecordingController.stopARRecording()
}
}
override fun onDestroy() {
super.onDestroy()
// 确保停止录屏
arRecordingController.stopARRecording()
}
}
技术细节说明
1. 协议栈分析
通过HCI日志分析,我了解到完整的通信协议栈:
应用层: Scene_Control{"name":"mix_record","open":true}
↓
传输层: RFCOMM (蓝牙串口仿真协议)
↓
数据链路层: L2CAP
↓
物理层: 蓝牙HCI
2. 关键发现
- 场景名称 :
mix_record表示混合录制(可能同时录制AR画面和音频) - 控制参数: 只需要简单的开关控制
- 系统目标 : 发送到
Sys系统服务
3. 错误处理
代码中完整处理了CXR API返回的各种状态:
REQUEST_SUCCEED: 请求成功REQUEST_FAILED: 请求失败REQUEST_WAITING: 设备未就绪
使用注意事项
1. 权限要求
在AndroidManifest.xml中添加必要权限:
xml
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.bluetooth" android:required="true" />
2. 设备连接状态
确保设备已正确连接:
kotlin
if (CxrApi.getInstance().isConnected()) {
// 设备已连接,可以控制
} else {
// 设备未连接,需要先连接
Toast.makeText(this, "请先连接Rokid眼镜", Toast.LENGTH_SHORT).show()
}
3. 录屏文件位置
录制的视频默认保存在:
/sdcard/ScreenRecorder/vid-{timestamp}.mp4
总结与展望
通过这次探索,我成功实现了以下目标:
✅ 已实现功能
- 通过蓝牙HCI日志分析找到了AR录屏的控制协议
- 利用现有CXR API实现了AR录屏控制
- 提供了完整的开始/停止录屏接口
- 完善了错误处理和状态反馈
🔮 未来展望
- 探索更多AR场景控制功能
- 研究视频流实时处理
- 开发AR内容创作工具链
- 构建AR应用开发框架
致谢
感谢Rokid提供的硬件平台和CXR SDK,虽然某些功能没有直接提供API,但通过深入的技术探索,我们仍然能够实现所需的功能。
希望这篇文章能够帮助到其他需要AR录屏功能的开发者。如果你有任何问题或改进建议,欢迎在评论区留言交流!