Skip to content

版本变更日志

V2.2.0-E(2026-6-5)

  • 手机端 SDK 版本com.rokid.security:phone.sdk:2.2.0-E
  • 眼镜端 SDK 版本com.rokid.security:glass3.open.sdk:2.2.0-E
  • 推荐 OTA 版本1.19.e002-20260603-150201 及以上

眼镜端接口变更

java
// IDeviceService.aidl
package com.rokid.security.system.server.device;
import com.rokid.security.system.server.device.listener.DeviceEventListener;
import com.rokid.security.system.server.device.listener.BatteryUpdateListener;
import com.rokid.security.system.server.device.listener.IAppVisibilityListener;
import com.rokid.security.system.server.device.listener.IWifiOperationCallback;
import com.rokid.security.glass3.sdk.base.data.device.bean.DeviceStatusInfo;
import com.rokid.security.glass3.sdk.base.data.device.bean.AppPackageInfo;
import com.rokid.security.glass3.sdk.base.data.device.bean.GlassAppConfig;
import com.rokid.security.glass3.sdk.base.data.device.wifi.WifiConnectRequest;
import com.rokid.security.glass3.sdk.base.data.device.wifi.WifiRemoveRequest;
import com.rokid.security.glass3.sdk.base.data.device.wifi.WifiNetworkInfo;

// Declare any non-default types here with import statements

interface IDeviceService {
    /**
     * 连接指定 Wi-Fi。
     *
     * 支持的安全类型:
     * - open: WifiConnectRequest.SECURITY_OPEN
     * - WEP: WifiConnectRequest.SECURITY_WEP,仅用于兼容老旧 AP
     * - WPA/WPA2-PSK: WifiConnectRequest.SECURITY_WPA_PSK
     * - WPA3-Personal/SAE: WifiConnectRequest.SECURITY_WPA3_SAE
     * - WPA/WPA2-Enterprise: WifiConnectRequest.SECURITY_ENTERPRISE
     * - WPA3-Enterprise: WifiConnectRequest.SECURITY_WPA3_ENTERPRISE
     * - WPA2/WPA3 自动模式: WifiConnectRequest.SECURITY_AUTO_PSK,服务端先尝试 SAE,失败后降级 PSK
     *
     * 调用注意:
     * - request.ssid 必填,且不需要调用方额外添加双引号。
     * - PSK/SAE 密码长度需为 8-63 位,或 64 位十六进制 PSK。
     * - Enterprise 场景需要传 request.enterprise;建议配置 CA 证书和 domainSuffixMatch。
     * - callback 可为空;若不为空,会收到阶段回调和最终结果。
     * - 操作由 system-server 异步执行,方法返回不代表连接已经完成。
     *
     * @param request Wi-Fi 连接参数。
     * @param callback 操作进度和最终结果回调。
     * 该操作异步执行,结果通过 callback 返回。
     */
    void connectWifi(in WifiConnectRequest request, IWifiOperationCallback callback);

    /**
     * 移除指定 Wi-Fi 配置。
     *
     * 匹配优先级:
     * - request.networkId >= 0 时,优先按 networkId 精确移除。
     * - 否则按 ssid/bssid 匹配;同名 AP 建议同时传 bssid。
     * - 如果目标网络当前正在连接,disconnectIfCurrent=true 时会先断开再移除配置。
     *
     * @param request Wi-Fi 移除参数,networkId、ssid、bssid 至少传一个。
     * @param callback 操作进度和最终结果回调。
     * 该操作异步执行,结果通过 callback 返回。
     */
    void removeWifi(in WifiRemoveRequest request, IWifiOperationCallback callback);

    /**
     * 获取已连接过的 Wi-Fi 列表。
     *
     * 返回内容来自系统已保存 Wi-Fi 配置,并合并当前 Wi-Fi 连接信息。
     * 列表元素通过 WifiNetworkInfo.status 区分:
     * - STATUS_CURRENT: 当前已连接 Wi-Fi
     * - STATUS_CONNECTING: 当前正在连接 Wi-Fi
     * - STATUS_HISTORY: 历史连接/已保存配置,当前未连接
     *
     * 注意:
     * - 历史记录通常只有 ssid/networkId/securityType/hiddenSsid,bssid/rssi/ip 等实时字段可能为空或默认值。
     * - 如果系统限制 configuredNetworks 可见性,列表可能只包含当前连接信息。
     *
     * @return Wi-Fi 连接记录列表;无记录时返回空列表。
     */
    List<WifiNetworkInfo> getConnectedWifiList();

    /**
     * 获取当前正在连接或已经连接的 Wi-Fi 信息。
     *
     * 当 Wi-Fi 当前已连接时返回 STATUS_CURRENT;
     * 当系统正在连接目标 Wi-Fi 但尚未完成联网时返回 STATUS_CONNECTING;
     * 当当前没有 Wi-Fi 连接/连接中状态时返回 null。
     *
     * @return 当前 Wi-Fi 信息,未连接时返回 null。
     */
    WifiNetworkInfo getCurrentWifiInfo();

}

V2.1.9-E(2026-5-25)

  • 手机端 SDK 版本com.rokid.security:phone.sdk:2.1.9-E
  • 眼镜端 SDK 版本com.rokid.security:glass3.open.sdk:2.1.9-E
  • 推荐 OTA 版本1.17.e002-20260509-150201 及以上

眼镜端接口变更

1. 事件拦截接口

