HarmonyOS鸿蒙Next中是否支持后台持续获取 GPS 位置(如运动轨迹记录)

HarmonyOS鸿蒙Next中是否支持后台持续获取 GPS 位置(如运动轨迹记录) 我们正在开发一款跑步类 App,需在锁屏或切后台后持续每秒获取一次高精度定位,这个有API或者实现代码吗?急急急。感谢 大佬 了。

7 回复

实现 锁屏/切后台后每秒获取一次高精度定位 是完全可行的,但需要严格遵循系统权限管理、后台保活机制和定位 API 的规范使用。


一、前提条件

  1. 目标设备为真机(模拟器不支持后台高频定位)
  2. 用户手动授权 后台定位权限(不能静默申请)
  3. App 声明了后台定位能力backgroundModes: ["location"]
  4. 使用 ContinuousTask 保活,防止系统杀进程

二、配置文件:module.json5

{
  "module": {
    "requestPermissions": [
      { "name": "ohos.permission.LOCATION" },
      { "name": "ohos.permission.LOCATION_IN_BACKGROUND" },
      { "name": "ohos.permission.KEEP_BACKGROUND_RUNNING" }
    ],
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "type": "page",
        "backgroundModes": ["location"]  // ⚠️ 关键:声明后台定位模式
      }
    ]
  }
}

三、核心代码(ArkTS)

1. 定位管理类:RunningLocationService.ets

import geolocation from '@ohos.geolocation';
import backgroundTaskManager from '@ohos.backgroundTaskManager';
import common from '@ohos.app.ability.common';
import hilog from '@ohos.hilog';

const TAG = 'RunningLocation';

export class RunningLocationService {
  private context: common.UIAbilityContext;
  private isRunning = false;
  private taskId: number = -1;
  private callback: geolocation.LocationCallback | null = null;

  constructor(context: common.UIAbilityContext) {
    this.context = context;
  }

  async start(): Promise<void> {
    if (this.isRunning) return;

    try {
      // 1. 检查并请求权限(必须由用户主动触发)
      const auth = await geolocation.checkLocationAuthorization();
      if (auth !== geolocation.LocationAuthorizationStatus.AUTHORIZED) {
        await geolocation.requestLocationAuthorization();
        const newAuth = await geolocation.checkLocationAuthorization();
        if (newAuth !== geolocation.LocationAuthorizationStatus.AUTHORIZED) {
          throw new Error('未获得定位权限');
        }
      }

      // 2. 开启定位服务
      await geolocation.enableLocation();

      // 3. 申请后台持续任务(保活)
      this.taskId = await backgroundTaskManager.startContinuousTask(
        this.context,
        backgroundTaskManager.ContinuousTaskType.CONTINUOUS_TASK_TYPE_LOCATION
      );

      // 4. 配置高精度 + 1秒间隔
      const config: geolocation.LocationRequestConfig = {
        priority: geolocation.LocationRequestPriority.HIGH_ACCURACY,
        scenario: geolocation.LocationRequestScenario.RUNNING, // 跑步场景优化
        timeInterval: 1000,     // 1秒
        distanceInterval: 0,    // 忽略距离变化
        maxAccuracy: 5,         // 要求5米内精度
        cacheValidTime: 0       // 不用缓存
      };

      // 5. 注册回调
      this.callback = (location: geolocation.Location) => {
        hilog.info(TAG, `📍定位: ${location.latitude}, ${location.longitude}, 精度=${location.accuracy}m`);
        // TODO: 发送到UI、记录轨迹、计算配速等
      };

      geolocation.on('locationChange', config, this.callback);
      this.isRunning = true;
      hilog.info(TAG, '✅ 跑步定位服务已启动(支持锁屏/后台)');
    } catch (err) {
      hilog.error(TAG, `❌ 启动失败: ${JSON.stringify(err)}`);
      this.stop();
      throw err;
    }
  }

