How to Integrate Location Kit in HarmonyOS Watches
Tags: openharmony, watch, demo, opensource
Published: 2022-03-23 11:41:30

These days, the smart watch market is highly competitive. Watches no longer just tell us the time, rather they can allow us to take and make calls, scan barcodes, check our location, and perform a variety of other functions. They are particularly useful for vulnerable groups such as children and elderly people, which has opened new doors for businesses. Huawei's HarmonyOS-powered watch is one such device that aims to create an intelligent user experience. It does this by leveraging the capabilities of HMS Core Location Kit, which are: fused location, activity identification, and geofence. In this article, I'll show you how the location function on HarmonyOS watches works, through several simple steps.

## Advantages and Restrictions of Location Kit​
1. It implements the geofence function based on chips, saving power.
2. It improves roadside location accuracy in urban canyons, and implements location accurate to less than a meter in open areas based on the Real-time Kinematic (RTK) technology.
3. The latest Location SDK can be used only on devices running HMS Core (APK) 6.0.0 or later. If HMS Core (APK) is not installed or its version is earlier than 6.0.0, the SDK functions properly but cannot be automatically updated.
4. To ensure app integrity, HarmonyOS uses a digital certificate and a profile to ensure that only packages with signed HarmonyOS Ability Package (HAP) files can be installed on devices.

## Demo Introduction​
I have provided a simple demo here. You can use the demo to experience how to implement location on HarmonyOS watches. The demo includes requesting location updates, obtaining the cached location, checking whether the location is available, and checking and setting the location permissions.

## Integration Procedure​
I'll now show you how to run the demo using source code, so that you can understand how it is implemented.
### Preparations​
1. Preparing Tools
- Test device: a Huawei smart watch running HarmonyOS 2.0 or later
- Development tool: DevEco Studio 2.1.0.201 or later

2. Preparing for the Development

(1) Register as a Huawei developer and create an app. Refer to the [Location Kit Development Preparations](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/introduction-0000001050706106?ha_source=hms1) to create an app in AppGallery Connect.
(2) Generate a digital certificate and profile. This requires you to apply for an app debugging certificate, register a debugging device, apply for a debugging profile, and configure signature information.
(3) Generate a signing certificate fingerprint and configure it.
(4) Integrate the Location SDK.
Download the **agconnect-services.json** file from AppGallery Connect, and place it in the entry\src\main\resources\rawfile directory.

Add **apply plugin: 'com.huawei.agconnect'** as a line under the file header declaration, and add the Maven repository address and a dependency on the AppGallery Connect service in the project-level **build.gradle** file.

```
buildscript {
    repositories {
        maven {url 'https://repo.huaweicloud.com/repository/maven/'}
        // Configure the Maven repository address for the HMS Core SDK.
        maven {url 'https://developer.huawei.com/repo/'}
        jcenter()
    }
    dependencies {
        classpath 'com.huawei.ohos:hap:2.4.4.2'
        // Add a dependency on the AppGallery Connect service.
        classpath 'com.huawei.agconnect:agcp-harmony:1.1.0.300'
        classpath 'com.huawei.ohos:decctest:1.2.4.0'
    }
}

allprojects {
    repositories {
        maven {url 'https://repo.huaweicloud.com/repository/maven/'}
        // Configure the Maven repository address for the HMS Core SDK.
        maven {url 'https://developer.huawei.com/repo/'}
        jcenter()
    }
}
```
Add a dependency in the app-level **build.gradle** file. You can replace the version number as needed.

```
dependencies {
implementation 'com.huawei.hms:location-ohos:6.0.0.300'
// Add a dependency on AppGallery Connect.
implementation 'com.huawei.agconnect:agconnect-core-harmony:1.1.0.300'
}
```
If you need to configure obfuscation, open the obfuscation configuration file **proguard-rules.pro** in the app's root directory of your project and add configurations to exclude the HMS Core SDK from obfuscation.

The figure below shows the demo effect.
![Demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vvfmcuryaagyv4yojh0x.png)

### Key Steps​
1. Declare required permissions in **reqPermissions** in the **config.json** file.
HarmonyOS provides two types of location permissions: **ohos.permission.LOCATION** (location permission) and **ohos.permission.LOCATION_IN_BACKGROUND** (background location permission). Note that network permission is also required.

