Building High-Precision Location Services with Location Kit

Published: 2021-07-30 06:43:44

HUAWEI Location Kit provides you with the tools to build ultra-precise location services into your apps, by utilizing GNSS, Wi-Fi, base stations, and a range of cutting-edge hybrid positioning technologies. Location Kit-supported solutions give your apps a leg up in a ruthlessly competitive marketplace, making it easier than ever for you to serve a vast, global user base. 

Location Kit currently offers three main functions: fused location, geofence, and activity identification. When used in conjunction with the Map SDK, which is supported in 200+ countries and regions and 100+ languages, you'll be able to bolster your apps with premium mapping services that enjoy a truly global reach.

Fused location provides easy-to-use APIs that are capable of obtaining the user's location with meticulous accuracy, and doing so while consuming a minimal amount of power. HW NLP, Huawei's exclusive network location service, makes use of crowdsourced data to achieve heightened accuracy. Such high-precision, cost-effective positioning has enormous implications for a broad array of mobile services, including ride hailing navigation, food delivery, travel, and lifestyle services, providing customers and service providers alike with the high-value, real time information that they need. 

To avoid boring you with the technical details, we've provided some specific examples of how positioning systems, geofence, activity identification, map display and route planning services can be applied in the real world.

For instance, you can use Location kit to obtain the user's current location and create a 500-meter geofence radius around it, which can be used to determine the user's activity status when the geofence is triggered, then automatically plan a route based on this activity status (for example, plan a walking route when the activity is identified as walking), and have it shown on the map.

**This article addresses the following functions: **

1.	Fused location: Incorporates GNSS, Wi-Fi, and base station data via easy-to-use APIs, making it easy for your app to obtain device location information.
2.	Activity identification: Identifies the user's motion status, using the acceleration sensor, network information, and magnetometer, so that you can tailor your app to account for the user's behavior.
3.	Geofence: Allows you to set virtual geographic boundaries via APIs, to send out timely notifications when users enter, exit, or remain with the boundaries.
4.	Map display: Includes the map display, interactive features, map drawing, custom map styles, and a range of other features.
5.	Route planning: Provides HTTP/HTTPS APIs for you to initiate requests using HTTP/HTTPS, and obtain the returned data in JSON format.

**Usage scenarios:**

1.	Using high-precision positioning technology to obtain real time location and tracking data for delivery or logistics personnel, for optimally efficient services. In the event of accidents or emergencies, the location of personnel could also be obtained with ease, to ensure their quick rescue.

2.	Creating a geofence in the system, which can be used to monitor an important or dangerous area at all times. If someone enters such an area without authorization, the system could send out a proactive alert. This solution can also be linked with onsite video surveillance equipment. When an alert is triggered, the video surveillance camera could pop up to provide continual monitoring, free of any blind spots. 

3.	Tracking patients with special needs in hospitals and elderly residents in nursing homes, in order to provide them with the best possible care. Positioning services could be linked with wearable devices, for attentive 24/7 care in real time.

4.	Using the map to directly find destinations, and perform automatic route planning.

**I.	Advantages of Location Kit and Map Kit**

1.	Low-power consumption (Location Kit): Implements geofence using the chipset, for optimized power efficiency

2.	High precision (Location Kit): Optimizes positioning accuracy in urban canyons, correctly identifying the roadside of the user. Sub-meter positioning accuracy in open areas, with RTK (Real-time kinematic) technology support. Personal information, activity identification, and other data are not uploaded to the server while location services are performed. As the data processor, Location Kit only uses data, and does not store it.

3.	Personalized map displays (Map Kit): Offers enriching map elements and a wide range of interactive methods for building your map.

4.	Broad-ranging place searches (Map Kit): Covers 130+ million POIs and 150+ million addresses, and supports place input prompts.

5.	Global coverage: Supports 200+ countries/regions, and 40+ languages.

For more information and development guides, [please visit:] 
(https://developer.huawei.com/consumer/en/hms/huawei-MapKit)

**II.	Demo App Introduction**

In order to illustrate how to integrate Location Kit and Map Kit both easily and efficiently, we've provided a case study here, which shows the simplest coding method for running the demo.
This app is used to create a geofence on the map based on the location when the user opens the app. The user can drag on the red mark to set a destination. After being confirmed, when the user triggers the geofence condition, the app will automatically detect their activity status and plan a route for the user, such as planning a walking route if the activity status is walking, or cycling route if the activity status is cycling. You can also implement real-time voice navigation for the planned route. 

**III.	Development Practice**	

You need to set the priority (which is 100 by default) before requesting locations. To request the precise GPS location, set the priority to 100. To request the network location, set the priority to 102 or 104. If you only need to passively receive locations, set the priority to 105.

Parameters related to activity identification include VEHICLE (100), BIKE (101), FOOT (102), and STILL (103).
Geofence-related parameters include ENTER_GEOFENCE_CONVERSION (1), EXIT_GEOFENCE_CONVERSION (2), and DWELL_GEOFENCE_CONVERSION (4).
The following describes how to run the demo using source code, helping you understand the implementation details.

**Preparations**
1.	Preparing Tools

1)	Huawei phones (It is recommended that multiple devices be tested)
2)	Android Studio