1.1 GlassSdk.setPrimaryEventListener()

位置: GlassSdk.kt

kotlin
@JvmStatic
fun setPrimaryEventListener(listener: DeviceEventListener?)

说明:

  • 设置主设备事件监听器
  • SDK 内部持有唯一 DeviceEventListener 槽位
  • 通过此方法注册的监听器会收到除 Leqi 拦截之外的所有事件

使用场景: 需要监听设备事件(如按键、电量等)但不想被乐奇拦截器干扰

1.2 GlassSdk.registerLeqiInterceptor()

位置: GlassSdk.kt

kotlin
@JvmStatic
fun registerLeqiInterceptor(context: Context, interceptor: LeqiInterceptor)

说明:

  • 注册乐奇语音指令拦截器
  • 应用在前台时,拦截器生效;退到后台后自动失效
  • 建议在 Activity.onCreate 中调用,onDestroy 中调用 unregisterLeqiInterceptor()

参数:

  • context: Android Context,用于生命周期管理
  • interceptor: 拦截器实现

使用示例:

kotlin
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        GlassSdk.registerLeqiInterceptor(this, object : LeqiInterceptor {
            override fun onLeqiInstruction(extra: String?): Boolean {
                // 返回 true 表示拦截,false 表示不拦截
                return handleCustomInstruction(extra)
            }
        })
    }
    
    override fun onDestroy() {
        GlassSdk.unregisterLeqiInterceptor()
        super.onDestroy()
    }
}
1.3 GlassSdk.unregisterLeqiInterceptor()

位置: GlassSdk.kt

kotlin
@JvmStatic
fun unregisterLeqiInterceptor()

说明:

  • 注销乐奇语音指令拦截器
  • 通常在 Activity.onDestroy 中调用
1.4 LeqiInterceptor 接口

位置: LeqiInterceptor.kt (新增文件)

kotlin
interface LeqiInterceptor {
    /**
     * 乐奇语音指令回调
     * @param extra 额外参数(JSON 格式)
     * @return true 表示拦截该指令,false 表示放行
     */
    fun onLeqiInstruction(extra: String?): Boolean
}

说明:

  • 定义乐奇语音指令拦截器接口
  • 应用可实现此接口自定义语音指令处理逻辑

2. CameraShareHelper 配置切换相关

2.1 CameraShareHelper.restartSurfaceWithConfig()

位置: CameraShareHelper.kt

kotlin
fun restartSurfaceWithConfig(config: CameraShareConfig, callback: SurfaceCallback)

说明:

  • 重要: 在同一 callbackId 下切换配置,避免新建 Helper 导致 system-server 残留多个 Surface session
  • 内部先调用 releaseSurface() 再调用 initSurfaceWithConfig()
  • 必须在 GL 线程调用

参数:

  • config: 新的相机配置(分辨率、帧率、防抖、zoom)
  • callback: 回调接口

使用场景:

  • 动态切换相机分辨率或帧率
  • 避免创建多个 Helper 实例导致内存泄漏

使用示例:

kotlin
// 初始配置
val config1 = CameraShareConfig(
    previewWidth = 1280,
    previewHeight = 720,
    previewTargetFps = 15,
    zoomLevel = 1
)
helper.initSurfaceWithConfig(config1, callback)

// 切换到新配置(复用同一个 helper)
val config2 = CameraShareConfig(
    previewWidth = 1920,
    previewHeight = 1080,
    previewTargetFps = 24,
    zoomLevel = 2
)
helper.restartSurfaceWithConfig(config2, callback)

注意事项:

  • ⚠️ 必须在 GL 线程调用(与 initSurfaceWithConfig 相同线程)
  • ⚠️ 不要创建多个 CameraShareHelper 实例来切换配置
2.2 CameraShareHelper.restartNv21ExportWithConfig()

位置: CameraShareHelper.kt

kotlin
fun restartNv21ExportWithConfig(enableMix: Boolean, config: CameraShareConfig, callback: Nv21Callback)

说明:

  • 在同一 callbackId 下切换 NV21 导出配置,避免多 Helper 残留 session
  • 内部先调用 releaseNv21Export() 再调用 initNv21ExportWithConfig()

参数:

  • enableMix: 是否启用 Mix 模式(camera + screen 叠加)
  • config: 新的相机配置
  • callback: NV21 回调接口

使用场景:

  • 动态切换 NV21 导出的分辨率或帧率
  • 避免创建多个 Helper 实例导致内存泄漏

3. 状态查询 API

3.1 CameraShareHelper.isSurfaceActive()

位置: CameraShareHelper.kt

kotlin
fun isSurfaceActive(): Boolean

说明:

  • 检查 Surface 共享是否处于活跃状态
  • 返回 true 表示 Surface 已初始化且未释放

使用场景:

  • 在切换配置前检查当前状态
  • 避免重复初始化或释放
3.2 CameraShareHelper.isNv21Active()

位置: CameraShareHelper.kt

kotlin
fun isNv21Active(): Boolean

说明:

  • 检查 NV21 导出是否处于活跃状态
  • 返回 true 表示 NV21 导出已初始化且未释放

使用场景:

  • 在切换配置前检查当前状态
  • 资源清理时的状态判断

4. 重点说明

1. 内存泄漏修复相关 API

背景: 之前版本存在 Surface Session 重复创建导致内存泄漏的问题

