Create and Monitor Geofences with HuaweiMap in Xamarin.Android Application

Tuğçe Arar
Huawei Developers
Published in
9 min readSep 14, 2020

A geofence is a virtual perimeter set on a real geographic area. Combining a user position with a geofence perimeter, it is possible to know if the user is inside the geofence or if he is exiting or entering the area.

In this article, we will discuss how to use the geofence to notify the user when the device enters/exits an area using the HMS Location Kit in a Xamarin.Android application. We will also add and customize HuaweiMap, which includes drawing circles, adding pointers, and using nearby searches in search places. We are going to learn how to use the below features together:

  • Geofence
  • Reverse Geocode
  • HuaweiMap
  • Nearby Search

Project Setup

First of all, you need to be a registered Huawei Mobile Developer and create an application in Huawei App Console in order to use HMS Map Location and Site Kits. You can follow these steps to complete the configuration required for development:

  1. Configuring App Information in AppGallery Connect
  2. Installing the Huawei Map NuGet package
  3. Install the Huawei Location Kit NuGet package
  4. Install the Huawei Site Kit NuGet package
  5. Integrating the HMS Core SDK

When we create our Xamarin.Android application in the above steps, we need to make sure that the package name is the same as we entered the Console. Also, don’t forget the enable them in Console.

Manifest & Permissions

We have to update the application’s manifest file by declaring permissions that we need as shown below.

Also, add a meta-data element to embed your app id in the application tag, it is required for this app to authenticate on the Huawei’s cloud server. You can find this id in agconnect-services.json file.

<meta-data android:name="com.huawei.hms.client.appid" android:value="appid=YOUR_APP_ID" />

Request location permission

Request runtime permissions in our app in order to use Location and Map Services. The following code checks whether the user has granted the required location permissions in Main Activity.

Add a Map

Within our UI, a map will be represented by either a MapFragment or MapView object. We will use the MapFragment object in this sample.

Add a <fragment> element to your activity’s layout file, activity_main.xml. This element defines a MapFragment to act as a container for the map and to provide access to the HuaweiMap object.

Also, let’s add other controls to use through this sample. That is two Button and a SeekBar. One button for clearing the map and the other for searching nearby locations. And seekbar is helping us to create a radius for the geofence.

In our activity’s OnCreate method, set the layout file as the content view, load AGConnectService, set button’s click events, and initialize FusedLocationProviderClient. Get a handle to the map fragment by calling FragmentManager.FindFragmentById. Then use GetMapAsync to register for the map callback.

Also, implement the IOnMapReadyCallback interface to MainActivity and override OnMapReady method which is triggered when the map is ready to use.

As you can see above, with the UiSettings property of the HuaweiMap object we set my location button, enable compass, etc. Other properties like below:

Now when the app launch, directly get the current location and move the camera to it. In order to do that we use FusedLocationProviderClient that we instantiated and call LastLocation API.

LastLocation API returns a Task object that we can check the result by implementing the relevant listeners for success and failure.In success listener we are going to move the map’s camera position to the last known position.

To change the position of the camera, we must specify where we want to move the camera, using a CameraUpdate. The Map Kit allows us to create many different types of CameraUpdate using CameraUpdateFactory.

There are some methods for the camera position changes as we see above. Simply these are:

1. NewLatLng: Change camera’s latitude and longitude, while keeping other properties

2. NewLatLngZoom: Changes the camera’s latitude, longitude, and zoom, while keeping other properties

3. NewCameraPosition: Full flexibility in changing the camera position

We are going to use NewCameraPosition. A CameraPosition can be obtained with a CameraPosition.Builder. And then we can set target, bearing, tilt and zoom properties.

Creating Geofence

Now that we’ve created the map, we can now start to create geofences using it. In this article, we will choose the location where we want to set geofence in two different ways. The first is to select the location by clicking on the map, and the second is to search for nearby places by keyword and select one after placing them on the map with the marker.

Set the geofence location by clicking on the map

It is always easier to select a location by seeing it. After this section, we are able to set a geofence around the clicked point when the map’s clicked. We attached the Click event to our map in the OnMapReady method. In this Click event, we will add a marker to the clicked point and draw a circle around it.

After clicking the map, we will add a circle, a marker, and a custom info window to that point like this:

Also, we will use the Seekbar at the bottom of the page to adjust the circle radius.

We set selectedCoordinates variable when adding the marker. Let’s create the following method to create the marker:

With MarkerOptions we can set the title and position properties. And for creating a custom info window, there is SetInfoWindowAdapter method. Adding MapInfoWindowAdapter class to our project for rendering the custom info model. And implement HuaweiMap.IInfoWindowAdapter interface to it.

This interface provides a custom information window view of a marker and contains two methods:

