geofencing_flutter_plugin

This Flutter plugin extends the functionality offered by the Woosmap Geofencing Mobile SDKs. Find more about the Woosmap Geofencing SDK.

Android iOS
Support SDK 33+ 13.0+

Supported Platforms


  • iOS
  • Android

Modules


  • GeofencingFlutterPlugin: Contains methods to monitor location, regions and POIs.

Objects


  • Location: Represents the location object.
  • POI: Represents Point of Interest.
  • Region: Represents a geographical region/geofence.
  • GeofenceRegion: Used while adding a new region in the local database.

Types


  • ProfileSource: Represents tracking profile source. It can either be ProfileSource.local and ProfileSource.external
  • RegionType: Represents the type of the region. Possible values are RegionType.circle and RegionType.isochrone

Usage

import 'package:geofencing_flutter_plugin/geofencing_flutter_plugin.dart';

final geofencingFlutterPlugin = GeofencingFlutterPlugin();
// ...

Check and request permissions


Before initializing the SDK it is required that you request for required location permissions.

To check if the location permissions are granted by the user call getPermissionsStatus method.

Future<String?> returnVal = geofencingFlutterPlugin.getPermissionsStatus();

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

Parameter status will be a string, one of:

  • GRANTED_BACKGROUND : User has granted location access even when app is not running in the foreground.
  • GRANTED_FOREGROUND : Location access is granted only while user is using the app.
  • DENIED: Location access is denied.
  • UNKNOWN: Without providing or denying any permission then it will return unknown.

Please note: Plugin will not work as expected if location access is denied.

Requesting location access

To request location access call requestPermissions method of the plugin. This will result in displaying location access permission dialog. This method accepts a boolean parameter background. If this parameter is set to true, then plugin will ask for background location access. Code snippet below asks for background location access.

Future<String?> returnVal = geofencingFlutterPlugin.requestPermissions(background);

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

Check Bluetooth permissions

In order to get beacon-fencing running on Android devices you need to make sure that all the Bluetooth related permissions are granted to the plugin.

To check if the Bluetooth permissions are granted by the user call getBLEPermissionsStatus method.

Future<String?> returnVal = geofencingFlutterPlugin.getBLEPermissionsStatus();

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

Parameter status will be a string, one of:

  • GRANTED : User has granted bluetooth access.
  • DENIED: Bluetooth access is denied.
  • BACKGROUND_LOCATION_DENIED: Background location access is denied. You first need to request background location permission.

Requesting Bluetooth permissions

To request Bluetooth access call requestBLEPermissions method of the plugin. This will result in displaying Bluetooth access permission dialog.

Future<String?> returnVal = geofencingFlutterPlugin.requestBLEPermissions();

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

Note: For beacon-fencing to work you will also need to request background location access. To request background location access please invoke requestPermissions method of the plugin with background parameter enabled.

Initializing the plugin


Plugin can be initialized by simply calling initialize method.

Map<String, String> woosmapSettings = {
    "privateKeyWoosmapAPI": "<<WOOSMAP_KEY>>",
    "trackingProfile": "liveTracking"
};

Future<String?> returnVal = geofencingFlutterPlugin.initialize(woosmapSettings);

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: $error');
});

Both configuration options privateKeyWoosmapAPI and trackingProfile are optional. You can also initialize the plugin by passing null configuration.

Future<String?> returnVal = geofencingFlutterPlugin.initialize();

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: $error');
});

You can also set the Woosmap API key later by calling setWoosmapApiKey method.

Future<String?> returnVal = geofencingFlutterPlugin.setWoosmapApiKey("<<WOOSMAP_KEY>>");

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

Tracking


Once you have initialized the plugin and the user has authorized location permissions, you can start tracking the user’s location.

To start tracking, call:

Future<String?> returnVal = geofencingFlutterPlugin.startTracking('liveTracking');

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

To stop tracking, call:

Future<String?> returnVal = geofencingFlutterPlugin.stopTracking();

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

Method startTracking accepts only following tracking profiles

  • liveTracking
  • passiveTracking
  • visitsTracking
  • beaconTracking

Tracking profile properties


Property liveTracking passiveTracking visitsTracking
trackingEnable true true true
foregroundLocationServiceEnable true false false
modeHighFrequencyLocation true false false
visitEnable false false true
classificationEnable false false true
minDurationVisitDisplay null null 300
radiusDetectionClassifiedZOI null null 50
distanceDetectionThresholdVisits null null 25
currentLocationTimeFilter 0 0 0
currentLocationDistanceFilter 0 0 0
accuracyFilter 100 100 100
searchAPIEnable false true false
searchAPICreationRegionEnable false true false
searchAPITimeFilter 0 0 0
searchAPIDistanceFilter 0 0 0
distanceAPIEnable false false false
modeDistance null null null
outOfTimeDelay 300 300 300
DOUBLEOfDayDataDuration 30 30 30

Listening to events


Location