解决方案:

  • 新增 restartSurfaceWithConfig()restartNv21ExportWithConfig()
  • 这两个方法会在同一 callbackId 下复用 session,避免创建多个 session

迁移建议:

kotlin
// ❌ 旧方式(会导致内存泄漏)
var helper = CameraShareHelper()
helper.initSurfaceWithConfig(config1, callback)
// ... 需要切换配置时
helper.releaseSurface()
helper = CameraShareHelper()  // 创建新实例 ← 问题所在
helper.initSurfaceWithConfig(config2, callback)

// ✅ 新方式(推荐)
val helper = CameraShareHelper()
helper.initSurfaceWithConfig(config1, callback)
// ... 需要切换配置时
helper.restartSurfaceWithConfig(config2, callback)  // 复用 helper
2. 乐奇拦截器使用注意事项

生命周期管理:

  • 拦截器只在应用前台时生效
  • 使用 LifecycleOwner 自动管理,无需手动启停
  • 但建议在 onDestroy 中调用 unregisterLeqiInterceptor() 确保清理

拦截逻辑:

kotlin
GlassSdk.registerLeqiInterceptor(this, object : LeqiInterceptor {
    override fun onLeqiInstruction(extra: String?): Boolean {
        return try {
            val json = JSONObject(extra ?: "{}")
            val command = json.optString("command")
            
            when (command) {
                "take_photo" -> {
                    // 自定义拍照逻辑
                    takePhoto()
                    true  // 拦截,不让乐奇处理
                }
                else -> false  // 不拦截,交给乐奇处理
            }
        } catch (e: Exception) {
            false  // 解析失败,不拦截
        }
    }
})
3. 配置变更回调的使用

虽然本次没有新增回调方法,但现有的回调现在会被正确触发:

SurfaceCallback:

kotlin
object : CameraShareHelper.SurfaceCallback {
    override fun onSurfaceShareConfigChanged(
        width: Int, 
        height: Int, 
        appliedPreviewFps: Int, 
        videoStabilizationEnabled: Boolean
    ) {
        // 当配置变更时会自动回调
        Log.d(TAG, "Config changed: ${width}x${height}@${appliedPreviewFps}fps")
    }
    
    override fun onZoomLevelChanged(zoomLevel: Int) {
        // Zoom 等级变更时回调
        Log.d(TAG, "Zoom changed: $zoomLevel")
    }
}

Nv21Callback:

kotlin
object : CameraShareHelper.Nv21Callback {
    override fun onNv21ExportResolutionChanged(
        width: Int, 
        height: Int, 
        appliedPreviewFps: Int
    ) {
        // NV21 导出分辨率变更时回调
    }
    
    override fun onNv21ExportRuntimeParamsChanged(
        appliedPreviewFps: Int, 
        videoStabilizationEnabled: Boolean
    ) {
        // 运行时参数变更时回调
    }
    
    override fun onZoomLevelChanged(zoomLevel: Int) {
        // Zoom 等级变更时回调
    }
}

V2.1.8-E(2026-5-9)

  • 手机端 SDK 版本com.rokid.security:phone.sdk:2.1.8-E
  • 眼镜端 SDK 版本com.rokid.security:glass3.open.sdk:2.1.8-E-20260518.101638-5
  • 推荐 OTA 版本1.17.e002-20260509-150201 及以上

手机端接口变更

WiFi P2P H264 解码控制(核心改动)

手机端接收 H264 时,默认仍自动转 NV21,外部调用方可通过 SDK 关闭 在 IWifiP2PClientOperate 接口中新增:

kotlin
// 设置是否自动将 H264 解码为 NV21(默认开启)
fun setAutoDecodeH264ToNv21(enable: Boolean)

// 查询当前是否开启 H264 自动解码为 NV21
fun isAutoDecodeH264ToNv21Enabled(): Boolean

功能说明:

  • 默认行为: 保持向后兼容,默认开启 H264 自动解码为 NV21
  • 性能优化: 当应用只需要 H264 数据时,可以关闭自动解码,节省 CPU 和内存
  • 灵活控制: 外部调用方可以根据实际需求动态开关

使用场景:

kotlin
// 场景1: 只需要 H264 流进行网络传输,关闭自动解码
wifiP2PClientService?.setAutoDecodeH264ToNv21(false)

// 场景2: 需要 NV21 数据进行 AI 识别,开启自动解码(默认)
wifiP2PClientService?.setAutoDecodeH264ToNv21(true)

GlassVideoStreamParam 数据类

kotlin
class GlassVideoStreamParam{
    var fps = 20
    var bitrate = 5184000
    /** 为 true 时本次视频流使用 AR 叠加编码(与眼镜端 USE_AR_MIX 一致),默认关闭 */
    var isARMixEnabled = false
    /** 期望的视频流宽度,-1 表示使用眼镜端默认分辨率 */
    var width = -1
    /** 期望的视频流高度,-1 表示使用眼镜端默认分辨率 */
    var height = -1
}

IDevice 接口扩展

requestVideoStream 方法中增加参数:

kotlin
fun requestVideoStream(
    tag: String,
    videoStreamParam: GlassVideoStreamParam = GlassVideoStreamParam(),
    callback: (isSuccess: Boolean) -> Unit
)

功能说明:

  • 支持手机端请求眼镜端摄像头数据时指定自定义分辨率
  • 与 open-sdk 的 CameraShareConfig 配合使用,实现端到端的自定义分辨率控制
  • 默认值为 0 时表示使用系统默认配置,保持向后兼容

