HarmonyOS鸿蒙Next中当通话用途时AVCastPicker组件在多次切换后出现切换无效

HarmonyOS鸿蒙Next中当通话用途时AVCastPicker组件在多次切换后出现切换无效 当音频输出为通话用途时,AVCastPicker组件刚开始可以正常切换音频输出设备,在多次切换后可能会出现切换无效。我可以提供实际的操作视频。

我专门写了一个测试的demo:https://gitee.com/chen_yi_ze/TestAVCastPicker/tree/master/

8 回复

开发者你好,测试您这边提供的demo发现,当音频输出为通话用途时,频繁切换输出设备没有出现切换无效的情况,请问是否可以提供详细的操作步骤或者视频。

更多关于HarmonyOS鸿蒙Next中当通话用途时AVCastPicker组件在多次切换后出现切换无效的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


上传操作视频了。

开发者你好, 查阅日志发现当avcastpicker的设备弹框改变时。 1、现象上:弹框样式变为了不接入avsession的样子。 2、日志上:发现avsession被垃圾回收,此时topsession为null。 3、代码上:查阅代码发现,

await avSession.createAVSession(this.getUIContext().getHostContext()!, 'VOIP', 'voice_call');
// 仅是一个临时变量,生命周期不稳定。
// 建议在struct内添加成员变量或其他方式,延长avsession对象的生命周期,使其更可控。
// 比如改成以下方式, 变量可用可不用, 防止被垃圾回收机制回收:
this.aaa = await avSession.createAVSession(this.getUIContext().getHostContext()!, 'VOIP', 'voice_call');

确实就是这个问题,感谢解答!

这是操作视频。

试下demo。

在HarmonyOS Next中,AVCastPicker组件在通话场景下多次切换后失效,通常是由于组件状态管理或事件监听机制异常导致。可能涉及组件生命周期未正确同步、事件回调未及时更新或系统资源未释放。建议检查组件的状态绑定与事件处理逻辑,确保切换操作能正确触发状态刷新与界面重绘。

根据您提供的描述和Demo代码,这是一个在特定场景下(通话用途)AVCastPicker组件可能出现的状态同步问题。

问题分析: 在音频路由策略为AudioRoutingManager.AudioDeviceUsage.CALL(通话用途)时,AVCastPicker组件内部维护的设备列表状态可能未与系统实际的音频路由状态保持同步。多次快速切换设备可能导致组件内部状态“卡住”,无法响应后续的正确路由变更事件,从而表现为切换失效。

排查与解决方向:

  1. 监听路由变更事件: 核心解决方案是确保UI状态与系统状态同步。您需要主动监听系统的音频设备路由变更事件,并据此更新AVCastPicker的显示状态。

    • 使用AudioRoutingManageron('audioDeviceChange')方法监听音频设备变更事件。
    • 在事件回调中,获取当前的实际音频输出设备列表,并更新到AVCastPickeravCastPickerValue中,强制其刷新显示。
  2. 检查生命周期与状态管理: 确保在页面或组件生命周期(如aboutToAppear)中正确注册监听,并在aboutToDisappear中注销监听,避免内存泄漏和事件冲突。

  3. 控制切换频率(可选): 在业务逻辑中,可以考虑对用户的切换操作增加适当的防抖或节流处理,避免在极短时间内触发多次系统路由请求,降低出现状态不一致的概率。

代码修改要点示例: 在您的Demo中,主要需在Index.ets中增加监听逻辑:

import { AudioRoutingManager, audio } from '@kit.AudioKit';
import { BusinessError } from '@kit.BasicServicesKit';

// 在组件内定义变量
private audioRoutingManager: AudioRoutingManager = audio.getAudioRoutingManager();
private audioDeviceChangeId: number = -1; // 用于保存监听ID

aboutToAppear(): void {
  // 注册音频设备变更监听
  this.audioDeviceChangeId = this.audioRoutingManager.on('audioDeviceChange', (deviceChanged: audio.DeviceChangeAction) => {
    console.info(`Audio device changed, device type: ${deviceChanged.deviceType}, device action: ${deviceChanged.action}`);
    // 当设备变更时,重新获取并设置当前设备列表
    this.updateCurrentAvCastPickerValue();
  });
}

aboutToDisappear(): void {
  // 组件消失时注销监听
  if (this.audioDeviceChangeId !== -1) {
    this.audioRoutingManager.off(this.audioDeviceChangeId);
    this.audioDeviceChangeId = -1;
  }
}

// 一个更新avCastPickerValue的方法示例
private async updateCurrentAvCastPickerValue(): Promise<void> {
  try {
    // 1. 获取当前音频输出设备列表
    const devices: audio.AudioDeviceDescriptors = await this.audioRoutingManager.getDevices(audio.DeviceFlag.OUTPUT_DEVICES_FLAG);
    // 2. 根据您的业务逻辑,从devices中筛选、映射出当前应显示的设备信息
    // 3. 将最终得到的设备列表赋值给 @State avCastPickerValue,触发UI更新
    // this.avCastPickerValue = ... (映射后的设备列表)
  } catch (error) {
    const err: BusinessError = error as BusinessError;
    console.error(`Failed to get devices, error code: ${err.code}, message: ${err.message}`);
  }
}

// 在您的AVCastPicker的onChange事件中,可能也需要调用此更新方法以确保状态同步

通过以上方式,可以让AVCastPicker的显示始终跟随系统实际的音频路由状态,从而解决多次切换后UI无响应的问题。请根据您的具体业务逻辑调整设备列表的映射与更新策略。

回到顶部