HarmonyOS 鸿蒙Next中WebSocket连接在应用进入后台后会被系统杀死吗?

HarmonyOS 鸿蒙Next中WebSocket连接在应用进入后台后会被系统杀死吗? 我们的 IM 应用在锁屏 2 分钟后收不到消息。除了申请 continuousTask,还有别的办法吗?

4 回复

申请长时任务:

应用退至后台后,在后台需要长时间运行用户可感知的任务,如播放音乐、导航等。为防止应用进程被挂起,导致对应功能异常,可以申请长时任务,使应用在后台长时间运行。在长时任务中,支持同时申请多种类型的任务,也可以对任务类型进行更新。应用退至后台执行业务时,系统会做一致性校验,确保应用在执行相应的长时任务。应用在申请长时任务成功后,通知栏会显示与长时任务相关联的消息,用户删除通知栏消息时,系统会自动停止长时任务。

使用场景:

下表给出了当前长时任务支持的类型,包含数据传输、音视频播放、录制、定位导航、蓝牙相关业务、多设备互联、音视频通话和计算任务。可以参考下表中的场景举例,选择合适的长时任务类型。

表1 长时任务类型

参数名 描述 配置项 场景举例
DATA_TRANSFER 数据传输。 dataTransfer 非托管形式的上传、下载,如在浏览器后台上传或下载数据。
AUDIO_PLAYBACK 音视频播放。 audioPlayback 音频、视频在后台播放,音视频投播。
说明: 支持在元服务中使用。
AUDIO_RECORDING 录制。 audioRecording 录音、录屏退后台。
LOCATION 定位导航。 location 定位、导航。
BLUETOOTH_INTERACTION 蓝牙相关业务。 bluetoothInteraction 通过蓝牙传输文件时退后台。
MULTI_DEVICE_CONNECTION 多设备互联。 multiDeviceConnection 分布式业务连接、投播。
说明: 支持在元服务中使用。
VOIP 音视频通话。 voip 某些聊天类应用(具有音视频业务)音频、视频通话时退后台。
TASK_KEEPING 计算任务。
说明: 从API version 21开始,对PC/2in1设备、非PC/2in1设备但申请了ACL权限为ohos.permission.KEEP_BACKGROUND_RUNNING_SYSTEM的应用开放。 API version 20及之前版本,仅对PC/2in1设备开放。
taskKeeping 如杀毒软件。

详细开发文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/continuous-task

更多关于HarmonyOS 鸿蒙Next中WebSocket连接在应用进入后台后会被系统杀死吗?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


涉及到app保活问题,如果满足条件就申请长时任务。

不然,可以申请短时任务,在短时任务结束后,主动断开WebSocket连接。IM消息走push远程推送。

以下参考:

【背景知识】

  • 应用进入后台会触发系统后台功耗管控策略,创建的所有网络连接在较短时间内都会被杀死。
  • 网络资源合理使用:无长时任务的应用退到后台主动断开socket连接,包含TCP和UDP连接。
  • 应用退至后台后,在后台需要长时间运行用户可感知的任务,如播放音乐、导航等。为防止应用进程被挂起,导致对应功能异常,可以申请长时任务,让应用在后台长时间运行。当前长时任务支持的类型,包含数据传输、音视频播放、录制、定位导航、蓝牙相关业务、多设备互联、WLAN相关业务和计算任务。

【解决方案】

websocket保活,可以使用长时任务保活websocket,应用退到后台会被杀掉进程,长时任务可以防止后台挂起的程序被杀掉。

websocket长连接对应的长时任务类型可以选择voip类型,参考示例如下:

import { webSocket } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { backgroundTaskManager } from '@kit.BackgroundTasksKit';
import { wantAgent, WantAgent } from '@kit.AbilityKit';

let defaultIpAddress = "ws://xxxxxx:xxxx";
let ws = webSocket.createWebSocket();

@Component
export struct Socket {
  @State message: string = 'ContinuousTask';
  // 通过getContext方法,来获取page所在的UIAbility上下文。
  private context: Context = getContext(this);