使用示例:

kotlin
// 请求 1280x720@30fps 的视频流
val extra = GlassVideoStreamParam(width = 1280, height = 720, fps = 30)
deviceService?.requestVideoStream("my_tag", extra) { success ->
    if (success) {
        // 开始接收视频流
    }
}

眼镜端接口变更

GlassSdk.kt 增强

  • 新增兼容方法:为离线指令服务添加了三个兼容性方法,确保新旧版本 SDK 之间的向后兼容:
    • setOfflineCmdLanguage(language: String): Boolean - 设置离线指令语言
    • setOfflineCmdWords(language: String, voiceActions: List<VoiceAction>): Boolean - 按语言覆盖离线指令词
    • clearOfflineCmdWords(language: String): Boolean - 清空某语言下的离线指令词

这些方法通过 try-catch 机制处理新旧 system-server 版本的兼容性问题。

CameraShareHelper.kt 新功能

  • 配置化相机共享:新增支持配置的相机共享方法

    • initSurfaceWithConfig(config: CameraShareConfig, callback: SurfaceCallback) - 可配置的 Surface 共享初始化
    • initNv21ExportWithConfig(enableMix: Boolean, config: CameraShareConfig, callback: Nv21Callback) - 可配置的 NV21 导出
  • 动态配置变更通知:新增回调方法支持运行时配置变更

    • onSurfaceShareConfigChanged(width: Int, height: Int, appliedPreviewFps: Int, videoStabilizationEnabled: Boolean) - Surface 共享配置变更通知
    • onNv21ExportResolutionChanged(width: Int, height: Int, appliedPreviewFps: Int) - NV21 导出分辨率变更通知
    • onNv21ExportRuntimeParamsChanged(appliedPreviewFps: Int, videoStabilizationEnabled: Boolean) - NV21 导出运行时参数变更
  • Zoom 功能支持:新增 Zoom 等级变更回调

    • onZoomLevelChanged(zoomLevel: Int) - Zoom 等级变更通知(在 SurfaceCallback 和 Nv21Callback 中均支持)
  • 获取支持的预览分辨率:新增方法获取 Camera API 支持的预览分辨率列表

    • getSupportedPreviewSizes(): List<Triple<Int, Int, Boolean>> - 获取支持的预览分辨率(camera sensor orientation 是旋转270°的,因此和initSurfaceWithConfig以及initNv21ExportWithConfig中传入的分辨率宽高是对调的 )

IDeviceService.aidl 新增接口

javascript
interface IDeviceService {
    
      /**
       * 设置拍摄灯光
       * @param timestamp 时间戳
        */
     void setCameraLedEnable(boolean enable);


      /**
       * 设置网络访问方式 0 手机访问; 1 glass 访问
       * @param timestamp 时间戳
        */
     void setNetworkType(int type);



     int getNetworkType();


    /**
     * 配置应用可见性与第三方应用显示顺序
     * 用于批量配置系统内置应用和第三方应用的显示/隐藏状态。
     *
     * @param appConfig 应用配置信息,包含:
     *                  - appList: 需要隐藏的系统内置应用列表
     *                  - thirdApps: 第三方应用列表,将显示在最前面
     * @param callback 设置结果回调,success=true 表示设置成功,false 表示设置失败
     *
     */
     void configureAppVisibility(in  GlassAppConfig appConfig, IAppVisibilityListener callback);

    /**
     * 设置时间同步服务器地址
     * 支持HTTP/HTTPS协议和NTP协议,根据URL自动识别协议类型
     *
     * @param serverUrl 时间服务器地址,支持以下格式:
     *                  - HTTP/HTTPS协议: https://time.example.com 或 http://time.example.com
     *                  - NTP协议: ntp.example.com 或 192.168.1.100
     *                  - null或空字符串: 使用默认的NTP协议和公共NTP服务器
     *
     * @note 如果URL以http://或https://开头,则使用HTTP协议获取时间
     *       否则使用NTP协议(标准UDP协议,端口123)
     */
    void setTimeServer(String serverUrl);

    /**
     * 获取当前配置的时间服务器地址
     *
     * @return 当前配置的时间服务器地址,如果未配置则返回null
     */
    String getTimeServer();
}

IMediaServer.aidl 新增接口

java
interface IMediaServer {
  /**
     * 开始跨进程Surface共享(仅渲染camera画面到Surface,不含NV21数据)
     * @param surface 客户端创建的Surface,用于接收相机画面
     * @param callback 生命周期回调
     */
    void startCameraShare(in Surface surface, ICameraSurfaceCallback callback);

    /**
     * 停止跨进程Surface共享
     * @param callback 之前注册的回调
     */
    void stopCameraShare(ICameraSurfaceCallback callback);

    /**
     * 开始NV21数据导出(通过SharedMemory双缓冲共享帧数据)
     * @param callback 回调接口,通过onNv21FrameAvailable接收帧数据
     * @param enableMix 是否启用叠加模式(camera + screen叠加),
     *                  false: 导出纯camera的NV21数据
     *                  true:  导出camera叠加屏幕内容后的NV21数据
     */
    void startCameraNv21Export(ICameraShareCallback callback, boolean enableMix);

    /**
     * 停止NV21数据导出
     * @param callback 之前注册的回调
     */
    void stopCameraNv21Export(ICameraShareCallback callback);

    /**
     * 关闭相机
     * @param callback 回调接口,true关闭相机成功,false相机未关闭
     */
    void closeCamera(ICameraCloseCallback callback);