2.	Registering as a Developer

1)	Register as a [Huawei developer](https://developer.huawei.com/consumer/en/?ha_source=hms1).
2)	Create an app in AppGallery Connect.
Create an app in AppGallery Connect by referring to [Location Kit development preparations](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/config-agc-0000001057629153?ha_source=hms1) or [Map Kit development preparations](https://developer.huawei.com/consumer/en/hms/huawei-MapKit?ha_source=hms1).

	Enable Location Kit and Map Kit for the app on the Manage APIs page.
	Add the SHA-256 certificate fingerprint.
	Download the agconnect-services.json file and add it to the app directory of the project.
3)	Create an Android demo project.
4)	Learn about the function restrictions.
To use the route planning function of Map Kit, refer to [Supported Countries/Regions (Route Planning)](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides-V5/supported-countries-and-regions-route-planning-0000001091168530-V5?ha_source=hms1).
To use other services of Map Kit, refer to [Supported Countries/Regions](https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides-V5/supported-countries-and-regions-0000001050160946-V5?ha_source=hms1)

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cvdnfpbudyiey978f8qz.png)
 
3.	Running the Demo App

1)	Install the app on the test device after debugging the project in Android Studio successfully
2)	Replace the project package name and JSON file with those of your own.
3)	Tap related button in the demo app to create a geofence which has a radius of 200 and is centered on the current location automatically pinpointed by the demo app.
4)	Drag the mark point on the map to select a destination.
5)	View the route that is automatically planned based on the current activity status when the geofence is triggered. 
The following figure shows the demo effect:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7b4oqpd4daqncmyeq5m0.png)
 

**Key Steps**

1.	Add the Huawei Maven repository to the project-level build.gradle file.
Add the following Maven repository address to the project-level build.gradle file of your Android Studio project:

```
buildscript {
    repositories {
        maven { url 'http://developer.huawei.com/repo/'}
    }
dependencies {
        ...
        // Add the AppGallery Connect plugin configuration.
        classpath 'com.huawei.agconnect:agcp:1.4.2.300'
    }
}allprojects {
    repositories {
        maven { url 'http://developer.huawei.com/repo/'}
    }
}
```

2.	Add dependencies on the SDKs in the app-level build.gradle file.

```
dependencies {
   implementation 'com.huawei.hms:location:5.1.0.300'
   implementation 'com.huawei.hms:maps:5.2.0.302' }
```

3.	Add the following configuration to the next line under apply plugin: 'com.android.application' in the file header:
apply plugin: 'com.huawei.agconnect'

Note:
•	You must configure apply plugin: 'com.huawei.agconnect' under apply plugin: 'com.android.application'.
•	The minimum Android API level (minSdkVersion) required for the HMS Core Map SDK is 19.

4.	Declare system permissions in the AndroidManifest.xml file.
Location Kit uses GNSS, Wi-Fi, and base station data for fused location, enabling your app to quickly and accurately obtain users' location information. Therefore, Location Kit requires permissions to access Internet, obtain the fine location, and obtain the coarse location. If your app needs to continuously obtain the location information when it runs in the background, you also need to declare the ACCESS_BACKGROUND_LOCATION permission in the AndroidManifest.xml file:

```
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="com.huawei.hms.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
```

Note: Because the ACCESS_FINE_LOCATION, WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE, and ACTIVITY_RECOGNITION permissions are dangerous system permissions, you need to dynamically apply for these permissions. If you do not have the permissions, Location Kit will reject to provide services for your app.

**Key Code**

I.	Map Display
Currently, the Map SDK supports two map containers: SupportMapFragment and MapView. This document uses the SupportMapFragment container.
1.	Add a Fragment object in the layout file (for example: activity_main.xml), and set map attributes in the file.

```
<fragment
    android:id="@+id/mapfragment_routeplanningdemo"
    android:name="com.huawei.hms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
```

2.	To use a map in your app, implement the OnMapReadyCallback API.

