HarmonyOS APP长时任务:让应用在后台持续运行的正确姿势

举报
Jack20 发表于 2026/06/20 15:07:15 2026/06/20
【摘要】 HarmonyOS APP长时任务:让应用在后台持续运行的正确姿势📌 核心要点:长时任务通过 backgroundTaskManager.startBackgroundRunning() 申请,必须在通知栏显示持续通知,适用于音频播放、持续定位、蓝牙连接等用户明确感知的场景。 一、背景与动机你有没有这样的经历——用网易云音乐听歌,切到微信聊天,音乐还在播放,通知栏还显示着一个"正在播放"...

HarmonyOS APP长时任务:让应用在后台持续运行的正确姿势

📌 核心要点:长时任务通过 backgroundTaskManager.startBackgroundRunning() 申请,必须在通知栏显示持续通知,适用于音频播放、持续定位、蓝牙连接等用户明确感知的场景。


一、背景与动机

你有没有这样的经历——用网易云音乐听歌,切到微信聊天,音乐还在播放,通知栏还显示着一个"正在播放"的小通知条?这就是长时任务在发挥作用。

再比如高德地图导航,你切到别的 App 看消息,导航语音还在继续播报,GPS 还在持续追踪你的位置。如果切后台就停止导航,那导航还有什么意义?

这些场景有一个共同特点:用户明确知道应用在后台干活,而且期望它一直干下去。HarmonyOS 把这类需求定义为"长时任务"(Continuous Task),它允许应用在退到后台后继续运行,但有一个硬性要求——必须在通知栏告诉用户"我还在后台运行"。

为什么必须显示通知?因为长时任务会持续占用 CPU、网络、GPS 等系统资源,如果偷偷在后台跑,用户完全不知情,手机发烫耗电却找不到元凶。通知栏显示就是给用户一个"知情权"——你可以随时知道谁在后台跑,不想让它跑就一键关掉。

这就是长时任务的设计哲学:给你后台运行的能力,但必须对用户透明


二、核心原理

2.1 长时任务生命周期

长时任务从申请到释放,有一个完整的生命周期:

flowchart TD
    A([应用前台运行]) --> B{需要后台持续运行?}
    B -->|| C[申请长时任务]
    B -->|| A

    C --> D[系统校验权限]
    D -->|权限通过| E[显示通知栏]
    D -->|权限不足| F[申请失败,抛出异常]

    E --> G[应用退到后台]
    G --> H[长时任务保活运行]
    H --> I{任务是否完成?}
    I -->|| H
    I -->|| J[取消长时任务]
    J --> K[通知栏消失]
    K --> A

    H --> L{用户从通知栏关闭?}
    L -->|| M[系统强制停止任务]
    M --> N[应用收到回调]
    N --> A

    classDef primary fill:#4CAF50,stroke:#388E3C,color:#fff
    classDef warning fill:#FF9800,stroke:#F57C00,color:#fff
    classDef error fill:#F44336,stroke:#D32F2F,color:#fff
    classDef info fill:#2196F3,stroke:#1976D2,color:#fff
    classDef purple fill:#9C27B0,stroke:#7B1FA2,color:#fff

    class A,B,G,H primary
    class C,E,J,K info
    class F,M,N error
    class D,L warning
    class I purple

2.2 长时任务类型

HarmonyOS 定义了多种长时任务类型,每种类型对应不同的后台行为和资源需求:

类型 枚举值 说明 典型场景
数据传输 DATA_TRANSFER 网络数据持续传输 文件上传/下载
音频播放 AUDIO_PLAYBACK 后台音频播放 音乐播放、有声书
音频录制 AUDIO_RECORDING 后台录音 录音笔、语音备忘录
定位导航 LOCATION 持续获取位置信息 导航、运动追踪
蓝牙交互 BLUETOOTH_INTERACTION 蓝牙持续连接 智能手环、蓝牙耳机
多设备互联 MULTI_DEVICE_CONNECTION 多设备协同 投屏、文件互传
任务切换 TASK_KEEPING 计算类任务 后台编译、数据处理
实时通话 VOIP 网络语音通话 视频会议、语音通话

2.3 长时任务与通知栏的绑定机制