    /**
     * 开始NV21导出(可指定预览分辨率、目标帧率、防抖;与旧接口二进制兼容由客户端选择调用)。
     * 多会话共享同一物理相机时,后发起的配置会抢占管线;已有会话通过
     * {@link com.rokid.security.system.server.media.callback.ICameraShareCallback#onNv21ExportResolutionChanged}
     * 或 {@link com.rokid.security.system.server.media.callback.ICameraShareCallback#onNv21ExportRuntimeParamsChanged} 同步。
     */
    void startCameraNv21ExportWithConfig(ICameraShareCallback callback, boolean enableMix, in CameraShareConfig config);

    /**
     * 开始跨进程Surface共享(可配置版本)
     * @param surface 客户端创建的Surface,用于接收相机画面
     * @param callback 生命周期回调
     * @param enableMix 是否启用AR Mix模式(camera + screen叠加)
     * @param config 配置项,与 CameraShareConfig 一致
     */
    void startCameraShareWithConfig(in Surface surface, ICameraSurfaceCallback callback, boolean enableMix, in CameraShareConfig config);

    /**
     * 获取 Camera API 支持的预览分辨率列表
     * @return 支持的分辨率列表(Camera 原始分辨率,横屏方向)
     */
    List<CameraSize> getSupportedPreviewSizes();
}

ICameraSurfaceCallback.aidl 新增接口

java
/**
 * 跨进程Surface共享的轻量回调(仅生命周期,不含NV21数据)
 */
interface ICameraSurfaceCallback {

    /**
     * 相机已打开
     * @param width 相机宽度
     * @param height 相机高度
     */
    void onCameraOpened(int width, int height);

    /**
     * 相机已关闭
     */
    void onCameraClosed();

    /**
     * 发生错误
     * @param code 错误码
     * @param msg 错误信息
     */
    void onError(int code, String msg);

    /**
     * 回调唯一标识
     */
    String getCallbackId();

    /**
     * Surface共享配置已变更(分辨率、帧率、防抖等)
     * 当通过 startCameraShareWithConfig 更新配置时触发,避免重启相机
     * @param width 新的宽度
     * @param height 新的高度
     * @param appliedPreviewFps 协商后的帧率
     * @param videoStabilizationEnabled 防抖是否启用
     */
    void onSurfaceShareConfigChanged(int width, int height, int appliedPreviewFps, boolean videoStabilizationEnabled);

    /**
     * Zoom 等级已变更
     * @param zoomLevel 当前的 zoom 等级(整数)
     */
    void onZoomLevelChanged(int zoomLevel);
}

ICameraShareCallback.aidl 新增接口

java
interface ICameraShareCallback {

    /**
     * 相机已打开,提供分辨率和NV21双缓冲SharedMemory
     * @param width 相机宽度
     * @param height 相机高度
     * @param nv21Buffer0 NV21双缓冲区0
     * @param nv21Buffer1 NV21双缓冲区1
     */
    void onCameraOpened(int width, int height, in SharedMemory nv21Buffer0, in SharedMemory nv21Buffer1);

    /**
     * 新的NV21帧已写入指定的缓冲区
     * @param bufferIndex 缓冲区索引 (0 或 1)
     * @param width 帧宽度
     * @param height 帧高度
     * @param timestamp 帧时间戳(毫秒)
     */
    void onNv21FrameAvailable(int bufferIndex, int width, int height, long timestamp);

    /**
     * 相机已关闭
     */
    void onCameraClosed();

    /**
     * 发生错误
     * @param code 错误码
     * @param msg 错误信息
     */
    void onError(int code, String msg);

    /**
     * 回调唯一标识
     */
    String getCallbackId();
    /**
     * 新的NV21帧已写入指定的缓冲区(异步版本,性能更优)
     * @param bufferIndex 缓冲区索引 (0 或 1)
     * @param width 帧宽度
     * @param height 帧高度
     * @param timestamp 帧时间戳(毫秒)
     */
    oneway void onNv21FrameAvailableAsync(int bufferIndex, int width, int height, long timestamp);
    /**
     * NV21 输出尺寸或 SharedMemory 缓冲区已切换(多应用抢占管线、或会话主动变更配置)。
     * 客户端应关闭旧映射,使用新的 SharedMemory 重新 map,其后的 {@link #onNv21FrameAvailable} 以本回调的宽高为准。
     *
     * @param width NV21 逻辑宽度
     * @param height NV21 逻辑高度
     * @param nv21Buffer0 新双缓冲 0
     * @param nv21Buffer1 新双缓冲 1
     * @param appliedPreviewFps 经设备协商后的预览 AE 目标帧率区间上界(代表性值)
     */
    void onNv21ExportResolutionChanged(int width, int height, in SharedMemory nv21Buffer0, in SharedMemory nv21Buffer1, int appliedPreviewFps);

    /**
     * 输出尺寸未变,但预览帧率或防抖开关因管线重配置发生变化。
     *
     * @param appliedPreviewFps 协商后的预览帧率代表性值(AE 区间上界)
     * @param videoStabilizationEnabled 当前是否请求开启视频防抖
     */
    void onNv21ExportRuntimeParamsChanged(int appliedPreviewFps, boolean videoStabilizationEnabled);

    /**
     * Zoom 等级已变更
     * @param zoomLevel 当前的 zoom 等级(整数)
     */
    void onZoomLevelChanged(int zoomLevel);
}

