目录

Location Positioning

Overview

In real-world app development, mobile device location information is frequently required for scenarios such as local weather inquiry, ride hailing, travel navigation, and movement path tracking. Location Kit provides two positioning methods: GNSS positioning and network positioning, as described in the following table.

Table 1 Description of positioning methods

Positioning Method

Description

Advantage

GNSS positioning

Locates a mobile device by using the location algorithm offered by the device chip to compute the location information provided by the Global Navigation Satellite System, for example, GPS, GLONASS, BeiDou, and Galileo.

Precise positioning

Network positioning

Locates a device through WLAN, Bluetooth, or base station positioning.

Fast positioning

By leveraging the system's location positioning capabilities, you can obtain real-time and accurate location information across various development scenarios. This document will introduce four common positioning scenarios and provide their specific implementation solutions to help you better understand the basic principles and development processes of location positioning.

Current Location Positioning

You can set appropriate positioning policies to obtain the device's current location information based on actual service requirements. Different positioning policies correspond to different positioning methods described in Table 1.

How to Implement

Location Kit provides the getCurrentLocation() API to obtain current location information. This API requires users to set key parameters within the location request options, including positioning priority and single positioning timeout. Location request information is divided into two types: CurrentLocationRequest and SingleLocationRequest. The positioning priorities corresponding to these two types are LocationRequestPriority and LocatingPriority.

How to Develop

  1. Apply for the required location permissions. For details, see Applying for Location Permissions or Application Permission Request.
  2. Instantiate the location request object to determine the current location positioning policy. Take the instantiation of a SingleLocationRequest object as an example. Set the positioning priority to PRIORITY_LOCATING_SPEED (fast positioning preferred) and the positioning timeout interval to 10 seconds. The sample code is as follows:
    let request: geoLocationManager.SingleLocationRequest = {
      locatingPriority: 0x502,
      locatingTimeoutMs: 10000
    };
  3. Call getCurrentLocation() to obtain current location information based on the positioning policy.
    geoLocationManager.getCurrentLocation(request).then((location: geoLocationManager.Location) => {
      // ...
    }).catch((err: BusinessError) => {
      hilog.error(0x0000, TAG, `getCurrentLocationPosition failed, code: ${err.code}, message: ${err.message}`);
      // ...
    });
  4. Call getAddressesFromLocation() to convert the coordinate information into the corresponding geographical location description.
    geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, async (err, data) => {
      if (data) {
        this.address = data[0]?.placeName || '';
        // ...
      } else {
        hilog.error(0x0000, TAG, `getAddressesFromLocation failed, code: ${err.code}, message: ${err.message}`);
        // ...
      }
    });
  5. View the effect of current location positioning.
    Figure 1 Obtaining the current location information

Real-time Location Positioning

You can set appropriate positioning policies to continuously obtain device location information based on actual user activity scenarios or power consumption scenarios. Different positioning policies correspond to different positioning methods described in Table 1.

How to Implement

You can subscribe to location changes through the on('locationChange') API to continuously obtain the device location information. Before that, you need to instantiate a LocationRequest or ContinuousLocationRequest object, and set an appropriate positioning scenario and location information reporting interval.

How to Develop

  1. Apply for the required location permissions. For details, see Applying for Location Permissions or Application Permission Request.
  2. Instantiate the location request object to determine the continuous location positioning policy. Take the instantiation of a ContinuousLocationRequest object as an example. Set the positioning scenario to NAVIGATION and the location information reporting interval to 1 second. The sample code is as follows:
    let request: geoLocationManager.ContinuousLocationRequest = {
      interval: 1,
      locationScenario: 0x401
    };
  3. Call on('locationChange') based on the positioning policy to subscribe to location changes and initiate a location request to continuously obtain the current device location information.
    geoLocationManager.on('locationChange', request, this.locationChange);
  4. In the callback function of on('locationChange'), call getAddressesFromLocation() to convert the coordinate information into the corresponding geographical location description.
    geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, async (err, data) => {
      if (data) {
        this.address = data[0]?.placeName || '';
        // ...
      } else {
        hilog.error(0x0000, TAG, `getAddressesFromLocation failed, code: ${err.code}, message: ${err.message}`);
        // ...
      }
    });
  5. When location information is no longer needed, promptly cancel the location change subscription and delete the corresponding location request to reduce device power consumption.
    try {
      geoLocationManager.off('locationChange', this.locationChange);
    } catch (err) {
      hilog.error(0x0000, TAG, `offLocationChange failed, code: ${err.code}, message: ${err.message}`);
    }
  6. View the effect of real-time location positioning.
    Figure 2 Obtaining real-time location information

Background Location Positioning

When an app switches to the background and still needs to obtain device location information, you can use this method for background location positioning.

How to Implement

Background location positioning requires the ohos.permission.LOCATION_IN_BACKGROUND permission for the app to access location in the background and the ohos.permission.KEEP_BACKGROUND_RUNNING permission for the application to run in the background. After obtaining the required permissions, start a continuous task with BackgroundMode set to LOCATION, and call on('locationChange') in its callback function to subscribe to location changes. This way, the application continuously obtains the current location information while running in the background.