长时任务和通知栏是强绑定的关系——没有通知栏,就没有长时任务

graph TB
    subgraph 应用进程
        A[startBackgroundRunning] --> B[申请长时任务]
        B --> C[绑定 NotificationRequest]
    end

    subgraph 系统服务
        D[后台任务管理服务] --> E[校验权限]
        E --> F[注册长时任务]
        F --> G[通知管理服务]
        G --> H[显示持续通知]
    end

    subgraph 用户交互
        H --> I[通知栏显示运行状态]
        I --> J[用户点击通知 → 打开应用]
        I --> K[用户划掉通知 → 停止任务]
    end

    C --> D

    classDef primary fill:#4CAF50,stroke:#388E3C,color:#fff
    classDef warning fill:#FF9800,stroke:#F57C00,color:#fff
    classDef error fill:#F44336,stroke:#D32F2F,color:#fff
    classDef info fill:#2196F3,stroke:#1976D2,color:#fff
    classDef purple fill:#9C27B0,stroke:#7B1FA2,color:#fff

    class A,B,C primary
    class D,E,F,G info
    class H,I,J,K warning

三、代码实战

3.1 音乐播放器长时任务

这是最经典的长时任务场景——音乐后台播放。我们实现一个完整的音乐播放器后台保活方案:

import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
import notificationManager from '@ohos.notificationManager';
import { BusinessError } from '@ohos.base';
import wantAgent from '@ohos.app.ability.wantAgent';

/**
 * 音乐播放器后台任务管理器
 * 封装长时任务的申请、通知栏显示、取消等完整流程
 */
export class MusicBackgroundTaskManager {
  /** 长时任务是否正在运行 */
  private isRunning: boolean = false;
  /** 通知ID,用于更新和取消通知 */
  private readonly NOTIFICATION_ID: number = 1001;
  /** 长时任务类型:音频播放 */
  private readonly BG_MODE = backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK;

  /**
   * 启动音乐播放长时任务
   * @param context UIAbilityContext
   * @param songName 当前播放歌曲名
   */
  async startMusicTask(context: Context, songName: string): Promise<void> {
    if (this.isRunning) {
      console.info('[音乐后台] 长时任务已在运行,无需重复申请');
      return;
    }

    try {
      // 第一步:创建 WantAgent,点击通知时打开应用
      const wantAgentInfo: wantAgent.WantAgentInfo = {
        wants: [
          {
            bundleName: context.abilityInfo.bundleName,
            abilityName: context.abilityInfo.name,
          }
        ],
        requestCode: 0,
        operationType: wantAgent.OperationType.START_ABILITY,
        wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG],
      };
      const agent = await wantAgent.getWantAgent(wantAgentInfo);

      // 第二步:构建通知请求
      const notificationRequest: notificationManager.NotificationRequest = {
        id: this.NOTIFICATION_ID,
        content: {
          notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
          normal: {
            title: '正在播放',
            text: songName,
          }
        },
        wantAgent: agent,
        // 设置为持续通知,用户无法划掉
        isOngoing: true,
        // 设置通知不可清除
        isUnremovable: false,
      };

      // 第三步:发布通知
      notificationManager.publish(notificationRequest);
      console.info('[音乐后台] 通知发布成功');

      // 第四步:申请长时任务
      backgroundTaskManager.startBackgroundRunning(
        context,
        this.BG_MODE,
        notificationRequest
      );

      this.isRunning = true;
      console.info('[音乐后台] 长时任务申请成功,音乐可在后台继续播放');

    } catch (error) {
      const err = error as BusinessError;
      console.error(`[音乐后台] 启动失败,错误码: ${err.code},错误信息: ${err.message}`);
    }
  }

  /**
   * 停止音乐播放长时任务
   * @param context UIAbilityContext
   */
  async stopMusicTask(context: Context): Promise<void> {
    if (!this.isRunning) {
      console.info('[音乐后台] 长时任务未在运行');
      return;
    }

    try {
      // 第一步:取消长时任务
      backgroundTaskManager.stopBackgroundRunning(context);
      console.info('[音乐后台] 长时任务已取消');

      // 第二步:移除通知
      notificationManager.cancel(this.NOTIFICATION_ID);
      console.info('[音乐后台] 通知已移除');

      this.isRunning = false;

    } catch (error) {
      const err = error as BusinessError;
      console.error(`[音乐后台] 停止失败,错误码: ${err.code},错误信息: ${err.message}`);
    }
  }

  /**
   * 更新通知栏内容(切歌时使用)
   * @param songName 新歌曲名
   */
  async updateNotification(songName: string): Promise<void> {
    if (!this.isRunning) {
      console.warn('[音乐后台] 长时任务未运行,无法更新通知');
      return;
    }

    try {
      const notificationRequest: notificationManager.NotificationRequest = {
        id: this.NOTIFICATION_ID,
        content: {
          notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
          normal: {
            title: '正在播放',
            text: songName,
          }
        },
        isOngoing: true,
      };

      notificationManager.publish(notificationRequest);
      console.info(`[音乐后台] 通知已更新: ${songName}`);

    } catch (error) {
      const err = error as BusinessError;
      console.error(`[音乐后台] 更新通知失败,错误码: ${err.code}`);
    }
  }

  /**
   * 获取长时任务运行状态
   */
  getTaskStatus(): boolean {
    return this.isRunning;
  }
}

