kmp-geofence-library
1.0.2indexedLightweight geofencing library offering lambda/callback-based enter/exit events, permission status checks, dynamic add/remove of circular geofences, background-capable event listeners, easy integration.
Lightweight geofencing library offering lambda/callback-based enter/exit events, permission status checks, dynamic add/remove of circular geofences, background-capable event listeners, easy integration.
A Kotlin Multiplatform library for geofencing on Android and iOS with callback-based event handling.
In your build.gradle.kts:
commonMain.dependencies {
implementation("io.github.mallikarjunpatelsh:geofence:1.0.2")
}
mavenCentral() is already included by default so no extra repository setup needed.
< = />
Initialize GeofenceContext and set the event listener in your Application class. Setting the listener here ensures callbacks work even in the background:
No additional initialization needed.
<key>NSLocationAlwaysAndWhenInUseUsageDescription
Give the description
NSLocationWhenInUseUsageDescription
Give the description
UIBackgroundModes
location
val geofenceManager = createGeofenceManager()
geofenceManager.setGeofenceEventListener(object : GeofenceEventListener {
override fun onGeofenceEnter(event: ) {
println()
println()
}
{
println()
println()
}
})
when (val status = geofenceManager.checkLocationPermissions()) {
is PermissionStatus.Granted -> {
println("All permissions granted")
}
is PermissionStatus.Denied -> {
println("Missing permissions: ${status.missingPermissions}")
println("Message: ${status.message}")
// Request permissions from user
}
}
geofenceManager.addGeofence(
id = "delivery_location_123",
latitude = 37.7749,
longitude = -122.4194,
radius = 100f, // meters
onSuccess = {
println("Geofence added successfully")
},
onFailure = { error ->
println("Failed to add geofence: $error")
}
)
geofenceManager.removeGeofences(
ids = listOf("delivery_location_123", "delivery_location_456"),
onSuccess = {
println("Geofences removed successfully")
},
onFailure = { error ->
println("Failed to remove geofences: $error")
}
)
data class GeofenceEvent(
val geofenceId: String,
val latitude: Double,
val longitude: Double,
val transitionType: TransitionType
)
sealed class PermissionStatus {
object Granted : PermissionStatus()
data class Denied(
val missingPermissions: List<PermissionType>,
val message: String
) : PermissionStatus()
}
enum class PermissionType {
FINE_LOCATION,
BACKGROUND_LOCATION,
PRECISE_LOCATION
}
Application class for background supportaddGeofenceThis library is provided as-is for use in your projects.
Feel free to submit issues and enhancement requests!
import android.app.Application
import com.kmp.geofence.GeofenceBroadcastReceiver
import com.kmp.geofence.GeofenceContext
import com.kmp.geofence.TransitionType
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// Initialize context
GeofenceContext.init(this)
// Set listener here — Application is always alive
GeofenceBroadcastReceiver.setEventListener { event ->
when (event.transitionType) {
TransitionType.ENTER -> {
println("✅ ENTERED: ${event.geofenceId}")
// handle enter — call API, save to DB, send notification, etc.
}
TransitionType.EXIT -> {
println("✅ EXITED: ${event.geofenceId}")
// handle exit
}
}
}
}
}
// MyApplication.kt
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
GeofenceContext.init(this)
GeofenceBroadcastReceiver.setEventListener { event ->
when (event.transitionType) {
TransitionType.ENTER -> println("✅ ENTERED: ${event.geofenceId}")
TransitionType.EXIT -> println("✅ EXITED: ${event.geofenceId}")
}
}
}
}
// MyActivity.kt
class MyActivity : ComponentActivity() {
private val geofenceManager = createGeofenceManager()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
when (val status = geofenceManager.checkLocationPermissions()) {
is PermissionStatus.Granted -> addGeofences()
is PermissionStatus.Denied -> requestPermissions(status.missingPermissions)
}
}
private fun addGeofences() {
geofenceManager.addGeofence(
id = "delivery_1",
latitude = 37.7749,
longitude = -122.4194,
radius = 100f,
onSuccess = { println("Geofence added!") },
onFailure = { error -> println("Failed: $error") }
)
}
}
val geofenceManager = createGeofenceManager()
// Step 1: Set listener BEFORE addGeofence
geofenceManager.setGeofenceEventListener(object : GeofenceEventListener {
override fun onGeofenceEnter(event: GeofenceEvent) {
println("✅ ENTERED: ${event.geofenceId}")
}
override fun onGeofenceExit(event: GeofenceEvent) {
println("✅ EXITED: ${event.geofenceId}")
}
})
// Step 2: Check permissions
when (val status = geofenceManager.checkLocationPermissions()) {
is PermissionStatus.Granted -> {
// Step 3: Add geofence
geofenceManager.addGeofence(
id = "delivery_1",
latitude = 37.7749,
longitude = -122.4194,
radius = 100f,
onSuccess = { println("Geofence added!") },
onFailure = { error -> println("Failed: $error") }
)
}
is PermissionStatus.Denied -> {
println("Missing: ${status.missingPermissions}")
// request permissions
}
}
addGeofence(id: String, latitude: Double, longitude: Double, radius: Float, onSuccess: () -> Unit, onFailure: (String) -> Unit)
removeGeofences(ids: List<String>, onSuccess: () -> Unit, onFailure: (String) -> Unit)
checkLocationPermissions(): PermissionStatus
setGeofenceEventListener(listener: GeofenceEventListener?)
Surfaced from shared tags and platforms — no rankings paid for.