  stop(): void {
    if (!this.isRunning) return;

    if (this.callback) {
      geolocation.off('locationChange', this.callback);
      this.callback = null;
    }

    if (this.taskId !== -1) {
      backgroundTaskManager.stopContinuousTask(this.context, this.taskId)
        .catch(e => hilog.error(TAG, `停止保活任务失败: ${JSON.stringify(e)}`));
      this.taskId = -1;
    }

    geolocation.disableLocation().catch(() => {});
    this.isRunning = false;
    hilog.info(TAG, '⏹️ 定位服务已停止');
  }
}

2. 在 Ability 中调用(用户点击“开始跑步”时触发)

// EntryAbility.ets
import { RunningLocationService } from '../common/RunningLocationService';
import UIAbility from '@ohos.app.ability.UIAbility';

export default class EntryAbility extends UIAbility {
  private locationService: RunningLocationService | null = null;

  onCreate() {
    this.locationService = new RunningLocationService(this.context);
  }

  // 假设用户点击“开始跑步”按钮
  onStartRunning() {
    this.locationService?.start().catch(err => {
      console.error('定位启动失败,请检查权限或系统设置', err);
      // 可弹窗提示用户去设置中开启“后台高耗电”和“后台定位”
    });
  }

  onDestroy() {
    this.locationService?.stop();
  }
}

测试建议

  1. 真机测试(华为 Mate/P系列、Pura 系列等)
  2. 启动 App → 点击“开始跑步” → 锁屏 → 观察日志是否持续输出
  3. 进入 设置 > 电池 > 应用启动管理,关闭自动管理,手动允许后台活动

更多关于HarmonyOS鸿蒙Next中是否支持后台持续获取 GPS 位置(如运动轨迹记录)的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


楼主您好,您可参考以下方案:

【解决方案】

示例代码基于位置服务获取设备定位信息:本示例通过@kit.LocationKit中的geoLocationManager实现获取缓存位置、获取当前位置和持续定位功能,并结合@kit.BackgroundTasksKit中的backgroundTaskManager开启长时任务,实现后台定位功能,同时运用map.Marker将位置信息标记在地图上。开发者可以在需要用到设备位置信息的开发场景中,如查看所在城市天气、出行打车、旅行导航以及观察运动轨迹等,集成本示例代码实现定位功能。

1、在进入长时任务前注意申请位置权限和后台运行权限:

// 启动定位之前先申请位置权限
let per = await reqPermissionsFromUser(['ohos.permission.APPROXIMATELY_LOCATION', 'ohos.permission.LOCATION'],
  this.getUIContext().getHostContext() as common.UIAbilityContext)
'requestPermissions': [
  {
    "name": "ohos.permission.APPROXIMATELY_LOCATION",
    "reason": "$string:app_name",
    "usedScene": {}
  },
  {
    "name": "ohos.permission.LOCATION",
    "reason": "$string:app_name",
    "usedScene": {}
  },
  {
    "name": "ohos.permission.LOCATION_IN_BACKGROUND",
    "reason": "$string:app_name",
    "usedScene": {}
  },
  {
    "name": "ohos.permission.KEEP_BACKGROUND_RUNNING",
    "reason": "$string:app_name",
    "usedScene": {}
  }
],

2、声明后台模式类型:在module.json5文件中为需要使用长时任务的UIAbility声明相应的长时任务类型,配置文件中填写长时任务类型的配置项。

"abilities": [
  {
    "name": "EntryAbility",
    "srcEntry": "./ets/entryability/EntryAbility.ets",
    "description": "$string:EntryAbility_desc",
    "icon": "$media:layered_image",
    "label": "$string:EntryAbility_label",
    "startWindowIcon": "$media:startIcon",
    "startWindowBackground": "$color:start_window_background",
    "exported": true,
    "backgroundModes": ["location"],// 声明支持定位后台模式
    "skills": [
      {
        "entities": [
          "entity.system.home"
        ],
        "actions": [
          "action.system.home"
        ]
      }
    ]
  },
],

