HarmonyOS鸿蒙Next中voipCallUiEvent无法收到点击接听回调

HarmonyOS鸿蒙Next中voipCallUiEvent无法收到点击接听回调 应用创建呼叫横幅,点击接听按钮会直接拉起Ability,没有回调,但点击拒绝是有回调。只有当应用内上报过一次VOIP_CALL_STATE_ACTIVE,后续创建横幅点击接听才有回调,相关代码如下:

voipCall.on("voipCallUiEvent", async (data: voipCall.VoipCallUiEventInfo) => {
  Logger.info(this.TAG, "voipCallUiEvent: " + JSON.stringify(data), false);
  // 忽略应用内逻辑
});

// 构建通话详细信息的对象
let callInfo: voipCall.VoipCallAttribute = {
  callId: this.params.callId,
  userName: this.params.callName,
  userProfile: image.createPixelMapSync(new ArrayBuffer(100), { size: { width: 90, height: 90 } }),
  abilityName: 'VoipAbility',
  isVoiceAnswerSupported: false,
  voipCallType: voipCall.VoipCallType.VOIP_CALL_VIDEO,
  voipCallState: voipCall.VoipCallState.VOIP_CALL_STATE_RINGING,
};
// 通知来电消息
let error = await voipCall.reportIncomingCall(callInfo);
if (error != voipCall.ErrorReason.ERROR_NONE) {
  Logger.warn(this.TAG, `Failed to reportIncomingCall: ` + error);
  this.release();
  return Promise.reject();
}

更多关于HarmonyOS鸿蒙Next中voipCallUiEvent无法收到点击接听回调的实战教程也可以访问 https://www.itying.com/category-93-b0.html

5 回复

开发者您好,您可以参考下这个demo:示例代码,本地测试使用6.0.0.115(API21)的手机是可以收到回调的,开发者测试的demo的时候注意把项目api修改成api21测试一下,如果还是没有回调,请开发者提供一下版本信息(DevEco Studio的版本信息以及测试手机的版本信息)。

更多关于HarmonyOS鸿蒙Next中voipCallUiEvent无法收到点击接听回调的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


DevEco Studio:6.0.1.112 手机版本:6.0.0.120、5.1.0.150

根据你的描述和代码,voipCallUiEvent 监听器在首次接听时没有回调,很可能是因为你的应用在用户点击“接听”时,尚未向系统声明你拥有处理一个“活跃”(Active)通话的能力

鸿蒙的 Call Kit(通话服务)设计了一套严格的状态管理机制。点击“接听”按钮后,系统需要拉起一个能真正处理音视频通话的 Ability。为了确保拉起成功,系统会检查上报的通话状态。

下面的表格清晰地展示了问题所在的关键状态差异:简单来说,应用必须通过 reportCallStateChange 接口,将通话状态从 VOIP_CALL_STATE_RINGING 明确更新为 VOIP_CALL_STATE_ACTIVE,才能完成一次完整的“接听”逻辑闭环

import voipCall from '@ohos.telephony.voipCall';
// ... 其他导入

// 1. 在合适的位置(如Ability的onCreate或页面初始化时)订阅事件
voipCall.on("voipCallUiEvent", async (data: voipCall.VoipCallUiEventInfo) => {
  Logger.info(this.TAG, "voipCallUiEvent: " + JSON.stringify(data), false);
  
  switch(data.action) {
    case voipCall.Action.ACTION_ANSWER: // 处理接听动作
      Logger.info(this.TAG, "收到接听事件,准备拉起通话界面并更新状态");
      // 2. 接听时,先上报通话状态为“活跃”
      try {
        await voipCall.reportCallStateChange(this.params.callId, voipCall.VoipCallState.VOIP_CALL_STATE_ACTIVE);
        Logger.info(this.TAG, "上报通话状态为ACTIVE成功");
      } catch (err) {
        Logger.error(this.TAG, "上报ACTIVE状态失败: " + JSON.stringify(err));
        // 处理错误
        return;
      }
      // 3. 然后,再执行你的拉起通话界面的逻辑(例如跳转到通话UI页面)
      // 例如:this.context.startAbility(...)
      break;
    case voipCall.Action.ACTION_REJECT: // 处理拒绝动作
      Logger.info(this.TAG, "收到拒绝事件");
      // 拒绝时,上报状态为 IDLE 或直接结束
      await voipCall.reportCallStateChange(this.params.callId, voipCall.VoipCallState.VOIP_CALL_STATE_IDLE);
      // 执行你的清理逻辑
      break;
    default:
      break;
  }
});