View GetInfoContents(Marker marker);View GetInfoWindow(Marker marker);

When an information window needs to be displayed for a marker, methods provided by this adapter are called in any case.

Now let’s create a custom info window layout and named it as map_info_view.xml

And return it after customizing it in GetInfoWindow() method. The full code of the adapter is below:

Now we create a method to arrange a circle around the marker that representing the geofence radius. Create a new DrawCircleOnMap method in MainActivity for this. To construct a circle, we must specify the Center and Radius. Also, I set other properties like StrokeColor etc.

We will use SeekBar to change the radius of the circle. As the value changes, the drawn circle will expand or shrink. For this reason, we will update the radius and re-draw the circle in SeekBar’s change event.

Reverse Geocoding

Now let’s handle the click event of the info window. We have the coordinates of the selected location and we want to bring up the alert dialog with the formatted address of this coordinates and radio group of Geofence conversions like below.

But before open that window, we need to reverse geocoding selected coordinates to getting a formatted address.

HUAWEI Site Kit provides us a set of HTTP API including the one that we need, reverseGeocode.

In the sample project, for convenience, I created the functions from different services in different classes. In GeocodeManager managing geocoding functions and in GeofenceManager managing geofence functions. So let’s add the GeocodeManager class to our project and update it as follows:

In the above code, we request the address corresponding to a given latitude/longitude. Also specified that the output must be in JSON format.

https://siteapi.cloud.huawei.com/mapApi/v1/siteService/reverseGeocode?key=API KEY

You can get API key in our agconnect-services.json file or Console.

Request model:

The response return from ReverseGeocode API looks like this:

Note that the JSON response contains three root elements:

  • “returnCode”: For details, please refer to Result Codes.
  • “returnDesc”: description
  • “sites” contains an array of geocoded address information

Generally, only one entry in the “sites” array is returned for address lookups, though the geocoder may return several results when address queries are ambiguous.

Add the following codes to our MapInfoWindowAdapter where we get results from the Reverse Geocode API and set the UI elements.

Now, after selecting the conversion, we can complete the process by calling the AddGeofence method in the GeofenceManager class by pressing the save button in the dialog window.

In the AddGeofence method, we need to set the geofence request parameters, like the selected conversion, unique Id and timeout according to conversion, etc. with GeofenceBuilder.

Geofence conversion can be set one of these:

To add geofences to a point we must create GeofenceService from LocationService and use CreateGeofenceList method with PendingIntent. When we created this intent we use a broadcast receiver because we need to notify whenever geofence conversions occur. So we create GeofenceBroadcastReceiver and display a toast message when a geofence action occurs.

After that in CreateGeoSuccessListener and CreateGeoFailureListener that we implement IOnSuccessListener and IOnFailureListener respectively, we display a toast message to the user like this:

Set geofence location using Nearby Search

In this section, we will implement the Huawei Site Kit’s Nearby Search API. And after using it to search for a location, we will display the results on the map with markers. The user can select one of these locations to add a geofence around them.

On the main layout when the user clicks the Search Nearby Places button, a search dialog like below appears:

Create search_alert_layout.xml with a search input :

In Main Activity, create click event of that button and open an alert dialog after it’s view is set to search_alert_layout. And make NearbySearch when clicking the Search button:

We pass search text and Current Location into the GeocodeManager NearbySearch method as parameters. We need to modify GeoCodeManager class and add nearby search method to it.

Let’s review this code. First of all, we create an ISearchService interface based on context and API Key with SearchServiceFactory class. This is the entry interface of the HUAWEI Site Kit. With the help of this interface, we are going to be able to use search services. In this case that would be NearbySearch. Before searching, we need to create an customize a NearbySearchRequest.

And to handle the result we must create a listener and implement the ISearchResultListener interface to it.

In OnSearchResult method, NearbySearchResponse object return. We will insert markers to the mapper element in this response. The map will look like this:

In Main Activity create a method named SetSearchResultOnMap and pass IList<Site> as a parameter to insert multiple markers on the map.

Now, we add markers as we did above. But here we use SetMarkersClustering(true) to consolidates markers into clusters when zooming out of the map.

You can download the source code from here. Also if you have any questions, ask away in Huawei Developer Forums.

Errors

  • If your location permission set “Allowed only while in use instead” of ”Allowed all the time” below exception will be thrown.

int GEOFENCE_INSUFFICIENT_PERMISSION

Insufficient permission to perform geofence-related operations.

  • You can see all result codes including errors, in here for Location service.
  • You can find result codes with details here for Geofence request.

References

· HMS LocationKit Documentation

· HMS Xamarin LocationKit Plugin References

· HMS MapKit Documentation

· HMS SiteKit Documentation

--

--