3、添加后台应用的相关信息:

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

4、启动长时任务时,注意长时任务类型,需要与具体的任务对应,本例中为获取位置信息所以需要启动"location"类型的任务。

let list: Array<string> = ["location"]; // 注意长时任务类型
backgroundTaskManager.startBackgroundRunning(this.context, list, wantAgentObj)
  .then(async (res: backgroundTaskManager.ContinuousTaskNotification) => {
    console.info("Operation startBackgroundRunning succeeded");
    // 此处执行具体的长时任务逻辑,该示例中为获取位置信息

    if (!geoLocationManager.isLocationEnabled()) {
      this.message = 'permission error';
    }
    let request: geoLocationManager.ContinuousLocationRequest = {
      'interval': 1,
      'locationScenario': geoLocationManager.UserActivityScenario.NAVIGATION
    }
    try {
      geoLocationManager.on('locationChange', request, (location: geoLocationManager.Location) => {
        this.message = JSON.stringify(location);
        this.seq++;
        console.info(this.seq.toString(), 'testing: ', JSON.stringify(location));
      });
    } catch (err) {
      this.message = JSON.stringify(err);
    }
  })
  .catch((error: BusinessError) => {
    console.error(`Failed to Operation startBackgroundRunning. code is ${error.code} message is ${error.message}`);
  });

【背景知识】

  • 长时任务(ArkTS):应用退至后台后,在后台需要长时间运行用户可感知的任务,如播放音乐、导航等。为防止应用进程被挂起,导致对应功能异常,可以申请长时任务,使应用在后台长时间运行。
  • Location Kit(位置服务):位置子系统使用多种定位技术提供服务,如GNSS定位、基站定位、WLAN/蓝牙定位(基站定位、WLAN/蓝牙定位后续统称“网络定位技术”);通过这些定位技术,无论用户设备在室内或是户外,都可以准确地确定设备位置。
  • geoLocationManager.on(‘locationChange’):获取时候位置的接口,开启位置变化订阅,并发起定位请求。

应该支持

在鸿蒙(HarmonyOS)系统中,支持后台持续获取高精度GPS位置(包括锁屏/切后台场景),可通过以下方案实现每秒定位:

实现方案

1. 权限配置(module.json5)

"requestPermissions": [
  {
    "name": "ohos.permission.LOCATION_IN_BACKGROUND",
    "reason": "后台持续定位",
    "usedScene": { "abilities": ["EntryAbility"], "when": "always" }
  },
  {
    "name": "ohos.permission.KEEP_BACKGROUND_RUNNING",
    "reason": "保持后台运行",
    "usedScene": { "abilities": ["EntryAbility"], "when": "always" }
  }
],
"abilities": [
  {
    "backgroundModes": ["location"]  // 声明定位长时任务
  }
]

2. 核心代码实现

import geoLocationManager from '@kit.GeoLocationKit';
import backgroundTaskManager from '@kit.ResourceScheduleKit';
import wantAgent from '@kit.AbilityKit';

// 配置高精度定位参数(每秒1次)
const locationRequest: geoLocationManager.LocationRequest = {
  priority: geoLocationManager.LocationRequestPriority.FIRST_FIX, // 最高精度
  scenario: geoLocationManager.LocationRequestScenario.NAVIGATION, // 导航级定位
  timeInterval: 1,  // 1秒间隔
  distanceInterval: 0, // 无距离限制
  maxAccuracy: 0 // 最高精度
};

// 开启后台定位任务
async function startBackgroundTracking() {
  const context = getContext(this) as common.UIAbilityContext;

  // 1. 创建WantAgent(后台任务触发入口)
  const wantAgentInfo = {
    wants: [{ bundleName: context.abilityInfo.bundleName }],
    requestCode: 0,
    operationType: wantAgent.OperationType.START_ABILITY
  };
  const agent = await wantAgent.getWantAgent(wantAgentInfo);
  // 2. 启动长时定位任务
  await backgroundTaskManager.startBackgroundRunning(
    context,
    backgroundTaskManager.BackgroundMode.LOCATION,
    agent
  );
  // 3. 注册位置监听(每秒回调)
  geoLocationManager.on('locationChange', locationRequest, (location) => {
    console.log(`实时位置:${location.latitude},${location.longitude}`);
    // 此处处理轨迹记录逻辑
  });
}