3.2 运动定位长时任务

运动类 App 需要持续追踪 GPS 位置,即使用户锁屏或切到其他应用也不能中断:

import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
import notificationManager from '@ohos.notificationManager';
import geoLocationManager from '@ohos.geoLocationManager';
import { BusinessError } from '@ohos.base';

/**
 * 运动定位后台任务管理器
 * 支持跑步、骑行等运动场景的持续定位追踪
 */
export class SportLocationTaskManager {
  private isTracking: boolean = false;
  private locationChangeCallback: ((location: geoLocationManager.Location) => void) | null = null;
  private readonly NOTIFICATION_ID: number = 2001;
  private totalDistance: number = 0; // 总距离(米)
  private lastLocation: geoLocationManager.Location | null = null;

  /**
   * 启动运动定位长时任务
   * @param context UIAbilityContext
   * @param sportType 运动类型名称
   */
  async startSportTracking(context: Context, sportType: string): Promise<void> {
    if (this.isTracking) {
      console.info('[运动定位] 已在追踪中');
      return;
    }

    try {
      // 1. 构建通知
      const notificationRequest: notificationManager.NotificationRequest = {
        id: this.NOTIFICATION_ID,
        content: {
          notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
          normal: {
            title: `${sportType}进行中`,
            text: '正在记录您的运动轨迹...',
          }
        },
        isOngoing: true,
      };

      // 2. 发布通知
      notificationManager.publish(notificationRequest);

      // 3. 申请长时任务(定位类型)
      backgroundTaskManager.startBackgroundRunning(
        context,
        backgroundTaskManager.BackgroundMode.LOCATION,
        notificationRequest
      );

      // 4. 开启持续定位
      const locationRequest: geoLocationManager.ContinuousLocationRequest = {
        interval: 1, // 每秒更新一次位置
        locationScenario: geoLocationManager.UserActivityScenario.NAVIGATION,
      };

      this.locationChangeCallback = (location: geoLocationManager.Location): void => {
        this.onLocationReceived(location);
      };

      geoLocationManager.on('locationChange', locationRequest, this.locationChangeCallback);

      this.isTracking = true;
      this.totalDistance = 0;
      this.lastLocation = null;
      console.info('[运动定位] 运动追踪已启动');

    } catch (error) {
      const err = error as BusinessError;
      console.error(`[运动定位] 启动失败,错误码: ${err.code},错误信息: ${err.message}`);
    }
  }

  /**
   * 位置变化回调
   * 计算累计距离并更新通知
   */
  private onLocationReceived(location: geoLocationManager.Location): void {
    if (this.lastLocation) {
      // 计算两点间距离(简化版,使用直线距离)
      const distance = this.calculateDistance(
        this.lastLocation.latitude, this.lastLocation.longitude,
        location.latitude, location.longitude
      );
      this.totalDistance += distance;
    }
    this.lastLocation = location;

    // 每累计100米更新一次通知
    if (Math.floor(this.totalDistance / 100) !== Math.floor((this.totalDistance - 1) / 100)) {
      this.updateDistanceNotification();
    }
  }

