Skip to content

Geofencing API 5.x

Olga Koroleva edited this page Nov 9, 2022 · 3 revisions

For 6.x version - Geofencing API

Mobile Messaging Geofencing API is designed and developed to easily enable developers make their application location aware in few steps. Geofencing API will notify the user each time specific geofence area is entered.

To mark a location of interest, you specify its latitude and longitude. To adjust the proximity for the location, you add a radius. The latitude, longitude, and radius define a geofence, creating a circular area, or fence, around the location of interest.

Installation

In order to install Geofencing service, declare an additional dependency in your application's build.gradle file:

dependencies {
    ...
    implementation 'com.infobip:infobip-mobile-messaging-android-geo-sdk:4.+@aar'
}

Check latest version here.

Notice

All required manifest components are merged to application manifest automatically by manifest merger. Please include geo-related components to manifest manually if manifest merger was disabled.

Enabling the Geofencing service

In order to enable the Geofencing service, use the following option:

MobileGeo.getInstance(this).activateGeofencing()
expand to see Java code

MobileGeo.getInstance(this).activateGeofencing();

Geofencing service requires location permission. For Android versions bigger than 6.0 Marshmallow, it's important to request location permission from user manually, or system may throw SecurityException if permission is not accepted already:

override fun onCreate(savedInstanceState: Bundle) {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        val permissions = arrayOf(Manifest.permission.ACCESS_FINE_LOCATION)
        ActivityCompat.requestPermissions(this, permissions, LOCATION_PERMISSION_REQUEST_CODE)
        return
    }
    MobileGeo.getInstance(this).activateGeofencing()
}

  ...

open fun onRequestPermissionsResult(requestCode: Int, @NonNull permissions: Array<String>, @NonNull grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return
        }
        if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) {
            return
        }
        MobileGeo.getInstance(this).activateGeofencing()
    }
expand to see Java code

@Override
protected void onCreate(Bundle savedInstanceState) {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        String permissions[] = {Manifest.permission.ACCESS_FINE_LOCATION};
        ActivityCompat.requestPermissions(this, permissions, LOCATION_PERMISSION_REQUEST_CODE);
        return;
    }

    MobileGeo.getInstance(this).activateGeofencing();
}

  ...

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }

    if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) {
        return;
    }

    MobileGeo.getInstance(this).activateGeofencing();
}

Notice

For some devices with API 29 (Android 10), geofencing monitoring activation may fail with following error in the console GeofencingImpl: Geofencing monitoring activation failed: Status{statusCode=ERROR, resolution=null}, while only ACCESS_FINE_LOCATION permission used - Google issue. To prevent it try to add also ACCESS_BACKGROUND_LOCATION.

Handle area entered event

When geofence area is entered, GeoEvent.GEOFENCE_AREA_ENTERED event is triggered. You can handle geofence area details using Geo object and campaign details using GeoMessage object:

val geofenceAreaEnteredReceiver: BroadcastReceiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent) {
        val geoMessage: GeoMessage = GeoMessage.createFrom(intent.extras)
        val geo = geoMessage.geo
        // do something...
    }
}
expand to see Java code

private final BroadcastReceiver geofenceAreaEnteredReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        GeoMessage geoMessage = GeoMessage.createFrom(intent.getExtras());
        Geo geo = geoMessage.getGeo();
        // do something...
    }
};

Don't forget to register your BroadcastReceiver to GEOFENCE_AREA_ENTERED event:

val localBroadcastManager = LocalBroadcastManager.getInstance(this)
localBroadcastManager.registerReceiver(geofenceAreaEnteredReceiver,
        IntentFilter(GeoEvent.GEOFENCE_AREA_ENTERED.key))
expand to see Java code

LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);
localBroadcastManager.registerReceiver(geofenceAreaEnteredReceiver,
        new IntentFilter(GeoEvent.GEOFENCE_AREA_ENTERED.getKey()));

Choose the optimal radius for your geofence

For best results, the minimium radius of the geofence should be set between 100 - 150 meters. When Wi-Fi is available location accuracy is usually between 20 - 50 meters. When indoor location is available, the accuracy range can be as small as 5 meters. Unless you know indoor location is available inside the geofence, assume that Wi-Fi location accuracy is about 50 meters. When Wi-Fi location is not available (for example, when you are driving in rural areas) the location accuracy degrades. The accuracy range can be as large as several hundred meters to several kilometers. In cases like this, you should create geofences using a larger radius.

Taken from: https://developer.android.com/training/location/geofencing.html#BestPractices

Clone this wiki locally