Areas alarms¶
Another powerful use case is triggering operations the moment a user enters or exits a defined geographic area.
The UNL Navigation SDK for Android includes a built-in UnlAlarmService class, making it effortless to configure and manage all your geofence events.
Add areas to be monitored¶
Define your geographic areas-RectangleGeographicArea, CircleGeographicArea, and UnlPolygonGeographicArea-then invoke the monitorArea method on your UnlAlarmService instance:
- Kotlin
- Java
// Kotlin
// Create a rectangular area using minLat, maxLat, minLon, maxLon
val rect = RectangleGeographicArea(
minLat = 0.5, // minimum latitude
maxLat = 1.0, // maximum latitude
minLon = 0.5, // minimum longitude
maxLon = 1.0 // maximum longitude
)
// Create a circular area with center coordinates and radius in meters
val circle = CircleGeographicArea(
center = UnlCoordinates(latitude = 1.0, longitude = 0.5),
radius = 100 // radius in meters
)
// Create a polygon area with a list of coordinates (first and last should be identical to close the polygon)
val polygonCoordinates = arrayListOf(
UnlCoordinates(latitude = 1.0, longitude = 0.5),
UnlCoordinates(latitude = 0.5, longitude = 1.0),
UnlCoordinates(latitude = 1.0, longitude = 1.0),
UnlCoordinates(latitude = 1.0, longitude = 0.5) // Close the polygon
)
val polygon = UnlPolygonGeographicArea(polygonCoordinates)
// Monitor the areas
SdkCall.execute {
alarmService?.monitorArea(rect)
alarmService?.monitorArea(circle)
alarmService?.monitorArea(polygon)
}
// Java
// Create a rectangular area using minLat, maxLat, minLon, maxLon
RectangleGeographicArea rect = new RectangleGeographicArea(
0.5, // minimum latitude
1.0, // maximum latitude
0.5, // minimum longitude
1.0 // maximum longitude
);
// Create a circular area with center coordinates and radius in meters
CircleGeographicArea circle = new CircleGeographicArea(
new UnlCoordinates(1.0, 0.5),
100 // radius in meters
);
// Create a polygon area with a list of coordinates (first and last should be identical to close the polygon)
ArrayList<UnlCoordinates> polygonCoordinates = new ArrayList<>();
polygonCoordinates.add(new UnlCoordinates(1.0, 0.5));
polygonCoordinates.add(new UnlCoordinates(0.5, 1.0));
polygonCoordinates.add(new UnlCoordinates(1.0, 1.0));
polygonCoordinates.add(new UnlCoordinates(1.0, 0.5)); // Close the polygon
UnlPolygonGeographicArea polygon = new UnlPolygonGeographicArea(polygonCoordinates);
// Monitor the areas
SdkCall.execute(() -> {
if (alarmService != null) {
alarmService.monitorArea(rect);
alarmService.monitorArea(circle);
alarmService.monitorArea(polygon);
}
});
The SDK automatically manages area identification internally for boundary crossing detection.
Get a list of monitored areas¶
Access your active geofences via the monitoredAreas property, which returns a list of AlarmMonitoredArea objects, each one reflecting the parameters you provided to monitorArea.
- Kotlin
- Java
// Kotlin
val monitoredAreas = alarmService?.monitoredAreas ?: emptyList()
for (monitoredArea in monitoredAreas) {
val area = monitoredArea.area
val id = monitoredArea.id
Log.d("AreaMonitoring", "Monitoring area: $id")
}
// Java
List<AlarmMonitoredArea> monitoredAreas = alarmService != null ? alarmService.getMonitoredAreas() : Collections.emptyList();
for (AlarmMonitoredArea monitoredArea : monitoredAreas) {
UnlGeographicArea area = monitoredArea.getArea();
int id = monitoredArea.getId();
Log.d("AreaMonitoring", "Monitoring area: " + id);
}
💡 TIP
When defining a
UnlPolygonGeographicArea, always "close" the shape by making the first and last coordinates identical. Otherwise, the SDK may return polygons that don't match the one you provided.
Unmonitor an area¶
To remove a monitored area, call the unmonitorArea method and pass in the same UnlGeographicArea instance you originally supplied to monitorArea. This will unregister that zone and stop all related geofence events.
- Kotlin
- Java
// Kotlin
val rect = RectangleGeographicArea(
minLat = 0.5,
maxLat = 1.0,
minLon = 0.5,
maxLon = 1.0
)
alarmService?.monitorArea(rect)
// Later, unmonitor the same area
alarmService?.unmonitorArea(rect)
// Java
RectangleGeographicArea rect = new RectangleGeographicArea(
0.5,
1.0,
0.5,
1.0
);
if (alarmService != null) {
alarmService.monitorArea(rect);
// Later, unmonitor the same area
alarmService.unmonitorArea(rect);
}
To unmonitor multiple areas, call unmonitorArea for each area individually.
Get notified when the user enters an area:¶
Attach your UnlAlarmListener-including the onBoundaryCrossed callback - to your UnlAlarmService. This callback is triggered when the user crosses area boundaries.
- Kotlin
- Java
// Kotlin
val alarmListener = UnlAlarmListener.create {
onBoundaryCrossed {
Log.d("BoundaryCrossed", "Boundary crossed detected")
// Handle area entry/exit events
// Update UI based on area changes
// Use alarmService?.crossedBoundaries to get detailed boundary information
}
}
val alarmService = UnlAlarmService.produce(alarmListener)
// Java
UnlAlarmListener alarmListener = UnlAlarmListener.create(
() -> {
Log.d("BoundaryCrossed", "Boundary crossed detected");
// Handle area entry/exit events
// Update UI based on area changes
// Use alarmService.getCrossedBoundaries() to get detailed boundary information
}
);
UnlAlarmService alarmService = UnlAlarmService.produce(alarmListener);
Get the list of areas where the user is located¶
Retrieve the zones the user is currently inside by calling the insideAreas property on your UnlAlarmService instance:
- Kotlin
- Java
// Kotlin
val insideAreas = alarmService?.insideAreas ?: emptyList()
Log.d("AreaMonitoring", "User is inside ${insideAreas.size} areas")
// Java
List<UnlGeographicArea> insideAreas = alarmService != null ? alarmService.getInsideAreas() : Collections.emptyList();
Log.d("AreaMonitoring", "User is inside " + insideAreas.size() + " areas");
📝 INFO
For the insideAreas property to return a non-empty list, the user must be inside at least one monitored area and must move or change position within that area.
To retrieve the zones the user has exited, call the outsideAreas property on your UnlAlarmService instance.
Here's a complete Android Activity example that demonstrates area alarm functionality:
- Kotlin
- Java
// Kotlin
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.unlmap.sdk.core.*
import com.unlmap.sdk.places.UnlCoordinates
class AreaAlarmsActivity : AppCompatActivity() {
private var alarmService: UnlAlarmService? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setupAreaAlarms()
createAndMonitorAreas()
}
private fun setupAreaAlarms() {
// Create alarm listener with boundary crossing callback
val alarmListener = UnlAlarmListener.create {
onBoundaryCrossed {
Log.d("AreaAlarm", "Boundary crossed detected")
// Update UI to show area status changes
// Check crossedBoundaries for detailed information
SdkCall.execute {
val crossedBoundaries = alarmService?.crossedBoundaries
Log.i("AreaAlarm", "Crossed boundaries: $crossedBoundaries")
}
}
}
// Create alarm service
alarmService = UnlAlarmService.produce(alarmListener)
}
private fun createAndMonitorAreas() {
// Create different types of geographic areas
val rectangularArea = RectangleGeographicArea(
minLat = 37.7649,
maxLat = 37.7849,
minLon = -122.4294,
maxLon = -122.4094
)
val circularArea = CircleGeographicArea(
center = UnlCoordinates(latitude = 37.7749, longitude = -122.4194),
radius = 500 // 500 meters radius
)
val polygonCoordinates = arrayListOf(
UnlCoordinates(latitude = 37.7749, longitude = -122.4194),
UnlCoordinates(latitude = 37.7799, longitude = -122.4144),
UnlCoordinates(latitude = 37.7849, longitude = -122.4194),
UnlCoordinates(latitude = 37.7799, longitude = -122.4244),
UnlCoordinates(latitude = 37.7749, longitude = -122.4194) // Close the polygon
)
val polygonArea = UnlPolygonGeographicArea(polygonCoordinates)
// Monitor all areas
alarmService?.monitorArea(rectangularArea)
alarmService?.monitorArea(circularArea)
alarmService?.monitorArea(polygonArea)
Log.d("AreaAlarm", "Started monitoring 3 geographic areas")
checkMonitoredAreas()
}
}
private fun checkMonitoredAreas() {
SdkCall.execute {
val monitoredAreas = alarmService?.monitoredAreas ?: emptyList()
Log.d("AreaAlarm", "Currently monitoring ${monitoredAreas.size} areas")
for (area in monitoredAreas) {
Log.d("AreaAlarm", "Area ID: ${area.id}")
}
// Check which areas user is currently inside
val insideAreas = alarmService?.insideAreas ?: emptyList()
Log.d("AreaAlarm", "User is inside ${insideAreas.size} areas")
}
}
override fun onDestroy() {
super.onDestroy()
// Clean up - unmonitor all areas
SdkCall.execute {
// Unmonitor areas individually using the original area instances
alarmService?.unmonitorArea(rectangularArea)
alarmService?.unmonitorArea(circularArea)
alarmService?.unmonitorArea(polygonArea)
Log.d("AreaAlarm", "Unmonitored all areas")
}
}
}
// Java
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import com.unlmap.sdk.core.*;
import com.unlmap.sdk.places.UnlCoordinates;
class AreaAlarmsActivity extends AppCompatActivity {
private UnlAlarmService alarmService = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setupAreaAlarms();
createAndMonitorAreas();
}
private void setupAreaAlarms() {
// Create alarm listener with boundary crossing callback
UnlAlarmListener alarmListener = UnlAlarmListener.create(
() -> {
Log.d("AreaAlarm", "Boundary crossed detected");
// Update UI to show area status changes
// Check crossedBoundaries for detailed information
SdkCall.execute(() -> {
Object crossedBoundaries = alarmService != null ? alarmService.getCrossedBoundaries() : null;
Log.i("AreaAlarm", "Crossed boundaries: " + crossedBoundaries);
});
}
);
// Create alarm service
alarmService = UnlAlarmService.produce(alarmListener);
}
private void createAndMonitorAreas() {
// Create different types of geographic areas
RectangleGeographicArea rectangularArea = new RectangleGeographicArea(
37.7649,
37.7849,
-122.4294,
-122.4094
);
CircleGeographicArea circularArea = new CircleGeographicArea(
new UnlCoordinates(37.7749, -122.4194),
500 // 500 meters radius
);
ArrayList<UnlCoordinates> polygonCoordinates = new ArrayList<>();
polygonCoordinates.add(new UnlCoordinates(37.7749, -122.4194));
polygonCoordinates.add(new UnlCoordinates(37.7799, -122.4144));
polygonCoordinates.add(new UnlCoordinates(37.7849, -122.4194));
polygonCoordinates.add(new UnlCoordinates(37.7799, -122.4244));
polygonCoordinates.add(new UnlCoordinates(37.7749, -122.4194)); // Close the polygon
UnlPolygonGeographicArea polygonArea = new UnlPolygonGeographicArea(polygonCoordinates);
// Monitor all areas
if (alarmService != null) {
alarmService.monitorArea(rectangularArea);
alarmService.monitorArea(circularArea);
alarmService.monitorArea(polygonArea);
}
Log.d("AreaAlarm", "Started monitoring 3 geographic areas");
checkMonitoredAreas();
}
}
private void checkMonitoredAreas() {
SdkCall.execute(() -> {
List<AlarmMonitoredArea> monitoredAreas = alarmService != null ? alarmService.getMonitoredAreas() : Collections.emptyList();
Log.d("AreaAlarm", "Currently monitoring " + monitoredAreas.size() + " areas");
for (AlarmMonitoredArea area : monitoredAreas) {
Log.d("AreaAlarm", "Area ID: " + area.getId());
}
// Check which areas user is currently inside
List<UnlGeographicArea> insideAreas = alarmService != null ? alarmService.getInsideAreas() : Collections.emptyList();
Log.d("AreaAlarm", "User is inside " + insideAreas.size() + " areas");
});
}
@Override
protected void onDestroy() {
super.onDestroy();
// Clean up - unmonitor all areas
SdkCall.execute(() -> {
if (alarmService != null) {
// Unmonitor areas individually using the original area instances
alarmService.unmonitorArea(rectangularArea);
alarmService.unmonitorArea(circularArea);
alarmService.unmonitorArea(polygonArea);
}
Log.d("AreaAlarm", "Unmonitored all areas");
});
}
}
This example demonstrates:
- Creating different types of geographic areas (rectangle, circle, polygon)
- Monitoring areas with the UnlAlarmService
- Handling boundary crossing events with proper Android logging
- Checking currently monitored and inside areas
- Proper cleanup when the activity is destroyed