```
RoutePlanningActivity extends AppCompatActivity implements OnMapReadyCallback
```

3.	Load SupportMapView in the onCreate method, call getMapAsync to register the callback.

```
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.mapfragment_routeplanningdemo);
if (fragment instanceof SupportMapFragment) {
    SupportMapFragment mSupportMapFragment = (SupportMapFragment) fragment;
    mSupportMapFragment.getMapAsync(this);
}
```


4.	Call the onMapReady callback to obtain the HuaweiMap object.

```
@Override
public void onMapReady(HuaweiMap huaweiMap) {

    hMap = huaweiMap;
    hMap.setMyLocationEnabled(true);
    hMap.getUiSettings().setMyLocationButtonEnabled(true);
}
```


**II.	Function Implementation**

1.	Check the permissions.

```
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
    if (ActivityCompat.checkSelfPermission(context,
            "com.huawei.hms.permission.ACTIVITY_RECOGNITION") != PackageManager.PERMISSION_GRANTED) {
        String[] permissions = {"com.huawei.hms.permission.ACTIVITY_RECOGNITION"};
        ActivityCompat.requestPermissions((Activity) context, permissions, 1);
        Log.i(TAG, "requestActivityTransitionButtonHandler: apply permission");
    }
} else {
    if (ActivityCompat.checkSelfPermission(context,
            "android.permission.ACTIVITY_RECOGNITION") != PackageManager.PERMISSION_GRANTED) {
        String[] permissions = {"android.permission.ACTIVITY_RECOGNITION"};
        ActivityCompat.requestPermissions((Activity) context, permissions, 2);
        Log.i(TAG, "requestActivityTransitionButtonHandler: apply permission");
    }
}
```


2.	Check whether the location permissions have been granted. If no, the location cannot be obtained. 

```
settingsClient.checkLocationSettings(locationSettingsRequest)
        .addOnSuccessListener(locationSettingsResponse -> {
                       fusedLocationProviderClient
                    .requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.getMainLooper())
                    .addOnSuccessListener(aVoid -> {
                        //Processing when the API call is successful.
                    });
        })
        .addOnFailureListener(e -> {});
if (null == mLocationCallbacks) {
    mLocationCallbacks = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            if (locationResult != null) {
                List<HWLocation> locations = locationResult.getHWLocationList();
                if (!locations.isEmpty()) {
                    for (HWLocation location : locations) {
                        hMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 14));
                        latLngOrigin = new LatLng(location.getLatitude(), location.getLongitude());
                        if (null != mMarkerOrigin) {
                            mMarkerOrigin.remove();
                        }
                        MarkerOptions options = new MarkerOptions()
                                .position(latLngOrigin)
                                .title("Hello Huawei Map")
                                .snippet("This is a snippet!");
                        mMarkerOrigin = hMap.addMarker(options);
                        removeLocationUpdatesWith();
                    }
                }
            }
        }

        @Override
        public void onLocationAvailability(LocationAvailability locationAvailability) {
            if (locationAvailability != null) {
                boolean flag = locationAvailability.isLocationAvailable();
                Log.i(TAG, "onLocationAvailability isLocationAvailable:" + flag);
            }
        }
    };
}
```

**III.	Geofence and Ground Overlay Creation**

Create a geofence based on the current location and add a round ground overlay on the map. 

```
GeofenceRequest.Builder geofenceRequest = new 
GeofenceRequest.Builder geofenceRequest = new GeofenceRequest.Builder();
geofenceRequest.createGeofenceList(GeoFenceData.returnList());
geofenceRequest.setInitConversions(7); 
try {
    geofenceService.createGeofenceList(geofenceRequest.build(), pendingIntent)
            .addOnCompleteListener(new OnCompleteListener<Void>() {
                @Override
                public void onComplete(Task<Void> task) {
                    if (task.isSuccessful()) {
                        Log.i(TAG, "add geofence success!");
                        if (null == hMap) {
                            return; }
                        if (null != mCircle) {
                            mCircle.remove();
                            mCircle = null;
                        }
                        mCircle = hMap.addCircle(new CircleOptions()
                                .center(latLngOrigin)
                                .radius(500)
                                .strokeWidth(1)
                                .fillColor(Color.TRANSPARENT));
                    } else {Log.w(TAG, "add geofence failed : " + task.getException().getMessage());}
                }
            });
} catch (Exception e) {
    Log.i(TAG, "add geofence error:" + e.getMessage());
}

// Geofence service
<receiver
    android:name=".GeoFenceBroadcastReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name=".GeoFenceBroadcastReceiver.ACTION_PROCESS_LOCATION" />
    </intent-filter>
</receiver>

if (intent != null) {
    final String action = intent.getAction();
    if (ACTION_PROCESS_LOCATION.equals(action)) {
        GeofenceData geofenceData = GeofenceData.getDataFromIntent(intent);
        if (geofenceData != null && isListenGeofence) {
            int conversion = geofenceData.getConversion();
            MainActivity.setGeofenceData(conversion);
        }
    }
}
```