To listen to location, call watchLocation method. After successful invokation of the method you'll need to call getWatchLocationStream method which will return a stream of Location object. Once you obtain the stream call the listen method of the stream.

Future<String?> returnVal = geofencingFlutterPlugin.watchLocation();

returnVal.then((value){
    //Get the location stream    
    watchLocationStream = geofencingFlutterPlugin.getWatchLocationStream();
    //Listen to the stream
    watchLocationStream.listen((location){
        //Location updates will be recieved here.
        if (location != null) {
            debugPrint(location.locationDescription);
        } else {
            debugPrint("Location is null");
        }
    });
}).catchError((error) {
    debugPrint('An error occurred: $error');
});

To stop getting location updates:

Future<String?> returnVal = geofencingFlutterPlugin.clearLocationWatch();

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: $error');
});

Define the radius value

When you create a Geofence around a POI (previously imported from Woosmap), manually define the radius value:

Future<String?> returnVal = _geofencingFlutterPlugin.setPoiRadius("100");

returnVal.then((value){
    showToast(value!);
}).catchError((error) {
    showToast('An error occurred: ${error.message}');
});

or choose the user_properties subfield that corresponds to radius value of the Geofence:

Future<String?> returnVal = _geofencingFlutterPlugin.setPoiRadius("radiusPOI");

returnVal.then((value){
    showToast(value!);
}).catchError((error) {
    showToast('An error occurred: ${error.message}');
});

Regions

Call watchRegions method to track Regions. Method will invoke a callback with Region object. Method will return a watch id which can be used later to remove the callback.

Future<String?> returnVal = geofencingFlutterPlugin.watchRegion();

returnVal.then((value){
    //Get the region stream    
    watchRegionStream = geofencingFlutterPlugin.getWatchRegionStream();
    //Listen to the stream
    watchRegionStream.listen((region){
        //Region updates will be recieved here.
        if (location != null) {
            debugPrint(region.eventName);
        } else {
            debugPrint("Region is null");
        }
    });
}).catchError((error) {
    debugPrint('An error occurred: $error');
});

To remove watch:

Future<String?> returnVal = geofencingFlutterPlugin.clearRegionWatch();

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: $error');
});

Initialize Salesforce MarketingCloud Connector


The SDK needs some input like credentials and object key to perform the API call to Salesforce Marketing Cloud API.

Input to initialize the SFMC connector

Parameters Description Required
authenticationBaseURI Authentication Base URI Required
restBaseURI REST Base URI Required
client_id client_id (journey_read and list_and_subscribers_read rights are required) Required
client_secret client_secret (journey_read and list_and_subscribers_read rights are required) Required
contactKey The ID that uniquely identifies a subscriber/contact Required
regionEnteredEventDefinitionKey Set the EventDefinitionKey that you want to use for the Woosmap event woos_geofence_entered_event
regionExitedEventDefinitionKey Set the EventDefinitionKey that you want to use for the Woosmap event woos_geofence_exited_event
poiEventDefinitionKey Set the EventDefinitionKey that you want to use for the Woosmap event woos_POI_event
zoiClassifiedEnteredEventDefinitionKey Set the EventDefinitionKey that you want to use for the Woosmap event woos_zoi_classified_entered_event
zoiClassifiedExitedEventDefinitionKey Set the EventDefinitionKey that you want to use for the Woosmap event woos_zoi_classified_exited_event
visitEventDefinitionKey Set the EventDefinitionKey that you want to use for the Woosmap event woos_Visit_event

Initialize the connector implementation


Map<String, String> arguments = {
      'authenticationBaseURI': config.authenticationBaseURI,
      'restBaseURI':config.restBaseURI,
      'client_id': config.clientId,
      'client_secret': config.clientSecret,
      'contactKey': config.contactKey,
      'regionEnteredEventDefinitionKey': config.regionEnteredEventDefinitionKey,
      'regionExitedEventDefinitionKey':config.regionExitedEventDefinitionKey,
    };

Future<String?> returnVal = geofencingFlutterPlugin.setSFMCCredentials(arguments);

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

Adding and removing regions


Call addRegion method to add a region that you want to monitor. Region type can be circle or isochrone only. Method will accept an object with the following attributes:

  • regionId - Id of the region
  • lat - Latitude
  • lng - Longitude
  • radius - Radius in meters
  • type - type of region
Create a custom circle region
GeofenceRegion geofenceRegion = GeofenceRegio(
                                '7F91369E-467C-4CBD-8D41-6509815C4780', 
                                51.50998, 
                                -0.1337, 
                                180, 
                                RegionType.circle
                            );

Future<String?> returnVal = geofencingFlutterPlugin.addRegion(geofenceRegion);

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

Create a custom isochrone region
GeofenceRegion geofenceRegion = GeofenceRegio(
                                '7F91369E-467C-4CBD-8D41-6509815C4780', 
                                51.50998, 
                                -0.1337, 
                                180, 
                                RegionType.isochrone
                            );