How to Develop

  1. Apply for the required background location permissions. For details, see Applying for Location Permissions or Application Permission Request.
  2. In the module.json5 file, declare the continuous task permission and set BackgroundMode of the continuous task to LOCATION.

    Apply for the continuous task permission.

    {
      "name": "ohos.permission.KEEP_BACKGROUND_RUNNING",
      "reason": "$string:running_background",
      "usedScene": {
        "abilities": [
          "EntryAbility"
        ],
        "when": "always"
      }
    },

    Set BackgroundMode of the continuous task to LOCATION.

    "abilities": [
      {
        // ...
        "backgroundModes": [
          "location"
        ],
        // ...
      }
    ],
  3. Start the continuous task, and subscribe to location changes in its callback function. Then, initiate a location request, and continuously obtain the current location information in the background.

    Sample code for starting a continuous task:

    startContinuousTask(): void {
      let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
      if (!context) {
        return;
      }
      let wantAgentInfo: wantAgent.WantAgentInfo = {
        wants: [
          {
            bundleName: context.abilityInfo.bundleName,
            abilityName: context.abilityInfo.name
          }
        ],
        operationType: wantAgent.OperationType.START_ABILITY,
        requestCode: 1,
        wantAgentFlags: [wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
      };
    
      wantAgent.getWantAgent(wantAgentInfo).then((wantAgentObj) => {
        backgroundTaskManager.startBackgroundRunning(context,
          backgroundTaskManager.BackgroundMode.LOCATION, wantAgentObj).then(() => {
          this.onLocationChange();
          hilog.info(0x0000, TAG, 'startBackgroundRunning succeeded');
        }).catch((err: BusinessError) => {
          hilog.error(0x0000, TAG, `startBackgroundRunning failed, cause:  ${JSON.stringify(err)}`);
        });
      }).catch((err: BusinessError) => {
        hilog.error(0x0000, TAG, `getWantAgent failed, cause:  ${JSON.stringify(err)}`);
      });
    }

    Sample code for subscribing to location changes:

    onLocationChange(): void {
      let request: geoLocationManager.ContinuousLocationRequest = {
        interval: 1,
        locationScenario: 0x401
      };
      try {
        geoLocationManager.on('locationChange', request, this.locationChange);
        // ...
      } catch (err) {
        hilog.error(0x0000, TAG, `onLocationChange failed, code: ${err.code}, message: ${err.message}`);
        // ...
      }
    }
  4. In the location change callback, call getAddressesFromLocation() to convert the coordinate information into the corresponding geographical location description.
    geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, async (err, data) => {
      if (data) {
        this.address = data[0]?.placeName || '';
        // ...
      } else {
        hilog.error(0x0000, TAG, `getAddressesFromLocation failed, code: ${err.code}, message: ${err.message}`);
        // ...
      }
    });
  5. When location information is no longer needed, promptly close the continuous task, cancel the location change subscription, and delete the corresponding location request to reduce device power consumption.

    Sample code for closing a continuous task

    stopContinuousTask(): void {
      let context = this.getUIContext().getHostContext() as common.UIAbilityContext;
      if (!context) {
        return;
      }
      backgroundTaskManager.stopBackgroundRunning(context).then(() => {
        if (!this.isOnLocationChange) {
          this.offLocationChange();
        }
        hilog.info(0x0000, TAG, 'stopBackgroundRunning succeeded');
      }).catch((err: BusinessError) => {
        hilog.error(0x0000, TAG, `stopBackgroundRunning failed, cause:  ${JSON.stringify(err)}`);
      });
    }

    Sample code for unsubscribing from location changes:

    offLocationChange(): void {
      try {
        geoLocationManager.off('locationChange', this.locationChange);
      } catch (err) {
        hilog.error(0x0000, TAG, `offLocationChange failed, code: ${err.code}, message: ${err.message}`);
      }
    }
  6. View the effect of background location positioning.
Figure 3 Obtaining location information continuously in the background

Historical Location Retrieval

When the device's network signal is weak or when system power consumption is a concern, you can first obtain the system's cached latest location, which is the most recent historical location information.

How to Implement

Location Kit uses getLastLocation() to obtain the latest location information cached in the system. If the parameter list of this API is empty, and the return value is the location information defined by Location.

How to Develop

  1. Apply for the required location permissions. For details, see Applying for Location Permissions or Application Permission Request.
  2. Call getLastLocation() to obtain the latest location information cached in the system.
    let location = geoLocationManager.getLastLocation();
  3. Call getAddressesFromLocation() to convert the coordinate information into the corresponding geographical location description.
    geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, async (err, data) => {
      if (data) {
        this.address = data[0]?.placeName || '';
        // ...
      } else {
        hilog.error(0x0000, TAG, `getAddressesFromLocation failed, code: ${err.code}, message: ${err.message}`);
        // ...
      }
    });
  4. View the effect of historical location retrieval.
    Figure 4 Obtaining the historical location information

FAQs

[h2]Imprecise Location Positioning or Incorrect Location Information

Symptom

During location positioning, the location results obtained are inaccurate, or there are deviations when marking the location results on the map.

Possible Cause

Solution

[h2]Positioning Failed

Symptom

Location information cannot be obtained using the location function.

Possible Cause

Solution

[h2]Incorrect Cached Location Information

Symptom

After getCurrentLocation() is invoked to obtain the current location information and then getLastLocation() is invoked to obtain the cached location information, the obtained location information is inconsistent.

Possible Cause

All apps share the same cached location information in the system. It is possible that another app initiates location between two API calls, which leads to updating of the cached location information.

Solution

Compare the time when the location information is obtained and determine whether the cached location information has been updated.

Sample Code