  /**
   * 计算两点间距离(Haversine公式简化版)
   */
  private calculateDistance(
    lat1: number, lon1: number,
    lat2: number, lon2: number
  ): number {
    const R = 6371000; // 地球半径(米)
    const dLat = (lat2 - lat1) * Math.PI / 180;
    const dLon = (lon2 - lon1) * Math.PI / 180;
    const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
              Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
              Math.sin(dLon / 2) * Math.sin(dLon / 2);
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    return R * c;
  }

  /**
   * 更新距离通知
   */
  private updateDistanceNotification(): void {
    try {
      const km = (this.totalDistance / 1000).toFixed(2);
      const notificationRequest: notificationManager.NotificationRequest = {
        id: this.NOTIFICATION_ID,
        content: {
          notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
          normal: {
            title: '运动进行中',
            text: `已运动 ${km} 公里`,
          }
        },
        isOngoing: true,
      };

      notificationManager.publish(notificationRequest);
    } catch (error) {
      console.error('[运动定位] 更新通知失败');
    }
  }

  /**
   * 停止运动追踪
   */
  async stopSportTracking(context: Context): Promise<number> {
    if (!this.isTracking) {
      return 0;
    }

    try {
      // 1. 停止定位
      if (this.locationChangeCallback) {
        geoLocationManager.off('locationChange', this.locationChangeCallback);
      }

      // 2. 取消长时任务
      backgroundTaskManager.stopBackgroundRunning(context);

      // 3. 移除通知
      notificationManager.cancel(this.NOTIFICATION_ID);

      this.isTracking = false;
      console.info(`[运动定位] 运动追踪已停止,总距离: ${(this.totalDistance / 1000).toFixed(2)} 公里`);

      return this.totalDistance;

    } catch (error) {
      const err = error as BusinessError;
      console.error(`[运动定位] 停止失败,错误码: ${err.code}`);
      return this.totalDistance;
    }
  }
}

3.3 长时任务保活与异常恢复

在实际生产环境中,长时任务可能因为系统资源回收、用户手动关闭等原因被中断。我们需要一套保活和恢复机制:

import backgroundTaskManager from '@ohos.resourceschedule.backgroundTaskManager';
import notificationManager from '@ohos.notificationManager';
import { BusinessError } from '@ohos.base';
import { AbilityConstant } from '@ohos.app.ability.AbilityConstant';

/**
 * 长时任务保活管理器
 * 处理长时任务被系统回收后的自动恢复
 */
export class ContinuousTaskKeepAliveManager {
  private static instance: ContinuousTaskKeepAliveManager;
  private currentTaskType: backgroundTaskManager.BackgroundMode | null = null;
  private currentNotificationId: number = 3001;
  private taskContext: Context | null = null;
  private taskDescription: string = '';
  private retryCount: number = 0;
  private readonly MAX_RETRY: number = 3;

  static getInstance(): ContinuousTaskKeepAliveManager {
    if (!ContinuousTaskKeepAliveManager.instance) {
      ContinuousTaskKeepAliveManager.instance = new ContinuousTaskKeepAliveManager();
    }
    return ContinuousTaskKeepAliveManager.instance;
  }

  /**
   * 注册长时任务保活
   * 在 Ability 的 onCreate 中调用
   */
  registerKeepAlive(
    context: Context,
    taskType: backgroundTaskManager.BackgroundMode,
    description: string
  ): void {
    this.taskContext = context;
    this.currentTaskType = taskType;
    this.taskDescription = description;
    this.retryCount = 0;

    console.info('[保活管理] 已注册长时任务保活');
  }

  /**
   * 处理 Ability 生命周期回调
   * 在 onForeground 中尝试恢复长时任务
   */
  handleAbilityForeground(): void {
    if (!this.taskContext || !this.currentTaskType) {
      return;
    }

    // 检查长时任务是否还在运行
    try {
      const status = backgroundTaskManager.getBackgroundRunningStatusSync();
      if (status > 0) {
        console.info('[保活管理] 长时任务仍在运行,无需恢复');
        return;
      }
    } catch (error) {
      // 查询失败,尝试恢复
    }

    // 长时任务已丢失,尝试恢复
    console.info('[保活管理] 检测到长时任务丢失,尝试恢复...');
    this.tryRestoreTask();
  }