// 4. 上报来电(初始状态为振铃)
let callInfo: voipCall.VoipCallAttribute = {
  callId: this.params.callId,
  userName: this.params.callName,
  // ... 其他属性
  voipCallState: voipCall.VoipCallState.VOIP_CALL_STATE_RINGING, // 初始状态
};
voipCall.reportIncomingCall(callInfo).then(() => {
  // 上报成功
}).catch((err) => {
  // 错误处理
});

如果按照上述步骤操作后问题仍然存在,请检查以下几点

  1. 权限与配置:确保应用在 module.json5 中正确声明了 ohos.permission.ANSWER_CALL 等必要的通话权限。

  2. Ability名称:检查 callInfo 中的 abilityName 是否与你想拉起的 Ability 的准确名称一致。

  3. 通知权限:在手机设置中,确认你的应用拥有显示“横幅通知”的权限。 如果以上步骤全部检查无误,但问题仍无法解决,建议通过华为开发者平台的在线提单渠道提交问题,将你的详细代码、日志和复现步骤提供给华为技术支持人员,以便进行更深入的排查

在HarmonyOS Next中,voipCallUiEvent未收到点击接听回调,可能涉及以下原因:

  1. 事件监听未正确注册或绑定。
  2. UI组件的事件处理逻辑存在缺陷。
  3. 系统权限或配置限制导致事件传递中断。
  4. SDK版本或API兼容性问题。

请检查事件注册代码、UI组件声明及系统配置。

根据你的描述,这是一个已知的HarmonyOS Next中voipCall模块的行为机制问题。

核心原因:系统设计上,首次创建通话横幅时,点击“接听”按钮的默认行为是直接启动你在VoipCallAttribute中指定的abilityName(即VoipAbility)。此时,系统认为这是一个全新的通话建立流程,因此不会触发voipCallUiEvent回调。

关键机制:当你的应用通过voipCall.reportCallState上报一次VOIP_CALL_STATE_ACTIVE状态后,系统会将此通话会话标记为“已由应用管理”。在此之后,如果通话状态流转(例如从ACTIVE回到RINGING)并再次创建横幅,用户点击“接听”将被视为对现有应用管理通话的一个UI操作,从而正确触发voipCallUiEvent回调。

当前解决方案

  1. 首次接听逻辑迁移:将首次点击接听后的处理逻辑,从依赖voipCallUiEvent回调,转移到VoipAbility的启动入口(例如onWindowStageCreate)中。在Ability启动后,立即上报VOIP_CALL_STATE_ACTIVE状态,并执行你的接听逻辑(如建立媒体连接)。
  2. 状态管理:确保应用内部维护清晰的通话状态机。在VoipAbility中启动并上报ACTIVE状态后,后续所有的用户界面操作(包括从横幅接听)就都能通过voipCallUiEvent回调进行响应和处理。

代码调整思路: 在你的VoipAbility启动后,尽早执行类似下面的代码:

// 在VoipAbility的onWindowStageCreate等生命周期回调中
let callId: string = ...; // 获取当前通话的callId
await voipCall.reportCallState(callId, voipCall.VoipCallState.VOIP_CALL_STATE_ACTIVE);
// 然后执行你的实际接听逻辑

这样,通话生命周期就与应用Ability绑定,后续的UI事件回调即可正常工作。

点击“拒绝”之所以始终有回调,是因为拒绝操作会直接结束通话会话,无需拉起Ability,因此系统总是通过回调通知应用进行状态清理。

回到顶部