Mark the selected point on the map to obtain the destination information, check the current activity status, and plan routes based on the detected activity status.

```
hMap.setOnMapClickListener(latLng -> {
    latLngDestination = new LatLng(latLng.latitude, latLng.longitude);
    if (null != mMarkerDestination) {
        mMarkerDestination.remove();
    }
    MarkerOptions options = new MarkerOptions()
            .position(latLngDestination)
            .title("Hello Huawei Map");
    mMarkerDestination = hMap.addMarker(options);
    if (identification.getText().equals("To exit the fence,Your activity is about to be detected.")) {
        requestActivityUpdates(5000);
    }

});
// Activity identification API
activityIdentificationService.createActivityIdentificationUpdates(detectionIntervalMillis, pendingIntent)
        .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void aVoid) {
                Log.i(TAG, "createActivityIdentificationUpdates onSuccess");
            }
        })
        .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(Exception e) {
                Log.e(TAG, "createActivityIdentificationUpdates onFailure:" + e.getMessage());
            }
        });
// URL of the route planning API (cycling route is used as an example): https://mapapi.cloud.huawei.com/mapApi/v1/routeService/bicycling?key=API KEY
 NetworkRequestManager.getBicyclingRoutePlanningResult(latLngOrigin, latLngDestination,
        new NetworkRequestManager.OnNetworkListener() {
            @Override
            public void requestSuccess(String result) {
                generateRoute(result);
            }

            @Override
            public void requestFail(String errorMsg) {
                Message msg = Message.obtain();
                Bundle bundle = new Bundle();
                bundle.putString("errorMsg", errorMsg);
                msg.what = 1;
                msg.setData(bundle);
                mHandler.sendMessage(msg);
            }
        });
```

Note:

The route planning function provides a set of HTTPS-based APIs used to plan routes for walking, cycling, and driving and calculate route distances. The APIs return route data in JSON format and provide the route planning capabilities.

The route planning function can plan walking, cycling, and driving routes. 
You can try to plan a route from one point to another point and then draw the route on the map, achieving the navigation effects.

**Related Parameters**

1.	In indoor environments, the navigation satellite signals are usually weak. Therefore, HMS Core (APK) will use the network location mode, which is relatively slow compared with the GNSS location. It is recommended that the test be performed outdoors.
2.	In Android 9.0 or later, you are advised to test the geofence outdoors. In versions earlier than Android 9.0, you can test the geofence indoors. 
3.	Map Kit is unavailable in the Chinese mainland. Therefore, the Android SDK, JavaScript API, Static Map API, and Directions API are unavailable in the Chinese mainland. For details, please refer to Supported Countries/Regions.
4.	In the Map SDK for Android 5.0.0.300 and later versions, you must set the API key before initializing a map. Otherwise, no map data will be displayed.
5.	Currently, the driving route planning is unavailable in some countries and regions outside China. For details about the supported countries and regions, please refer to the Huawei official website.
6.	Before building the APK, configure the obfuscation configuration file to prevent the HMS Core SDK from being obfuscated.
	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.
	If you are using AndResGuard, add its trustlist to the obfuscation configuration file.

For details, please visit the [following link]: 

(https://developer.huawei.com/consumer/en/doc/development/HMSCore-Guides/android-sdk-config-obfuscation-scripts-0000001061882229 )


To learn more, visit the following links:
[Documentation on the HUAWEI Developers website]
(https://developer.huawei.com/consumer/en/hms/huawei-locationkit)
https://developer.huawei.com/consumer/en/hms/huawei-MapKit

[HUAWEI Developers official website](https://developer.huawei.com/consumer/en/hms?ha_source=hms1)

[Development Guide](https://developer.huawei.com/consumer/en/doc/development?ha_source=hms1) 

[Reddit](https://www.reddit.com/r/HMSCore/)to join developer discussions

[GitHub](https://github.com/HMS-Core) or Gitee to download the [demo](https://github.com/HMS-Core) and sample code

[Stack Overflow](https://stackoverflow.com/questions/tagged/huawei-mobile-services) to solve integration problems