Work with Geotriggers

Geotriggers let you monitor your GIS data in real-time and receive notifications when specified conditions are met. The most common type of notification is when a device (such as a cellphone) enters or leaves an area (sometimes called Geofencing). With geotriggers, you can monitor locations from whatever LocationDataSource you choose, while tapping into the full power of ArcGIS Runtime's GeometryEngine for evaluating spatial relationships.

With geotriggers your apps can do things like:

  • Warn users when they enter a restricted or dangerous area.
  • Provide notifications about nearby points of interest or attractions.
  • Inform drivers when they enter or leave an area that has noise or speed restrictions.
  • Notify a customer when their delivery is about to arrive.

A geotrigger that routes to an associated charging station.

Using geotriggers in your app involves the following main steps.

  1. Define a geotrigger condition to monitor.
  2. Set up a geotrigger monitor and listen for events.
  3. React to notification events.

Define a Geotrigger condition to monitor

A Geotrigger defines a condition that you want to monitor as the device location changes. For monitoring conditions based on a spatial relationship, ArcGIS Runtime provides the FenceGeotrigger class.

For example, you could use a fence geotrigger to represent a condition such as "Inform me when my device location comes within 50 meters of one of my target areas".

The table below shows the meaningful parts of this condition and how they are represented in the Geotrigger API.

PartExampleAPI
Dynamic position"my device location"GeotriggerFeed
Spatial operation"comes within"FenceRuleType
Areas (fences) to check"my target areas"FenceParameters

Geotrigger feed

To monitor your device location, pass a LocationDataSource to a LocationGeotriggerFeed. The LocationDataSource is also what you use with the LocationDisplay to show your position on a map.

You can use the following types of LocationDataSource depending on your use case.

The following example creates a simulated location data source that follows a provided route polyline. You can also configure a simulated location data source with a velocity (in meters per second) and the time of day (useful when considering traffic conditions, for example).

The location data source is used to configure a geotrigger feed as well as the map view's location display.

Use dark colors for code blocksCopy
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
// Create a new simulated location data source.
_simulatedDeviceLocation = new SimulatedLocationDataSource();
SimulationParameters simParams = new SimulationParameters
{
    StartTime = System.DateTime.Now,
    Velocity = 100.0 // Meters/Second
};
// The simulated location will move across the provided polyline.
_simulatedDeviceLocation.SetLocationsWithPolyline(routeLine, simParams);
// ...

// Create a new Geotrigger feed with the simulated location source.
var locationFeed = new LocationGeotriggerFeed(_simulatedDeviceLocation);
// ...

// Enable location display on the map view using the same simulated location source.
MainMapView.LocationDisplay.DataSource = _simulatedDeviceLocation;
MainMapView.LocationDisplay.IsEnabled = true;

Fence parameters

You supply a FenceParameters to monitor target areas, including an optional buffer distance. Depending on your workflow, you can make your fences visible or hidden in the map. Your user may not need to know exactly where the fences are, only when one has been entered or exited.

Your fences are based on either:

  • Graphics, which are light-weight, in-memory, and quick to create without needing a defined table schema. For example, graphics could represent a target area that the user sketches on the view. Graphic fences are dynamic, with new ones added, old ones removed, or geometry updates processed on-the-fly. For example, if your fences are polygons representing moving storm clouds, changes to these graphics will be evaluated in real-time. Use graphics when your condition uses temporary data created on the device. To represent fences using graphics, create a GraphicFenceParameters or a GraphicsOverlayFenceParameters.

  • Features from a FeatureTable that can be filtered by attributes and/or geometry. Features allow you to monitor online and offline data that can be shared across the Esri ecosystem. Use features when your condition makes use of authoritative data that you share with your map or scene. You create a FeatureFenceParameters to work with features.

The following example creates a fence geotrigger using the simulated location feed set up previously. The fence features come from a feature table of service areas defined by drive time with a buffer of 50 meters applied. Specifying a rule type of "enter" means notifications will be triggered when the fences are entered, but not when exited.

Use dark colors for code blocksCopy
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
// Create parameters that define the geofence features and a buffer distance (meters).
var fenceParameters = new FeatureFenceParameters(_driveTimeServiceAreas.FeatureTable, 50);

// Create a geotrigger with the location feed, "enter" rule type, and the fence parameters.
var fenceGeotrigger = new FenceGeotrigger(locationFeed, FenceRuleType.Enter, fenceParameters);

Set up a Geotrigger monitor and listen for events

Once you have defined your geotrigger, you are ready to start monitoring it. The geotrigger itself just defines what you want to be notified about. To actually check for when things happen (conditions are met), you pass it to a geotrigger monitor.

The GeotriggerMonitor is the heart of the geotriggers workflow: it takes a single Geotrigger and monitors the condition it defines using real-time changes to the location feed. When a condition is met, it raises an event and provides the info your app needs in order to react appropriately.

Once you have created your GeotriggerMonitor, you need to:

  • Subscribe to notification events so that you will be informed when the condition is met.
  • Watch for warnings that indicate something isn't working correctly.
  • Start the geotrigger monitor to begin monitoring and wait for notifications to start coming in.