```
"reqPermissions": [
   {
    "reason": "get Local Location",
    "name": "ohos.permission.LOCATION",
    "usedScene": {
      "ability": [
        "com.huawei.codelab.MainAbility",
      ],
      "when": "always"
    }
  },
  {
    "name": "ohos.permission.GET_NETWORK_INFO"
  },
  {
    "name": "ohos.permission. LOCATION_IN_BACKGROUND"
  }
```
2. Dynamically apply for the **ohos.permission.LOCATION** and **ohos.permission.LOCATION_IN_BACKGROUND** permissions in the code.

```
/The following uses the location permission as an example.
if (verifySelfPermission("ohos.permission.LOCATION") != IBundleManager.PERMISSION_GRANTED) {
    printLog(HiLog.INFO, TAG, "Self: LOCATION permission not granted!");
    if (canRequestPermission("ohos.permission.LOCATION")) {
        printLog(HiLog.INFO, TAG, "Self: can request permission here");
        requestPermissionsFromUser(
                new String[]{"ohos.permission.LOCATION"}, REQUEST_CODE);
    } else {
        printLog(HiLog.WARN, TAG, "Self: enter settings to set permission");
    }
} else {
    printLog(HiLog.INFO, TAG, "Self: LOCATION permission granted!");
}
```
### Key Code​
1. Create a location service client.
Create a **FusedLocationProviderClient** instance in the **onStart() **method of **BaseAbilitySlice**, and use this instance to call location-related APIs.

```
public FusedLocationProviderClient fusedLocProviderClient;
@Override
protected void onStart(Intent intent) {
    super.onStart(intent);
    fusedLocProviderClient = new FusedLocationClient(this);
}
```
2. Check the device location settings.
Call **LocationRequest** to set location request parameters, including the location update interval (in milliseconds), weight, and location information language. Before requesting callback, call the location service to check location settings.

```
private void checkLocationSettings() {
    LocationRequest locationRequest = new LocationRequest();
    locationRequest.setPriority(100);
    LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
    LocationSettingsRequest request =
            builder.addLocationRequest(locationRequest).setAlwaysShow(false).setNeedBle(false).build();
    settingsClient.checkLocationSettings(request)
            .addOnSuccessListener(response -> {
                // Device location settings meet the requirements.
            })
            .addOnFailureListener(exp -> {
                // Device location settings do not meet the requirements.
            });
}
```
3. Implement the location function.
Call **requestLocationUpdates()** for continuous location.

```
fusedLocProviderClient.requestLocationUpdates(locationRequest, locationCallback)
        .addOnSuccessListener(var -> {
            // Processing when the API call is successful.
        })
        .addOnFailureListener(e -> {
            // Processing when the API call fails.          
        });
```
Call **removeLocationUpdates()** to stop requesting location updates.

```
// Note: When location updates are stopped, the mLocationCallback object must be the same object as LocationCallback in the requestLocationUpdates() method.
fusedLocProviderClient.removeLocationUpdates(locationCallback)
        .addOnSuccessListener(var -> {
            // Processing when the API call is successful.
        })
        .addOnFailureListener(e -> {
            // Processing when the API call fails.      
        });
```
Define the location update callback.

```
LocationCallback locationCallback = new LocationCallback() {
    @Override
    public void onLocationResult(LocationResult locationResult) {
        if (locationResult != null) {
            // Process the location callback result.
        }
    }
    @Override
    public void onLocationAvailability(LocationAvailability locationAvailability) {
        super.onLocationAvailability(locationAvailability);
        if (locationAvailability != null) {
            // Process the location status.
        }
    }
};
```
### Related Parameters​
1.Parameter for setting the location type. The options are as follows:
- 100: GNSS location
- 102 or 104: network location
- 105: indicates that locations are being received passively as opposed to being requested proactively.

2.Parameter for setting the location language. Currently, the options include only EN and CN.

3.Parameter for setting the number of location updates (setNumUpdates). If the value is 3, the app will receive three location updates. To continuously receive location updates, you are advised to use the default value.

## References​
Location Kit [official website](https://developer.huawei.com/consumer/cn/hms/huawei-locationkit?ha_source=hms1)
Location Kit [Development Guide](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/harmonyos-introduction-0000001121618904?ha_source=hms1)
[Reddit](https://www.reddit.com/r/HMSCore/) to join developer discussions
[GitHub](https://github.com/HMS-Core) to download the sample code
[Stack Overflow](https://stackoverflow.com/questions/tagged/huawei-mobile-services?tab=Votes) to solve integration problems