V2.1.7-E(2026-4-7)

  • 手机端 SDK 版本com.rokid.security:phone.sdk:2.1.7-E
  • 眼镜端 SDK 版本com.rokid.security:glass3.open.sdk:2.1.7-E
  • 推荐 OTA 版本1.11.e003-20260331-150201 及以上

手机端接口变更

移除了 RTC 模块:删除了 EngineParam.ktMobileEngineServerImpl.kt(分别在 sdk-basesdk-server 目录下)中所有与 RTC 相关的引擎参数和初始化配置。也就是说,SDK 不再包含实时音视频通话相关功能。

手机端接口新增AR录制

IWifiP2PClientOperate 接口中新增了 getIARMixControl() 方法,返回 IARMixControl 对象。集成方可通过 PSecuritySDK.getWifiP2PClientService() 获取 P2P 能力对象,再调用 getIARMixControl() 获取 AR 录制控制接口,从而在手机端对 AR 录制进行设置(如开启/关闭、参数调整等)。

使用示例 1

kotlin
private val mIARMixControl by lazy {
    PSecuritySDK.getWifiP2PClientService()?.getIARMixControl()
}

// 设置 AR 混录开关
binding.switchArMix.setOnCheckedChangeListener { _, isChecked ->
    if (GlobalData.btConnectState.value) {
        mIARMixControl?.setARMixEnabled(isChecked) { success ->
            if (!success) {
                L.i(TAG, "setARMixEnabled: Fail")
                getARMixState()
            }
        }
    } else {
        Toast.makeText(this, "请先完成设备蓝牙连接", Toast.LENGTH_LONG).show()
    }
}

// 获取 AR 混录状态
private fun getARMixState() {
    if (GlobalData.btConnectState.value) {
        val activityRef = WeakReference(this)
        mIARMixControl?.getARMixState(
            action = { isOpen ->
                activityRef.get()?.runOnUiThread {
                    L.i(TAG, "getARMixState: $isOpen")
                }
            },
            onFail = { errMsg, code ->
                activityRef.get()?.runOnUiThread {
                    L.i(TAG, "getARMixState: onFail --- errMsg=$errMsg")
                }
            }
        )
    }
}

使用示例 2

kotlin
class GlassVideoStreamParam {
    var fps = 20                     // 帧率
    var bitrate = 5184000            // 视频比特率
    /**
     * 是否启用 AR 叠加模式(相机画面 + 屏幕画面)
     * 为 true 时,通过 P2P 获取的视频流为相机叠加屏幕内容后的实时画面
     * 默认值为 false
     */
    var isARMixEnabled = false
}

// 请求视频流
val param = GlassVideoStreamParam().apply {
    this.fps = fps
    this.bitrate = bitrate
    this.isARMixEnabled = true
}
PSecuritySDK.getAbsDeviceInfoService()?.requestVideoStream(VIDEO_TAG, videoStreamParam = param) {}

眼镜端接口变更

IMediaServer新增如下四个接口

kotlin
public interface IMediaServer extends IInterface {
	/**
     * 开始跨进程Surface共享(仅渲染camera画面到Surface,不含NV21数据)
     * @param surface 客户端创建的Surface,用于接收相机画面
     * @param callback 生命周期回调
     */
    void startCameraShare(in Surface surface, ICameraSurfaceCallback callback);

    /**
     * 停止跨进程Surface共享
     * @param callback 之前注册的回调
     */
    void stopCameraShare(ICameraSurfaceCallback callback);

    /**
     * 开始NV21数据导出(通过SharedMemory双缓冲共享帧数据)
     * @param callback 回调接口,通过onNv21FrameAvailable接收帧数据
     * @param enableMix 是否启用叠加模式(camera + screen叠加),
     *                  false: 导出纯camera的NV21数据
     *                  true:  导出camera叠加屏幕内容后的NV21数据
     */
    void startCameraNv21Export(ICameraShareCallback callback, boolean enableMix);

    /**
     * 停止NV21数据导出
     * @param callback 之前注册的回调
     */
    void stopCameraNv21Export(ICameraShareCallback callback);
}

使用方式可参考 Demo 示例中的 SendMessageActivity 类。

增加 IMediaServer 接口参数

startRecord 方法中新增 isArRMixEnabled 参数(通过在 RecordConfig 中增加该字段实现),用于控制是否开启 AR 混录功能。

kotlin
@Keep
@Parcelize
data class RecordConfig(
    val path: String,
    val min: Int,
    val enableAudio: Boolean,
    val width: Int = 1280,
    val height: Int = 720,
    val fps: Int = 20,
    /**
     * 本次录制是否启用 AR 叠加(相机画面 + 屏幕画面)。
     * 默认值为 false,旧客户端不传该字段时保持 false。
     * 实际生效时,眼镜端会与手机端的「AR 录屏」持久开关合并处理。
     */
    val isArRMixEnabled: Boolean = false,
) : Parcelable {
    override fun toString(): String {
        return "RecordConfig(path='$path', min=$min, enableAudio=$enableAudio, width=$width, height=$height, fps=$fps, isArRMixEnabled=$isArRMixEnabled)"
    }
}

使用示例可参考 Demo 示例中的 SdkMediaActivity 类。

