蓝牙相关业务开发中长时任务的使用流程以及注意事项
========================

#### 问题现象

蓝牙相关业务开发中如何使用长时任务？有哪些注意事项？

#### 背景知识

*   [BLUETOOTH\_INTERACTION](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/continuous-task#使用场景)：应用退至后台后，在后台需要长时间运行用户可感知的任务，如录制。为防止应用进程被挂起，导致对应功能异常，可以申请长时任务，使应用在后台长时间运行。
*   [蓝牙低功耗连接和传输数据](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/gatt-development-guide)：基于通用属性协议（Generic Attribute Profile，GATT）实现BLE设备间连接和传输数据的开发。当两个设备间进行GATT通信交互时，依据设备功能的不同，可区分为GATT客户端和GATT服务端。

#### 解决方案

蓝牙低功耗场景长时任务开发步骤：

1.  申请ohos.permission.KEEP\_BACKGROUND\_RUNNING权限，配置方式请参见[声明权限](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/declare-permissions)。
2.  声明后台模式类型：
    
    在[module.json5配置文件](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/module-configuration-file)中abilities下的backgroundModes字段里，为需要使用长时任务的UIAbility声明相应的长时任务类型，配置文件中填写长时任务类型的[配置项](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/continuous-task#使用场景)。
    
    "backgroundModes": \[
      _// 蓝牙传输类型长时任务_
      "bluetoothInteraction"
    \],
    
3.  申请和取消长时任务。
    
    import { bundleManager, WantAgent, wantAgent } from '@kit.AbilityKit';
    import { backgroundTaskManager } from '@kit.BackgroundTasksKit';
    import { BusinessError } from '@kit.BasicServicesKit';
    
    class BackgroundRunningManager {
      _// 申请长时任务_
      public static async startBackgroundRunning(context?: Context) {
        _// 获取bundle应用信息_
        let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET\_BUNDLE\_INFO\_WITH\_APPLICATION);
        _// 通过wantAgent模块下getWantAgent方法获取WantAgent对象_
        let wantAgentInfo: wantAgent.WantAgentInfo = {
          _// 点击通知后，将要执行的动作列表_
          _// 添加需要被拉起应用的bundleName和abilityName_
          wants: \[
            {
              bundleName: bundleInfo.name,
              abilityName: 'MainAbility'
            }
          \],
          _// 指定点击通知栏消息后的动作是拉起ability_
          actionType: wantAgent.OperationType.START\_ABILITY,
          _// 使用者自定义的一个私有值_
          requestCode: 0,
          _// 点击通知后，动作执行属性_
          actionFlags: \[wantAgent.WantAgentFlags.UPDATE\_PRESENT\_FLAG\],
          _// 车钥匙长时任务子类型，从API version 16开始支持。只有申请bluetoothInteraction类型的长时任务，车钥匙子类型才能生效。_
          _// 确保extraInfo参数中的Key值为backgroundTaskManager.BackgroundModeType.SUB\_MODE，否则子类型不生效。_
          _// extraInfo: { \[backgroundTaskManager.BackgroundModeType.SUB\_MODE\] : backgroundTaskManager.BackgroundSubMode.CAR\_KEY }_
        };
    
        try {
          _// 通过wantAgent模块下getWantAgent方法获取WantAgent对象_
          wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => {
            try {
              backgroundTaskManager.startBackgroundRunning(context,
                backgroundTaskManager.BackgroundMode.BLUETOOTH\_INTERACTION, wantAgentObj).then(() => {
                console.info('Operation startBackgroundRunning succeeded');
              }).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 startBackgroundRunning. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}\`);
        }
      }
    
      _// 停止后台任务_
      public static async stopBackgroundRunning(context?: Context) {
        backgroundTaskManager.stopBackgroundRunning(context).then(() => {
          console.info(\`Succeeded in operationing stopBackgroundRunning.\`);
        }).catch((err: BusinessError) => {
          console.error(\`Failed to operation stopBackgroundRunning. Code is ${err.code}, message is ${err.message}\`);
        });
      }
    }
    
4.  调用方式。
    
    @Entry
    @Component
    struct Index {
      private context: Context = this.getUIContext().getHostContext() as Context;
    
      build() {
        Column({ space: 20 }) {
          Button() {
            Text('申请蓝牙长时任务').fontSize(25).fontWeight(FontWeight.Bold);
          }
          .type(ButtonType.Capsule)
          .margin({ top: 10 })
          .backgroundColor('#0D9FFB')
          .width(300)
          .height(40)
          .onClick(() => {
            _// 通过按钮申请长时任务_
            BackgroundRunningManager.startBackgroundRunning(this.context);
            _// 下方执行开发者自己的蓝牙相关任务_
          });
    
          Button() {
            Text('停止蓝牙长时任务').fontSize(25).fontWeight(FontWeight.Bold);
          }
          .type(ButtonType.Capsule)
          .margin({ top: 10 })
          .backgroundColor('#0D9FFB')
          .width(300)
          .height(40)
          .onClick(() => {
            _// 通过按钮停止长时任务_
            BackgroundRunningManager.stopBackgroundRunning(this.context);
          });
        }
        .height('100%')
        .width('100%')
        .justifyContent(FlexAlign.Center);
      }
    }
    

完整代码：

_/\*_
 _\*_
 _\*  \* Copyright (c) 2025 Huawei Device Co., Ltd._
 _\*  \* Licensed under the Apache License, Version 2.0 (the ""License"");_
 _\*  \* you may not use this file except in compliance with the License._
 _\*  \* You may obtain a copy of the License at_
 _\*  \*_
 _\*  \*     http://www.apache.org/licenses/LICENSE-2.0_
 _\*  \*_
 _\*  \* Unless required by applicable law or agreed to in writing, software_
 _\*  \* distributed under the License is distributed on an ""AS IS"" BASIS,_
 _\*  \* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied._
 _\*  \* See the License for the specific language governing permissions and_
 _\*  \* limitations under the License._
 _\*_
 _\*/_

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

class BackgroundRunningManager {
  _// 申请长时任务_
  public static async startBackgroundRunning(context?: Context) {
    _// 获取bundle应用信息_
    let bundleInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET\_BUNDLE\_INFO\_WITH\_APPLICATION);
    _// 通过wantAgent模块下getWantAgent方法获取WantAgent对象_
    let wantAgentInfo: wantAgent.WantAgentInfo = {
      _// 点击通知后，将要执行的动作列表_
      _// 添加需要被拉起应用的bundleName和abilityName_
      wants: \[
        {
          bundleName: bundleInfo.name,
          abilityName: 'MainAbility'
        }
      \],
      _// 指定点击通知栏消息后的动作是拉起ability_
      actionType: wantAgent.OperationType.START\_ABILITY,
      _// 使用者自定义的一个私有值_
      requestCode: 0,
      _// 点击通知后，动作执行属性_
      actionFlags: \[wantAgent.WantAgentFlags.UPDATE\_PRESENT\_FLAG\],
      _// 车钥匙长时任务子类型，从API version 16开始支持。只有申请bluetoothInteraction类型的长时任务，车钥匙子类型才能生效。_
      _// 确保extraInfo参数中的Key值为backgroundTaskManager.BackgroundModeType.SUB\_MODE，否则子类型不生效。_
      _// extraInfo: { \[backgroundTaskManager.BackgroundModeType.SUB\_MODE\] : backgroundTaskManager.BackgroundSubMode.CAR\_KEY }_
    };

    try {
      _// 通过wantAgent模块下getWantAgent方法获取WantAgent对象_
      wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj: WantAgent) => {
        try {
          backgroundTaskManager.startBackgroundRunning(context,
            backgroundTaskManager.BackgroundMode.BLUETOOTH\_INTERACTION, wantAgentObj).then(() => {
            console.info('Operation startBackgroundRunning succeeded');
          }).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 startBackgroundRunning. code is ${(error as BusinessError).code} message is ${(error as BusinessError).message}\`);
    }
  }

  _// 停止后台任务_
  public static async stopBackgroundRunning(context?: Context) {
    backgroundTaskManager.stopBackgroundRunning(context).then(() => {
      console.info(\`Succeeded in operationing stopBackgroundRunning.\`);
    }).catch((err: BusinessError) => {
      console.error(\`Failed to operation stopBackgroundRunning. Code is ${err.code}, message is ${err.message}\`);
    });
  }
}


@Entry
@Component
struct Index {
  private context: Context = this.getUIContext().getHostContext() as Context;

  build() {
    Column({ space: 20 }) {
      Button() {
        Text('申请蓝牙长时任务').fontSize(25).fontWeight(FontWeight.Bold);
      }
      .type(ButtonType.Capsule)
      .margin({ top: 10 })
      .backgroundColor('#0D9FFB')
      .width(300)
      .height(40)
      .onClick(() => {
        _// 通过按钮申请长时任务_
        BackgroundRunningManager.startBackgroundRunning(this.context);
        _// 下方执行开发者自己的蓝牙相关任务_
      });

      Button() {
        Text('停止蓝牙长时任务').fontSize(25).fontWeight(FontWeight.Bold);
      }
      .type(ButtonType.Capsule)
      .margin({ top: 10 })
      .backgroundColor('#0D9FFB')
      .width(300)
      .height(40)
      .onClick(() => {
        _// 通过按钮停止长时任务_
        BackgroundRunningManager.stopBackgroundRunning(this.context);
      });
    }
    .height('100%')
    .width('100%')
    .justifyContent(FlexAlign.Center);
  }
}

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/45/v3/OKlKPVOXSDeBDu6PzBlBMQ/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260709T134216Z&HW-CC-Expire=86400&HW-CC-Sign=38D8C3D4E6BC274CB014E38783E8802CEABEA2BBEF7EBCE4BE03D1523061BBA4)

*   使用钱包服务中的[数字车钥匙](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/wallet-carkey-overview)实现保活蓝牙的方案，主要用于车钥匙长时任务子类型。只有申请bluetoothInteraction类型的长时任务，车钥匙子类型才能生效。
*   确保extraInfo参数中的Key值为backgroundTaskManager.BackgroundModeType.SUB\_MODE，否则子类型不生效。
*   如果使用钱包拉起宿主应用长时任务，在执行backgroundTaskManager.startBackgroundRunning时，需要注意参数context是否能获取到。如果获取不到，可以在宿主应用启动时先缓存context。
*   开启蓝牙后台长时任务时，若蓝牙连接断开需在一分钟内重新连接成功，否则长时任务将自动结束。