The following example creates a geotrigger monitor to monitor the fence geotrigger. Event handlers are added for handling notifications from the monitor (when one of the fence areas is entered) and for when warnings are received. Finally, the monitor is started.

Use dark colors for code blocksCopy
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
// Create a GeotriggerMonitor to monitor the FenceGeotrigger created previously.
_geotriggerMonitor = new GeotriggerMonitor(fenceGeotrigger);

// Handle notification events (when a fence is entered).
_geotriggerMonitor.Notification += NotifyChargingServiceAreaEntered;

// Handle monitor warnings (such as temporarily losing the device location).
_geotriggerMonitor.WarningChanged += GeotriggerMonitorWarningChanged;

// Start monitoring.
await _geotriggerMonitor.StartAsync();

React to notification events

Whenever your geotrigger monitor is in a started state, you should be ready to handle notifications that provide details for the condition that was met. The GeotriggerNotificationInfo class provides information such as:

  • The location where the condition was met. You can zoom to this position by updating the viewpoint for your map view or scene view.
  • The geoelement for the fence, which includes all of its underlying attributes and attachments.
  • The GeotriggerMonitor that sent the notification. You could use this to stop monitoring once a condition has been met.

When you receive a GeotriggerNotificationInfo you could display a message to the user to tell them what happened. You could take other action, such as selecting a feature on the map or routing to a location. Alternatively, you may not need to interact with the user at all, perhaps writing to a logfile or taking some internal action in your app.

The following example handles geotrigger monitor notifications. The event argument (e) is used to get the fence feature. The fence attributes are used to determine if this is a suitable feature (charging station). If not, the geotrigger monitor will continue to run. If it is, a graphic will be added to the map view to show the station location and monitoring will stop.

Use dark colors for code blocksCopy
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
private void NotifyServiceAreaEntered(object sender, GeotriggerNotificationInfo e)
{

    // Get the Geofence element that was entered (charging station service area).
    GeoElement fence = (e as FenceGeotriggerNotificationInfo).FenceGeoElement;

    // Get info for this charging station: accessibility, longitude/latitude.
    string access = fence.Attributes["Access_Day"].ToString().ToLower();
    double stationLongitude = double.Parse(fence.Attributes["Longitude"].ToString());
    double stationLatitude = double.Parse(fence.Attributes["Latitude"].ToString());

    // If the station requires you to call ahead or is for hotel guests only, return.
    if (access.Contains("call ahead") || access.Contains("guest use only")) { return; }

    // Show the station for this service area on the map view.
    var stationPoint = new MapPoint(stationLongitude, stationLatitude, SpatialReferences.Wgs84);
    var stationGraphic = new Graphic(stationPoint, _stationStopSymbol);

    // Use DispatcherQueue to run on the UI thread when adding graphics.
    DispatcherQueue.TryEnqueue(() => MainMapView.GraphicsOverlays[0].Graphics.Add(stationGraphic));

    // Stop monitoring.
    e.GeotriggerMonitor.Stop();

}

Customizing Notifications

Optionally, you can provide an expression that defines the message for your Geotrigger, using the Arcade language. This controls the message provided with GeotriggerNotificationInfo that is populated whenever the geotrigger condition is met. The expression uses the Geotrigger Notification Profile, which gives you access to:

  • The $feedfeature (the device location, for example) and its geometry and attributes.
  • Whether the area was "entered" or "exited".
  • The $fencefeature (the target area) and its geometry and attributes.

You can also make use of other functions and objects available in Arcade, such as the Geometry() or Now() functions. For example, the following geotrigger message expression:

"Hello, you have entered " + $fencefeature.name + " with a heading of " + $feedfeature.heading + " degrees at " + Now()

Might result in a GeotriggerNotificationInfo.message of:

Hello, you have entered Area 1 with a heading of 45 degrees at 01 Jan 2021 12:00:00 pm.

Working with Geotriggers when your app is in the background

Many geotrigger workflows monitor and provide notifications while the user is interacting with and viewing the app. Sometimes, however, your app needs to provide notifications for a geotrigger condition while the user is engaged in other tasks, even when the app is not active. When working on mobile devices, it is particularly important to consider how geotriggers will behave when you navigate away from the app. In these scenarios, your app must contain logic that ensures its geotriggers are monitored when running in the background.

Xamarin.Android

On Android devices, one approach is to move the geotriggers business logic to a long running foreground service that you interact with via a persistent notification.

You can continue to show UI such as the map view in your main activity but must ensure that the data required for geotriggers, such as the LocationDataSource and data used for fences, is managed by the foreground service. Your main activity starts the foreground service and then binds to it for sharing data and so on. To receive location updates from the device, you also need to request the ACCESS_BACKGROUND_LOCATION permission.

Once your foreground service is started it will be shown in the device's notification bar irrespective of the state of your app. When a geotrigger condition is met, information can be displayed without relying on the main activity's UI (using a Toast or Snackbar, for example). You can add UI controls to the notification that allow the user to stop geotrigger monitoring.

See Foreground services in the Microsoft documentation for more information about implementing foreground services in your Xamarin.Android app.