V2.1.5-E(2026-2-5)

  • 手机端 SDK 版本com.rokid.security:phone.sdk:2.1.5-E
  • 眼镜端 SDK 版本com.rokid.security:glass3.open.sdk:2.1.5-E
  • 推荐 OTA 版本1.11.e003-20260131-150201 及以上

手机端接口变更

IBTRingClientListener 接口新增方法:

kotlin
interface IBTRingClientListener {

    /***
     * 蓝牙连接状态回调
     * @param extra 回调的参数
     */
    fun onConnect(extra: RingExtra)

}

眼镜端接口变更

IDeviceService 接口新增方法:

kotlin
void setSystemTime(long var1) throws RemoteException;

// 使用示例,在sdk初始化成功之后,设置眼镜端系统时间
GlassSdk.getGlassDeviceService()?.setSystemTime(1770014682490)

V2.1.04-E(2026-1-16)

  • 手机端 SDK 版本com.rokid.security:phone.sdk:2.1.04-E
  • 眼镜端 SDK 版本com.rokid.security:glass3.open.sdk:2.1.04-E
  • 推荐 OTA 版本1.11.e002-20260116-150201 及以上

新增功能

  • 国标/RTC支持横屏1080p显示
  • 新增扫一扫链接 WiFi应用,WiFi 二维码生成工具
  • 眼镜端新增蓝牙、app连接、低电量提示音
  • 手机端新增默认开启应用配置,选择后,眼镜开机默认进入该应用
  • 修复移除单个离线语音指令

手机端接口变更

IDevice 接口新增方法:

kotlin
package com.rokid.security.phone.sdk.api.device

import com.rokid.security.sdk.base.common.GlassVideoStreamParam
import com.rokid.security.sdk.base.common.out.GlassDeviceInfo


interface IDevice {

	/**
     * 请求拉取眼镜端视频流
     * @param tag 请求视频流标识, 用于取消请求视频流
     * @param videoStreamParam  修改视频帧率
     * @param callback true请求视频流成功,false请求视频流失败
     */
    fun requestVideoStream(tag: String,videoStreamParam: GlassVideoStreamParam = GlassVideoStreamParam(),callback: (isSuccess: Boolean) -> Unit)

    /**
     * 停止拉取眼镜端视频流
     * @param tag 停止视频流标识, 用于取消停止视频流
     * @param callback true停止视频流成功,false停止视频流失败
     */
    fun stopVideoStream(tag: String,callback: (isSuccess: Boolean) -> Unit)
    /**
     * 请求拉取眼镜端音频流
     * @param tag 音频流标识, 用于取消请求音频流
     * @param callback true请求音频流成功,false请求音频流失败
     */
    fun requestAudioStream(tag: String,callback: (isSuccess: Boolean) -> Unit)
    /**
     * 停止拉取眼镜端音频流
     * @param tag 音频流标识, 用于取消停止音频流
     * @param callback true停止音频流成功,false停止音频流失败
     */
    fun stopAudioStream(tag: String,callback: (isSuccess: Boolean) -> Unit)
}

IFileOperate 接口新增方法:

kotlin
package com.rokid.security.phone.sdk.api.msg.api

import com.rokid.security.phone.sdk.api.msg.listener.FileReceiveListener
import com.rokid.security.phone.sdk.api.msg.listener.FileReceiveV2Listener
import com.rokid.security.phone.sdk.api.msg.listener.IMessageListener
import com.rokid.security.phone.sdk.base.data.callback.IResult
import java.io.File

/**
 * Created by wjm on 2025/5/9
 */
interface IFileOperate {
   
    /**
     *  添加本端文件接收的监听器
     *  @param listener
     */
    @Deprecated(
        message = "V2.1.4版本废弃,addFileReceiveV2Listener方法",
        replaceWith = ReplaceWith("addFileReceiveV2Listener(listener)"),
        level = DeprecationLevel.WARNING
    )
    fun addFileReceiveListener(listener: FileReceiveListener)

    /**
     * 移除本端文件接收的监听器
     *  @param listener
     */
    @Deprecated(
        message = "V2.1.4版本废弃,removeFileReceiveV2Listener方法",
        replaceWith = ReplaceWith("removeFileReceiveV2Listener(listener)"),
        level = DeprecationLevel.WARNING
    )
    fun removeFileReceiveListener(listener: FileReceiveListener)

    /**
     *  添加本端文件接收的监听器
     *  @param listener
     */
    fun addFileReceiveV2Listener(listener: FileReceiveV2Listener)

    /**
     * 移除本端文件接收的监听器
     *  @param listener
     */
    fun removeFileReceiveV2Listener(listener: FileReceiveV2Listener)

}

IBluetoothRing 接口修改方法:

kotlin
package com.rokid.security.phone.sdk.api.bluetooth.ring.api

import android.bluetooth.BluetoothDevice
import com.rokid.security.phone.sdk.api.bluetooth.classic.listener.IClassicBTClientListener

/**
 * Author: zhangshengwei
 * Date: 2025/6/24
 */
interface IBluetoothRing {

    /**
     * 开启经典蓝牙扫描
     * @param timeoutMillis 扫描超时时间设置
     * */
    fun startScan(
        deviceNameFilter:List<String> = listOf("D01"),
        timeoutMillis: Long = 20000L,
    ){}
}

眼镜端接口变更

ICommonInfoListener 接口新增方法:

kotlin
/**
 * Created by wjm on 2025/9/3
 */
interface ICommonInfoListener {

    /**
     * 眼镜端的配置信息
     */
    fun onConfig(config: String)
}

