August 13, 2021

Add geofences in android

By lj007

Create Geofence client and Add

private var geofenceList: ArrayList<geofence> = ArrayList()
geofencingClient = LocationServices.getGeofencingClient(this)

Create list for geofences

private var geofenceList: ArrayList<geofence> = ArrayList()
geofenceList.add(Geofence.Builder().setRequestId(requestId.toString()).setCircularRegion(latitude, longitude, distance)
                        .setLoiteringDelay(60000).setExpirationDuration(-1).setTransitionTypes(Geofence.GEOFENCE_TRANSITION_DWELL or Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT).build())

you can check all parameters here

Create Geofences request

private fun getGeofencingRequest(): GeofencingRequest {
        return GeofencingRequest.Builder().apply {
            setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER)
            addGeofences(geofenceList)
        }.build()
    }

Create pending Intent for Geofences

private val geofencePendingIntent: PendingIntent by lazy {
        val intent = Intent(this, MyGeoFencingTransition::class.java)
        // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling
        // addGeofences() and removeGeofences().
        PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
    }

You need to create one Intent Service to receive events from Geofence. In this MyGeoFencingTransition is that one. You must need to register this service in Manifest.xml file.

Add geofences now

geofencingClient.addGeofences(getGeofencingRequest(), geofencePendingIntent)?.run {
            addOnSuccessListener {
                Toast.makeText(baseContext, "Geofence successfully added", Toast.LENGTH_SHORT).show()
            }

            addOnFailureListener {
                Toast.makeText(baseContext, "Geofence exception occurs -->  ${it.localizedMessage}", Toast.LENGTH_SHORT).show()
            }
        }

And the final one MyGeoFencingTransition

class MyGeoFencingTransition : IntentService("MyGeoFencingTransition") {
    override fun onHandleIntent(intent: Intent?) {
        val geofencingEvent = GeofencingEvent.fromIntent(intent)
        if (geofencingEvent.hasError()) {
//            Log.e("Geofence", geofencingEvent.errorCode.toString())
            return
        }

        // Get the transition type.
        val geofenceTransition = geofencingEvent.geofenceTransition
        sendNotification(geofencingEvent.triggeringGeofences, geofenceTransition, geofencingEvent.triggeringLocation)

    }

    private fun sendNotification(triggeringGeofences: List<geofence>, geofenceTransition: Int, triggeringLocation: Location) {

        //You can receive this broadcast by creating broadcast receiver in activity.
        val geofenceIds: ArrayList<string> = ArrayList()
        triggeringGeofences.forEach {
            geofenceIds.add(it.requestId)
        }
        val intent = Intent("$packageName.GeofenceTriggered")
        intent.putExtra(ParamsUtils.geofenceIds, geofenceIds) //geofence Ids for which event occurs
        intent.putExtra(ParamsUtils.geofenceTransition, geofenceTransition) // geofence event can be Geofence.GEOFENCE_TRANSITION_ENTER || Geofence.GEOFENCE_TRANSITION_EXIT || Geofence.GEOFENCE_TRANSITION_DWELL
        intent.putExtra(ParamsUtils.latitude, triggeringLocation)
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
    }
}

Now you can receive broadcast in activity and perform any task. Please always check best practices