  /**
   * 尝试恢复长时任务
   */
  private async tryRestoreTask(): Promise<void> {
    if (this.retryCount >= this.MAX_RETRY) {
      console.error('[保活管理] 已达到最大重试次数,放弃恢复');
      return;
    }

    this.retryCount++;

    try {
      // 重新构建通知
      const notificationRequest: notificationManager.NotificationRequest = {
        id: this.currentNotificationId,
        content: {
          notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
          normal: {
            title: '后台任务恢复中',
            text: this.taskDescription,
          }
        },
        isOngoing: true,
      };

      notificationManager.publish(notificationRequest);

      // 重新申请长时任务
      backgroundTaskManager.startBackgroundRunning(
        this.taskContext!,
        this.currentTaskType!,
        notificationRequest
      );

      this.retryCount = 0; // 恢复成功,重置重试计数
      console.info('[保活管理] 长时任务恢复成功');

    } catch (error) {
      const err = error as BusinessError;
      console.error(`[保活管理] 第${this.retryCount}次恢复失败,错误码: ${err.code}`);

      // 延迟后重试
      setTimeout(() => {
        this.tryRestoreTask();
      }, 2000 * this.retryCount); // 指数退避
    }
  }

  /**
   * 处理 Ability 回调状态变化
   * 当系统因资源回收回调应用时,尝试保活
   */
  handleOnCallback(state: AbilityConstant.OnCallbackState): void {
    switch (state) {
      case AbilityConstant.OnCallbackState.CONTINUOUS_TASK_BEGIN:
        console.info('[保活管理] 系统通知:长时任务已开始');
        break;
      case AbilityConstant.OnCallbackState.CONTINUOUS_TASK_END:
        console.warn('[保活管理] 系统通知:长时任务已结束,尝试恢复');
        this.tryRestoreTask();
        break;
      default:
        break;
    }
  }

  /**
   * 注销保活
   * 在 Ability 的 onDestroy 中调用
   */
  unregisterKeepAlive(): void {
    this.taskContext = null;
    this.currentTaskType = null;
    this.taskDescription = '';
    this.retryCount = 0;
    console.info('[保活管理] 已注销长时任务保活');
  }
}

/**
 * 在 UIAbility 中集成保活机制的示例
 */
export class MyAbility {
  private keepAliveManager: ContinuousTaskKeepAliveManager =
    ContinuousTaskKeepAliveManager.getInstance();

  onCreate(): void {
    // 注册保活
    this.keepAliveManager.registerKeepAlive(
      this as unknown as Context,
      backgroundTaskManager.BackgroundMode.AUDIO_PLAYBACK,
      '音乐播放中'
    );
  }

  onForeground(): void {
    // 前台时检查并恢复长时任务
    this.keepAliveManager.handleAbilityForeground();
  }

  onDestroy(): void {
    // 注销保活
    this.keepAliveManager.unregisterKeepAlive();
  }
}

四、踩坑与注意事项

4.1 通知ID冲突

踩坑:多个长时任务使用同一个通知ID,导致通知互相覆盖,系统无法正确关联长时任务和通知。

解决方案:每个长时任务使用不同的通知ID,且保证全局唯一。

// ❌ 错误:多个任务共用通知ID
const NOTIFICATION_ID = 1000; // 所有任务都用1000

// ✅ 正确:不同任务使用不同ID
const MUSIC_NOTIFICATION_ID = 1001;
const LOCATION_NOTIFICATION_ID = 2001;
const BLUETOOTH_NOTIFICATION_ID = 3001;

4.2 忘记取消长时任务

踩坑:应用退出时忘记调用 stopBackgroundRunning(),导致通知栏一直显示,长时任务一直占用资源。

解决方案:在 Ability 的 onDestroy 中确保取消长时任务。