PreviewResolution 录制时视频文件对应的分辨率

kotlin
/**
 * 录制时视频文件对应的分辨率
 */
object PreviewResolution{
    val ResolutionInfo_720P  = ResolutionInfo("720P", 1280, 720) //预览
    val ResolutionInfo_1080P  = ResolutionInfo("1080P", 1080,1920) //预览

    // 新增横屏摄像头预览
    val ResolutionInfo_1080P_Land  = ResolutionInfo("1080P_Land", 1920, 1080) //预览
}

v2.1.2 (2025-12-15)

  • 手机端 SDK 版本com.rokid.security:phone.sdk:2.1.2-E
  • 眼镜端 SDK 版本com.rokid.security:glass3.open.sdk:2.1.2-E
  • 推荐 OTA 版本1.10.e001-20251215-150202 及以上

新增功能

  • 新增离线 TTS 语音小模型支持
  • 新增按键监听功能
  • 系统人脸识别算法升级为 NPU 加速,识别速度更快
  • 默认开发者模式

手机端接口变更

IWifiP2PClientOperate 接口新增方法:

kotlin
interface IWifiP2PClientOperate {
    /**
     * 获取 P2P 群组信息
     * @param action 回调函数,返回 WifiP2pGroup 对象
     */
    fun getGroupInfo(action: (group: WifiP2pGroup?) -> Unit)

    /**
     * 获取 P2P 连接策略管理实例
     * @return IP2PConnectControl 接口实例
     */
    fun getIP2PConnectControl(): IP2PConnectControl
}

IAIChat 接口新增方法

kotlin
interface IAIChat {
    /**
     * 移除 AI 聊天监听器
     */
    fun removeAiChatListener()

    /**
     * 获取运行时聊天记录
     * @return 可变的聊天记录列表
     */
    fun getRunTimeChatList(): MutableList<ChatBean>
}

眼镜端接口变更

GlassSdk 新增服务获取方法

kotlin
object GlassSdk {
    /**
     * 获取图像采集服务(人脸/车牌等)
     * @return ICollectService 实例
     */
    @JvmStatic
    fun getGlassCollectService(): ICollectService? {
        return getService(ServerType.COLLECT, ICollectService::class.java)
    }
    
    /**
     * 获取离线 TTS 管理服务
     * @return IOfflineTtsService 实例
     */
    @JvmStatic
    fun getGlassOfflineTtsService(): IOfflineTtsService? {
        return getService(ServerType.SERVICE_OFFLINE_TTS, IOfflineTtsService::class.java)
    }
}

新增 ICollectService 接口

kotlin
/**
 * 图像采集服务接口
 * 提供人脸、车牌等图像的采集、传输和查询功能
 */
interface ICollectService {
    
    /**
     * 启动图像采集
     * @param mode 采集模式
     */
    fun startCollect(mode: Int)
    
    /**
     * 停止图像采集
     */
    fun stopCollect()
    
    /**
     * 设置图像采集监听器
     * @param listener 采集监听器实例
     */
    fun setCollectListener(listener: IGlassCollectListener)
    
    /**
     * 移除图像采集监听器
     * @param listener 要移除的监听器实例
     */
    fun removeCollectListener(listener: IGlassCollectListener)
    
    /**
     * 发送人脸图片到指定目标
     * @param identifier 目标标识符(如设备ID、用户ID等)
     * @param param 采集参数,包含采集配置信息
     * @param callback 发送结果回调
     */
    fun sendFacePicture(identifier: String, param: CollectParam, callback: ICollectCallback)
    
    /**
     * 发送车牌识别图片到指定目标
     * @param identifier 目标标识符
     * @param platNo 车牌号码
     * @param callback 发送结果回调
     */
    fun sendLPRPicture(identifier: String, platNo: String, callback: ICollectCallback)
    
    /**
     * 切换采集模式
     * @param mode 新的采集模式
     */
    fun changeMode(mode: Int)
    
    /**
     * 获取人脸小图
     * @param frameId 帧ID
     * @param trackId 跟踪ID
     * @return 人脸小图Bitmap,获取失败时返回null
     */
    fun getFaceSmallBitmap(frameId: Long, trackId: Long): Bitmap?
    
    /**
     * 获取车牌小图
     * @param plateNo 车牌号码
     * @return 车牌小图Bitmap,获取失败时返回null
     */
    fun getLprSmallBitmap(plateNo: String): Bitmap?
}

新增 IOfflineTtsService 接口

kotlin
interface IOfflineTtsService {
    /**
     * 播放指定文本的语音
     * @param ttsMsg 需要播报的文本内容
     */
    fun playTtsMsg(ttsMsg: String)
}

IMediaServer 接口新增监听器管理方法

kotlin
interface IMediaServer {
    /**
     * 注册媒体服务状态监听器
     * @param listener 监听器实例
     */
    fun setMediaStateLister(listener: IMediaStateLister)

    /**
     * 注销媒体服务状态监听器
     * @param listener 监听器实例
     */
    fun removeMediaStateLister(listener: IMediaStateLister)
}

IOfflineRecServer 接口新增人脸识别结果上报方法

kotlin
interface IOfflineRecServer {
    /**
     * 上报人脸识别结果
     * @param info 人脸识别提交信息
     * @param face 人脸图像 Bitmap
     */
    fun submitRecognizedFaceInfo(info: RecognizeFaceSubmitInfo, face: Bitmap)
}