跳转至

音量组(API 1.2)

最后更新:

契约状态 值
引入版本 EvccApi 1.2,EVCC 3.2.17
稳定性 稳定公开接口
弃用状态 未弃用

音量组接口面向车机上的第三方 Android 应用,通过 EVCC 已有 CarAudio 链路查询、读取、设置和 增减音量。第三方不需要 Car API 或 Shell 权限;仍须由用户在 EVCC 中授予开放 API 权限。 具体可用组由车机系统决定,组号不能固定解释为媒体、导航或通话。此接口不是网络 API。

接入与授权

先确认运行时 apiMajor == 1 && apiMinor >= 2,再检查当前会话权限。

权限 方法 新授权预设
volume.read 查询、读取 只读、标准联动、高级控制
volume.control 设置、增减、预检查 标准联动、高级控制

两项权限彼此独立,不依赖 property.write、music.control 或 Shell。升级不会自动扩展已有授权; 用户需要主动选择预设或勾选新权限并保存。权限变化会结束旧会话,客户端重新绑定后读取真实权限集合。

queryCapabilities() 提供 volume.group.query、volume.group.read、volume.group.set、volume.group.adjust 四个能力 ID。 其中 available 表示当前接口存在且已授权,不代表车型已通过音量查询;后端支持以实际业务状态为准。 能力查询本身不会启动 RootService。查询音量组或执行音量请求时才按需连接既有音量链路。

四个同步接口

所有音量调用均应在工作线程执行。

EvccVolumeGroupsResult queryVolumeGroups();
EvccVolumeGroupState readVolumeGroup(int groupId);
EvccVolumeWriteResult setVolumeGroup(in EvccVolumeSetRequest request);
EvccVolumeWriteResult adjustVolumeGroup(in EvccVolumeAdjustRequest request);

查询成功返回 AVAILABLE 和 groups;每组包含 groupId、current、min、max。 先查询实际组号再操作。音量值使用该组自身的整数刻度,不统一转换为百分比。 负组号返回 INVALID_ARGUMENT,不存在的组返回 NOT_FOUND。最多返回 256 个组。

withContext(Dispatchers.IO) {
    val groups = client.queryVolumeGroups()
    if (groups.status == EvccApiContract.Status.AVAILABLE) {
        val group = groups.groups.firstOrNull() ?: return@withContext
        val result = client.adjustVolumeGroup(
            EvccVolumeAdjustRequest(
                requestId = UUID.randomUUID().toString(),
                groupId = group.groupId,
                delta = 1,
            )
        )
        if (result.status == EvccApiContract.Status.OK) {
            // result.target 是已下发目标;需要当前系统值时调用 readVolumeGroup。
        }
    }
}

写入目标、读取和预检查

绝对设置使用 value,增减使用有符号 delta,超出范围时限幅到该组的 min..max。 写入成功的 OK 表示底层设置调用返回,不证明已回读,也不证明扬声器实际响度。 返回的 target 是限幅后的下发目标,不提供一个误称为实测值的 actual 字段。 读取成功的 current 才是这次系统读取值。

连续增减复用 500 毫秒的短期目标基线,每次接受的请求仍执行一次真实设置,不合并公共请求。 显式读取会刷新该基线;暂停超过 500 毫秒后的首次调整重新读取系统值。其他入口同时调节时, 客户端应通过显式读取重新建立基线。

请求设置 validateOnly = true 时,验证权限、组和目标范围,返回预检查目标但不写入。 requestId 最多 128 字符,不能包含控制字符;允许空字符串,推荐使用唯一 ID 方便排查。 预检查不会锁定后续系统状态,也不会替下一次调用保留授权。

失败、配额与生命周期

按 status 分支,message 只用于展示。常见状态:UNSUPPORTED、UNAVAILABLE、NOT_FOUND、 INVALID_ARGUMENT、PERMISSION_DENIED、RATE_LIMITED、TIMEOUT、FAILED、SESSION_CLOSED。 没有该车型接口为不支持;未连接或服务暂不可用是不可用,两者不要混同。

读请求使用独立 UID 配额:突发 10 次、每秒补充 2 次;写请求突发 60 次、每秒补充 30 次。 预检查使用读取配额。多个会话共享 UID 配额,并受每 UID 4 个、全局 12 个同步调用并发上限约束。

写入发生超时或 Binder/传输断连时,结果可能不确定。SDK 和服务不自动重放音量写入;尤其不要直接 重发相对增减,否则可能重复加减。恢复连接后先读系统值,再根据新状态生成新的用户操作。 请求 ID 是关联标识,不是服务端幂等键。SDK 连接旧 API 1.0/1.1 时返回 UNSUPPORTED,不发送新增事务。

音量运行时只持有自己的连接,空闲 30 秒、最后会话关闭或服务销毁后释放。首版没有音量订阅, Binder 重连后也不会恢复写入。不要把 RootService 连接成功或名称当作已取得 root 或车辆操作成功。

调试

EVCC 开放 API 控制台和 Demo 1.2.0 提供“音量组”入口,支持:

list
get 3
set 3 10
adjust 3 -1
validate set 3 10
validate adjust 3 1

示例中的组号必须替换成查询到的实际组号。Demo 支持 SDK 与 Raw AIDL 对照,执行写入前显示确认。 只读自检不会调整音量。公开源码包包含可编译的 Java/Kotlin 示例。