// 停止定位
function stopTracking() {
  geoLocationManager.off('locationChange'); // 取消监听
  backgroundTaskManager.stopBackgroundRunning(); // 结束长时任务
}

关键注意事项

权限要求:

  • 必须申请ohos.permission.LOCATION_IN_BACKGROUND
  • 必须申请ohos.permission.KEEP_BACKGROUND_RUNNING
  • 用户需在设置中开启 "始终允许"定位权限

设备限制:

  • 需引导用户关闭省电模式(如vivo的i管家→允许后台高耗电)
  • 测试时避免充电状态(可能绕过省电限制)

性能优化:

// 按需调整定位参数(降低精度可省电)
const batterySaverRequest = {
  priority: geoLocationManager.LocationRequestPriority.ACCURACY,
  timeInterval: 5  // 低功耗时延长间隔
};

状态验证:

  • 成功时状态栏显示定位图标
  • 通过backgroundTaskManager.getBackgroundRunningStatus()检查任务状态

完整工作流程

graph TD
    A[申请后台定位权限] --> B[配置长时任务类型]
    B --> C[启动BackgroundMode.LOCATION]
    C --> D[注册locationChange监听]
    D --> E[每秒接收高精度定位]
    E --> F[存储轨迹数据]
    F --> G{是否继续?}
    G -- 是 --> E
    G -- 否 --> H[取消监听并结束任务]

此方案满足运动轨迹记录场景需求,实测中需注意:

  • 首次使用需手动授予"始终允许"权限
  • 华为设备需关闭"电池优化"
  • 持续定位会显著增加耗电,建议提供省电模式选项

高频定位(每秒1次)会显著增加功耗!!!(如果是专业就当我没说好吧)注意平衡功耗!!!

ⅰ.定位服务API:
    ohos.location.LocationManager
ⅱ.后台任务API:
ohos.resourcemanager.BackgroundTaskManager
ⅲ.相关权限API:
    ohos.permission.LOCATION
    ohos.permission.BACKGROUND_LOCATION
ⅳ.若需要锁屏后CPU不休眠,可结合 PowerManager 申请唤醒锁
ohos.permission.KEEP_BACKGROUND_RUNNING 

实现代码如下:
配置权限  module.json5
__________________________开始于下

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.LOCATION",
        "reason": "$string:location_reason",
        "usedScene": { "abilities": [".MainAbility"], "when": "always" }
      },
      {
        "name": "ohos.permission.BACKGROUND_LOCATION",
        "reason": "$string:bg_location_reason",
        "usedScene": { "abilities": [".MainAbility"], "when": "always" }
      }
    ]
  }
}

___________________截止于此

申请后台运行能力_____(这一段是用Java写的,我才从Java转还不太熟ArkTs)

import ohos.resourcemanager.BackgroundTaskManager;
import ohos.resourcemanager.continuoustask.ContinuousTaskParam;
import ohos.resourcemanager.continuoustask.ContinuousTaskType;