Xamarin.iOS

Background processing is strictly controlled on iOS devices. See Introduction to Backgrounding in iOS in the Microsoft documentation for an overview and guidelines for implementing backgrounding in your Xamarin.iOS app.

UWP

See Support your app with background tasks in the Microsoft documentation for more information about implementing background tasks in your UWP app.

GPS accuracy considerations for feed updates

Inaccuracies in GPS data can affect the accuracy of geotrigger monitoring. To ensure that geotriggers more accurately report entering and exiting a fence, you can filter the feed updates to only monitor the most suitable locations by using an on LocationGeotriggerFeed.Filter. For example, the expression return $locationupdate.horizontalaccuracy <= 10.0 only accepts those location updates with a horizontal accuracy less than or equal to 10 meters.

You can factor GPS accuracy into your geotriggers using FenceGeotriggerFeedAccuracyMode.UseGeometryWithAccuracy to buffer locations by their horizontal accuracy. This creates a polygon representing the area of uncertainty around the reported location, and this polygon is used to check if a geotrigger condition is met.

Fence enter and exit spatial relationships

The purpose of your application determines when you want to be notified of the geotriggers. For example, you may choose to receive notifications when you are near a fence or only when you are completely inside it. You can use FenceEnterExitSpatialRelationship to define enter and exit rules for the location with respect to the fence.

Some possible use cases for each FenceEnterExitSpatialRelationship value are described below. Each available value is followed by a diagram that illustrates a corresponding enter and exit scenario. In each diagram, the feed enters the fence from the left (shown in yellow) and exits to the right (shown in purple).

FenceEnterExitSpatialRelationship.EnterIntersectsAndExitDoesNotIntersect: You want to be notified when the location is near a fence, so you choose to receive enter notifications whenever the feed polygon intersects the fence. Exit notifications require that the location is completely outside the fence. For example, an industry worker needs to be notified whenever they are potentially approaching an area with hazardous gases and are also notified when they are clear of the danger.

A geotrigger with spatial relationship enterIntersectsAndExitDoesNotIntersect

FenceEnterExitSpatialRelationship.EnterContainsAndExitDoesNotContain: You want to be notified only when you are completely inside a fence, so you choose to receive enter notifications when the feed polygon is contained within the fence. Exit notifications require that the location is not contained. For example, a field crew sent to cut down trees needs to avoid accidentally cutting down trees in neighboring plots. They only want on-site staff to be notified when there is high confidence.

A geotrigger with spatial relationship enterContainsAndExitDoesNotContain

FenceEnterExitSpatialRelationship.EnterContainsAndExitDoesNotIntersect: You want to be notified only when you are completely inside or outside a fence. For example, a delivery driver driving along a highway past many addresses does not want to be notified of addresses they pass by, but only when they arrive at or leave their destination.

A geotrigger with spatial relationship enterContainsAndExitDoesNotIntersect

Performance considerations

Geotriggers may monitor conditions for long periods of time (maybe the entire time that your app is running). To minimize memory usage and to maximize your device's battery life, consider some factors that can affect the performance of your geotrigger code.

Device specifications determine the limits of what you can successfully monitor. For example, mobile devices with reduced memory capacity can handle fewer fences than a powerful desktop computer. For typical workflows, you can expect mobile devices to effectively monitor tens of thousands of fences and perform well. By comparison, the same geotrigger code running on a desktop machine could handle hundreds of thousands of fences. As a guideline, you should try to monitor the minimum amount of fence data required for your application. Geotriggers use your device's GPS and may continue to run in the background. To reduce your device's battery consumption, turn GPS off when it is not required. Geotriggers are not monitored unless there are location or graphics updates.

You can use multiple geotriggers to monitor features from different feature tables within one application. When using online feature data, there is the possibility of losing network connectivity, which can affect your app's availability. If you need to guarantee consistent performance without relying on network availability, consider taking the fence data offline.

If your app uses Runtime versions prior to 100.13, when using online features as fences, the total number of fences you can monitor is limited by the service's maximum feature count (usually 1,000 - 2,000 features). To create fences beyond that limit, you can split the features between several geotriggers.

Fence creation considerations

Geotrigger notifications can be affected by several factors including signal strength, accuracy of GPS data, and the frequency of position updates. To ensure accurate notifications, consider the intended speed of travel as well as your device's accuracy when creating fences.

The speed of travel for an app designed for car users is higher than the one designed for pedestrians. For example, if you are traveling at 60 mph (around 100 kph) with location updates every second, the real world distance between two adjacent locations is approximately 30 meters. If the fence was just 10 meters wide, it might fall into the "gap" between positions, and the notification may be missed. Since the distance between position updates is greater when travelling at higher speeds, consider making your fences large enough.

As a general rule, favor larger fences. This helps avoid problems such as

  • Receiving erroneous exit notifications when you're inside a small fence due to GPS drift.
  • Missing an enter notification when you're traveling at high speeds and your locations fall on either side of a small fence.

Also, consider updating your app's location data source to send position updates more frequently, if your performance considerations permit. This allows your app to get more accurate notifications.

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.