Future<String?> returnVal = geofencingFlutterPlugin.addRegion(geofenceRegion);

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

Call removeRegions method to remove a region that you are monitoring. Method will accept the following parameter, and passing a null value will remove all the regions.

Future<String?> returnVal = geofencingFlutterPlugin.removeRegions('7F91369E-467C-4CBD-8D41-6509815C4780');

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

Or To Delete all Regions

Future<String?> returnVal = geofencingFlutterPlugin.removeRegions();

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

Local database operations


  • Get POIs: Call getPois method to get an array of POIs from the local db

// Get single POI
Future<List<Poi>?> returnVal = geofencingFlutterPlugin.getPois(poiId);

returnVal.then((pois){
    if (pois != null){
        debugPrint('POIs: ${pois.length}');
    }
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

// Get all POIs
Future<List<Poi>?> returnVal = geofencingFlutterPlugin.getPois();

returnVal.then((pois){
    if (pois != null){
        debugPrint('POIs: ${pois.length}');
    }
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});
  • Delete POIs: Call removePois method to clear all POIs from the local db.
Future<String?> returnVal = geofencingFlutterPlugin.removePois();

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});
  • Refresh POIs: Call refreshPois method to fetch updated POI information from Woosmap API.
Future<String?> returnVal = geofencingFlutterPlugin.refreshPois();

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});
  • Get Locations: Call getLocations method to get an array of Locations from the local db.
//Get single location
Future<List<Location>?> returnVal = geofencingFlutterPlugin.getLocations(locationId);

returnVal.then((locations){
    if (locations != null){
        debugPrint('Locations: ${locations.length}');
    }
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

//Get all locations
Future<List<Location>?> returnVal = geofencingFlutterPlugin.getLocations();

returnVal.then((locations){
    if (locations != null){
        debugPrint('Locations: ${locations.length}');
    }
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});
  • Delete Locations: Call removeLocations method to clear all Locations info from the local db.
Future<String?> returnVal = geofencingFlutterPlugin.removeLocations();

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});
  • Get Regions: Call getRegions method to get an array of Regions from the local db. specify region id to retrieve specific region info
//Get single region
Future<List<Region>?> returnVal = geofencingFlutterPlugin.getRegions(regionId);

returnVal.then((regions){
    if (regions != null){
        debugPrint('Regions: ${regions.length}');
    }else{
        debugPrint('Regions is null');
    }
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

//Get all regions
Future<List<Region>?> returnVal = geofencingFlutterPlugin.getRegions();

returnVal.then((regions){
    if (regions != null){
        debugPrint('Regions: ${regions.length}');
    }else{
        debugPrint('Regions is null');
    }
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});
  • Get Indoor Beacons: Call getIndoorBeacons method to get a list of IndoorBeacon from the local db. You can pass a venueId to get the beacons for a specific venue or you can pass ref parameter which will get a beacon with specific identifier or you can pass both.
    Future<List<IndoorBeacon>?> returnVal;

    returnVal = geofencingFlutterPlugin.getIndoorBeacons(); //Get all indoor beacons

    returnVal = geofencingFlutterPlugin.getIndoorBeacons(venueID: "YOUR-VENUE-ID"); //Get beacons for a venue

    returnVal = geofencingFlutterPlugin.getIndoorBeacons(ref: "BEACON-IDENTIFIER"); //Get beacon with an identifier

    returnVal = geofencingFlutterPlugin.getIndoorBeacons(venueID: "YOUR-VENUE-ID", ref: "BEACON-IDENTIFIER"); //Filter by both

    returnVal.then((beacons) {
        if (beacons != null) {
            debugPrint('Indoor beacons: ${beacons.length}');
        }
    }).catchError((error) {
        showToast('An error occurred: ${error.message}');
    });

  • Delete Indoor Beacons: Call removeIndoorBeacons method to delete all indoor beacons from the local DB.
    Future<String?> returnVal = geofencingFlutterPlugin.removeIndoorBeacons();

    returnVal.then((value) {
        debugPrint(value!);
    }).catchError((error) {
        debugPrint('An error occurred: ${error.message}');
    });

Custom tracking profile


If preset tracking profiles don’t fit with your use cases, you can build your own profile and uses the startCustomTracking() method. There are two way to host the json file:

  • Include json file in the client application (local) for ios.
  • For local mode put json file in assets folder in android.
  • Host externally in a file folder in your information system (external)
Future<String?> returnVal = geofencingFlutterPlugin.startCustomTracking(ProfileSource.local, 'localProfile.json');

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

or

Future<String?> returnVal = geofencingFlutterPlugin.startCustomTracking(ProfileSource.external, 'https://raw.githubusercontent.com/lpernelle-wgs/files/master/customProfileLeo.json');

returnVal.then((value){
    debugPrint(value!);
}).catchError((error) {
    debugPrint('An error occurred: ${error.message}');
});

Build a custom tracking profile

Define tracking properties in a Json file that respect the Json Schema in the Tracking properties page.

License

BSD-3