// 申请后台持续任务(定位类型)
ContinuousTaskParam param = new ContinuousTaskParam(ContinuousTaskType.TYPE_LOCATION);
BackgroundTaskManager.getInstance().startContinuousTask(getContext(), param, (result, msg) -> {
    if (result) {
        startLocationUpdate();
    }
}

________初始化定位管理器并设置高精度监听

import ohos.location.*;
import ohos.rpc.RemoteException;

private LocationManager locationManager;
private MyLocationListener locationListener;

// 初始化
private void initLocationManager() {
    locationManager = LocationManager.getInstance(getContext());
    locationListener = new MyLocationListener();
    
    // 配置高精度定位参数
    LocationRequest request = new LocationRequest(LocationRequest.PRIORITY_HIGH_ACCURACY);
    request.setInterval(1000); // 定位间隔1秒
    request.setFastestInterval(1000); // 最快间隔1秒
}

// 开始持续定位
private void startLocationUpdate() {
    try {
        locationManager.requestLocationUpdates(request, locationListener);
    } catch (RemoteException e) {
        e.printStackTrace();
    }
}

// 自定义位置监听器
class MyLocationListener implements LocationCallback {
    @Override
    public void onLocationChanged(Location location) {
        // 获取定位结果
        double latitude = location.getLatitude();
        double longitude = location.getLongitude();
        // 处理定位数据
    }

    @Override
    public void onStatusChanged(int type) {
        // 变化回调
    }
}

HarmonyOS Next支持后台持续获取GPS位置。系统提供后台任务管理机制,允许应用申请后台定位权限。开发者需在配置文件中声明ohos.permission.LOCATIONohos.permission.LOCATION_IN_BACKGROUND权限,并使用geolocationgeoLocationManager接口进行位置订阅。应用进入后台后,系统会维持位置更新,但会根据设备状态进行资源调度。

在HarmonyOS Next中,可以通过后台任务管理位置服务的API实现应用在后台持续获取GPS位置。以下是关键实现步骤和代码示例:

1. 申请权限

module.json5配置文件中声明位置权限和后台持续任务权限:

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.LOCATION",
        "reason": "用于记录运动轨迹"
      },
      {
        "name": "ohos.permission.KEEP_BACKGROUND_RUNNING",
        "reason": "需要后台持续获取位置"
      }
    ]
  }
}

2. 后台任务配置

module.json5中配置后台任务类型为location

{
  "module": {
    "abilities": [
      {
        "backgroundModes": ["location"]
      }
    ]
  }
}

3. 核心实现代码

使用@ohos.location@ohos.backgroundTaskManager模块:

import location from '@ohos.location';
import backgroundTaskManager from '@ohos.backgroundTaskManager';

// 初始化定位参数
let requestInfo: location.LocationRequest = {
  priority: location.LocationRequestPriority.FIRST_FIX, // 高精度定位
  scenario: location.LocationScenario.UNSET, // 运动场景
  timeInterval: 1, // 1秒间隔
  distanceInterval: 0, // 距离间隔为0米,按时间触发
  maxAccuracy: 10 // 精度10米以内
};

// 启动持续定位
async function startContinuousLocation() {
  try {
    // 申请后台任务
    await backgroundTaskManager.requestSuspendDelay();
    
    // 开始定位
    await location.on('locationChange', requestInfo, (locationData) => {
      console.log(`位置更新: ${JSON.stringify(locationData)}`);
      // 处理位置数据(存储或上传)
    });
  } catch (error) {
    console.error(`定位失败: ${error.code}, ${error.message}`);
  }
}

// 停止定位
function stopContinuousLocation() {
  location.off('locationChange');
}

4. 注意事项

  • 电量优化:每秒定位会显著增加耗电,建议根据运动速度动态调整频率
  • 精度平衡:高精度模式(GNSS)在室内可能失效,可结合网络定位
  • 后台保活:需在设置中允许应用的后台活动权限
  • 隐私合规:必须提供清晰的权限使用说明

5. 完整示例架构

// 位置服务管理类
class LocationTracker {
  private isTracking: boolean = false;
  
  async startTracking() {
    if (this.isTracking) return;
    
    // 检查权限
    // 启动后台任务
    // 开始位置监听
    this.isTracking = true;
  }
  
  async stopTracking() {
    // 停止所有监听
    this.isTracking = false;
  }
}

此方案可在锁屏和后台状态下维持GPS定位,满足运动轨迹记录需求。实际开发中需测试不同机型的后台策略差异。

回到顶部