// 在 UIAbility 的生命周期中管理长时任务
onDestroy(): void {
  // 确保取消长时任务
  try {
    backgroundTaskManager.stopBackgroundRunning(this.context);
    notificationManager.cancel(NOTIFICATION_ID);
  } catch (error) {
    console.error('取消长时任务失败');
  }
}

4.3 长时任务类型不匹配

踩坑:申请了 AUDIO_PLAYBACK 类型的长时任务,但实际在后台做的是数据计算。系统在审核时可能会判定为"类型不匹配",拒绝上架。

解决方案:长时任务类型必须与实际后台行为一致。音频播放就用 AUDIO_PLAYBACK,定位就用 LOCATION,不要张冠李戴。

4.4 通知内容不规范

踩坑:通知内容写得太模糊,比如只写"正在运行",用户不知道应用在后台干什么。

解决方案:通知内容应该清晰描述后台任务的具体行为。

// ❌ 通知内容模糊
normal: { title: '正在运行', text: '请勿关闭' }

// ✅ 通知内容清晰
normal: { title: '正在播放音乐', text: '周杰伦 - 晴天' }

4.5 在后台申请长时任务

踩坑:应用已经在后台了,才调用 startBackgroundRunning(),系统会拒绝。

解决方案:长时任务必须在前台申请,然后再退到后台。如果应用已经在后台,需要先通过通知或桌面图标把应用拉到前台,再申请。


五、HarmonyOS 6 适配

5.1 API 变更

变更项 HarmonyOS 5.0 HarmonyOS 6
长时任务申请 startBackgroundRunning() 新增重载方法,支持更多配置参数
通知绑定 必须手动构建 NotificationRequest 新增简化接口,自动生成默认通知
任务回调 无系统级回调 新增on('continuousTaskStateChange') 回调
多任务支持 同一应用只能有一个长时任务 支持同一应用同时运行多个不同类型长时任务

5.2 迁移指南

  1. 回调监听:6.0 新增了长时任务状态变化回调,可以替代手动查询:
// HarmonyOS 6 新增的回调监听
backgroundTaskManager.on('continuousTaskStateChange', (info) => {
  console.info(`[长时任务] 状态变化: ${JSON.stringify(info)}`);
  if (info.state === 'end') {
    // 长时任务被系统终止,执行恢复逻辑
  }
});
  1. 多任务支持:6.0 允许同一应用同时运行多个长时任务,但每个任务类型只能有一个实例。
  2. 通知简化:6.0 提供了默认通知模板,可以不手动构建 NotificationRequest:
// HarmonyOS 6 简化接口(示意)
backgroundTaskManager.startBackgroundRunning(context, bgMode, {
  title: '正在播放音乐',
  text: '周杰伦 - 晴天',
});

六、总结

核心知识点回顾

长时任务(Continuous Task)
├── 核心API
│   ├── startBackgroundRunning() → 申请长时任务
│   ├── stopBackgroundRunning() → 取消长时任务
│   └── getBackgroundRunningStatusSync() → 查询运行状态
│
├── 任务类型(8种)
│   ├── AUDIO_PLAYBACK → 音频播放
│   ├── AUDIO_RECORDING → 音频录制
│   ├── LOCATION → 定位导航
│   ├── BLUETOOTH_INTERACTION → 蓝牙交互
│   ├── MULTI_DEVICE_CONNECTION → 多设备互联
│   ├── TASK_KEEPING → 计算任务
│   ├── DATA_TRANSFER → 数据传输
│   └── VOIP → 实时通话
│
├── 通知栏绑定
│   ├── 必须显示持续通知(isOngoing: true)
│   ├── 通知内容需清晰描述后台行为
│   └── 用户可通过通知栏终止任务
│
├── 保活机制
│   ├── onForeground 时检查任务状态
│   ├── 任务丢失时自动恢复
│   └── 指数退避重试策略
│
└── 开发准则
    ├── 前台申请,后台运行
    ├── 任务类型与行为一致
    ├── 用完即释放
    └── 通知内容清晰规范

一句话总结:长时任务是把双刃剑——用好了让应用在后台如鱼得水,用滥了让用户电量如流水。记住"前台申请、通知绑定、类型匹配、用完释放"这十六个字,就能用好长时任务。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。