  aboutToAppear() {
    let wantAgentInfo: wantAgent.WantAgentInfo = {
      // 点击通知后,将要执行的动作列表
      // 添加需要被拉起应用的bundleName和abilityName
      wants: [
        {
          bundleName: "com.example.myapp",
          abilityName: "EntryAbility"
        }
      ],
      // 指定点击通知栏消息后的动作是拉起ability
      actionType: wantAgent.OperationType.START_ABILITY,
      // 使用者自定义的一个私有值
      requestCode: 0,
      // 点击通知后,动作执行属性
      actionFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
    };

    try {
      // 通过wantAgent模块下getWantAgent方法获取WantAgent对象
      wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => {
        try {
          let list: Array<string> = ["voip"];
          backgroundTaskManager.startBackgroundRunning(this.context, list, wantAgentObj)
            .then((res: backgroundTaskManager.ContinuousTaskNotification) => {
              console.info("Operation startBackgroundRunning succeeded");
              // 此处执行具体的长时任务逻辑,如录音,录制等。
              ws.on('open', (err: BusinessError, value: Object) => {
                console.log("on open, status:" + value);
                // 当收到on('open')事件时,可以通过send()方法与服务器进行通信
                ws.send("Hello, server!", (err: BusinessError, value: boolean) => {
                  if (!err) {
                    console.log("Message send successfully");
                  } else {
                    console.log("Failed to send the message. Err:" + err);
                  }
                });
              });
              ws.on('message', (err: BusinessError, value: string | ArrayBuffer) => {
                console.log("on message, message:" + value);
                // 当收到服务器的`bye`消息时(此消息字段仅为示意,具体字段需要与服务器协商),主动断开连接
                if (value === 'bye') {
                  ws.close((err: BusinessError, value: boolean) => {
                    if (!err) {
                      console.log("Connection closed successfully");
                    } else {
                      console.log("Failed to close the connection. Err:" + err);
                    }
                  });
                }
              });
              ws.on('close', (err: BusinessError, value: webSocket.CloseResult) => {
                console.log("on close, code is " + value.code + ", reason is " + value.reason);
              });
              ws.on('error', (err: BusinessError) => {
                console.log("on error, error:" + err);
              });
              ws.connect(defaultIpAddress, (err: BusinessError, value: boolean) => {
                if (!err) {
                  console.log("Connected successfully");
                } else {
                  console.log("Connection failed. Err:" + err);
                }
              });
            })
            .catch((error: BusinessError) => {
              console.error(`Failed to Operation startBackgroundRunning. code is ${error.code} message is ${error.message}`);
            });
        } catch (error) {
          console.error(`Failed to Operation startBackgroundRunning. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
        }
      });
    } catch (error) {
      console.error(`Failed to Operation getWantAgent. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}`);
    }
  }

  build() {
    Button("发送消息").onClick((event: ClickEvent) => {
      ws.send("我发消息了,我是xx")
    })
  }
}

【总结】 应用切换到后台场景websocket可以申请长时任务来进行保活,申请时应当注意以下几点: 1.应用按需求申请长时任务,当应用无需在后台运行(任务结束)时,要及时主动取消长时任务,否则系统会强行取消。 2.如果进程标记了长时任务,系统会检测标记的任务和实际执行是否符合,不符合也会被杀死。 3.使用数据传输长时任务时,如果进度超过10分钟不更新,任务也会被取消,建议增加更新进度的逻辑,避免未下载完成被系统挂起。

4.建议使用Push Kit的方式去实现,服务器可以定时向客户端发送心跳消息,客户端接收到心跳消息后,可以向服务器发送响应消息,以表明自己仍然处于连接状态。这样可以避免websocket连接因为长时间没有数据传输而被关闭。

在HarmonyOS Next中,WebSocket连接在应用进入后台后可能会被系统挂起或终止,具体取决于系统资源管理策略。系统为优化资源,可能中断后台应用的网络连接。若需维持连接,可申请后台持续任务权限,但需符合系统规范。

在HarmonyOS Next中,应用进入后台(包括锁屏)后,系统为优化资源与功耗,会限制其网络活动,WebSocket连接确实可能被挂起或中断,导致无法实时接收消息。

除了申请continuousTask(持续任务)来保持后台网络连接,你还可以考虑以下技术方案:

  1. 使用系统推送服务:这是首推的替代方案。HarmonyOS提供了Push Kit。你的服务端将消息发送给华为推送服务器,由系统级服务负责唤醒或通知你的应用。这比维持一个常驻的后台连接更省电、更可靠,是IM类应用的推荐架构。

  2. 合理使用短时任务:对于需要在后台执行短暂网络同步的任务,可以使用transientTask。它允许应用在后台获得短时间(约3分钟)的资源访问权限,适合进行数据拉取或连接保活,但无法解决长期实时监听的需求。

  3. 优化连接与重连策略

    • 在应用从前台切到后台时,主动将WebSocket状态通知服务端,并尝试进入低功耗模式。
    • 实现健壮的重连机制。当应用从后台返回前台时,立即检查WebSocket连接状态并进行重建。
    • 可以利用后台代理能力,在特定时间间隔进行轻量级的心跳或拉取,但这需要系统调度配合,实时性无法保证。

核心建议:对于用户感知强的即时消息,应优先采用 “系统推送(Push Kit) + 前台WebSocket连接” 的混合模式。应用在前台时使用WebSocket保证实时性和低延迟;应用在后台时,依赖Push Kit送达通知,用户点击通知或打开应用后再通过WebSocket获取完整数据和状态同步。这符合HarmonyOS Next的后台管理设计哲学,能在体验与功耗间取得最佳平衡。

回到顶部