目录

应用前后台切换后出现通信不可达、网络异常

问题现象

用户在应用内使用网络进行通信时(或者数据传输和文件上传下载),若将应用切换至后台(例如锁屏或进行其他任务),一段时间后切回前台,可能会遇到网络连接中断、无法发送消息或文件下载失败等问题。

另外,在使用SSH、Mosh或SFTP等终端工具执行远程服务器上的持续任务时,将应用退至后台后,系统会挂起应用进程并释放网络连接,导致会话意外中断,远端任务无法持续跟踪或状态丢失。

背景知识

补充说明,startBackgroundRunning的TASK_KEEPING类型需要系统级ACL特权,普通三方应用无法申请;DATA_TRANSFER类型在无实际大流量数据吞吐时,会被系统后台一致性校验判定违规并强杀。短时任务有严格的时间限制(最高3分钟)与每日总配额限制。

问题定位

  1. 以申请长时任务为例,查看module.json5配置文件中是否有ohos.permission.KEEP_BACKGROUND_RUNNING的权限声明,并搜索startBackgroundRunning和stopBackgroundRunning,检查申请和取消长时任务的逻辑是否完善。
  2. 监听on('error')事件,判断连接链路是否异常。在连接异常情况下,发送消息报错2301107 Socket not connected。
  3. 对于SSH、Mosh等终端工具类应用,检查是否尝试通过backgroundTaskManager申请长时任务保活。由于TASK_KEEPING需要系统级ACL特权,DATA_TRANSFER在低频心跳场景下会被一致性校验拦截,普通三方应用无法通过长时任务机制实现终端会话的长时间后台保活。

分析结论

由于应用在使用TCPSocket、UDPSocket等通信时(或者使用相应网络服务进行数据传输或文件上传下载),当应用切换退到后台后,未申请短时任务或长时任务会导致网络资源被冻结和释放。同时,将应用切后台和切回前台,未正确管理对应的通信状态,继续使用之前的TCPSocket、UDPSocket等连接对象和服务器通信,导致出现网络异常。

补充说明,对于SSH、Mosh等终端工具类应用,系统基于功耗与资源调度考量,判定纯粹的终端会话或闲置TCP不属于合法的高优先级后台服务,从而强制回收资源。backgroundTaskManager的长时/短时任务机制无法支撑普通三方应用的长时间网络空载或低频心跳保活需求。

修改建议

// 基于UIAbility生命周期的前台重连逻辑
import { UIAbility } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

export default class EntryAbility extends UIAbility {
  onForeground(): void {
    // 检查是否有由于切后台而中断的SSH会话
    if (SessionManager.hasDisconnectedSession()) {
      // 触发静默重连
      SessionManager.reconnectAllActiveSessions().then(() => {
        // 重连成功后,发送自动附着命令恢复现场
        SessionManager.executeCommand('tmux attach -t agent_session_1');
      }).catch((err: BusinessError) => {
        hilog.error(0x0000, 'EntryAbility', `Foreground reconnect failed: ${err.message}`);
        // 通过状态变量通知UI组件展示网络异常提示,引导用户手动重连或稍后重试
        AppStorage.setOrCreate('isNetworkError', true);
      });
    }
  }

  onBackground(): void {
    // 主动释放非必要资源,坦然接受即将到来的TCP冻结
  }
}

另外,还有以下备选方案:

常见FAQ

Q:UDPsocket在手机熄屏或应用切到后台后一段时间,重新切回前台时无法收到消息的原因分析?

A:应用退后台后UDPsocket被abort了,回到前台接收线程会退出并且触发error回调。因此需要监听事件管理,在监听到error事件后重新bind,避免无法收到消息。

Q:SSH、Mosh等终端工具类应用能否通过长时任务实现后台保活?

A:普通三方应用无法通过backgroundTaskManager的长时任务实现终端会话的长时间后台保活。TASK_KEEPING类型需要系统级ACL特权,DATA_TRANSFER类型在低频心跳场景下会被一致性校验拦截。建议采用服务端会话托管(如tmux)配合客户端前台重连的架构方案。

Q:应用使用第三方通信库在后台时收不到指令或消息,如何处理?

A:应用退至后台后,网络资源会被冻结和释放,导致基于网络的通信库无法正常收发消息。若应用在后台需要长时间运行用户可感知的通信任务,可以申请长时任务,使应用在后台长时间运行,确保网络资源不被冻结和释放。