Skip to content

Location and Proximity

Sam Woodall edited this page Jul 16, 2020 · 9 revisions

The Location module brings Rover-powered geofence monitoring, Bluetooth Low Energy beacon monitoring, and general location tracking to your app, when your users grant location permission. This allows you to automate Rover Campaigns, triggering on geographic events.


Initialization

By default, the Location module enables all three (geofences, beacon monitoring, and location tracking) by default. However, you can opt in or out by setting parameters on LocationAssembler as follows:

RoverCampaigns.initialize(
    // ...,
    LocationAssembler(
        automaticGeofenceMonitoring = true,
        automaticBeaconMonitoring = true,
        automaticLocationTracking = true
    )
)

Requesting Permissions from your User

You then need, at an appropriate moment in your product’s user flow, prompt users to choose whether or not to grant your app ongoing location permission. You will use the Android permissions framework to do this.

Note that this serves as a check; if the permission has already been granted, it will not prompt again on subsequent invocations. Note that it may be necessary to add it in more than one area: for instance, if you include it in a shown-only-once on boarding area, it may be necessary to add it to your 'Home' screen as well. This is to gracefully handle any changes in the permission granted to your app, for example if the user decides to clean up the apps allowed to access their location in their system-wide privacy settings.

Declare ACCESS_BACKGROUND_LOCATION permission in app's mainfest:

<manifest ... >
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>

Create a helper method for prompting for permission and override the Android callback template method onRequestPermissionsResult:

import android.Manifest
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import io.rover.campaigns.core.RoverCampaigns

private fun makePermissionsAttempt() {
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(
                this,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION),
                0
            )
    } else {
        // Permission has already been granted
        RoverCampaigns.shared?.resolveSingletonOrFail(PermissionsNotifierInterface::class.java)?.permissionGranted(
            Manifest.permission.ACCESS_FINE_LOCATION
        )
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            RoverCampaigns.shared?.resolveSingletonOrFail(PermissionsNotifierInterface::class.java)?.permissionGranted(
                Manifest.permission.ACCESS_BACKGROUND_LOCATION
            )
        } else {
            ActivityCompat.requestPermissions(this,
                arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), 0
            )
        }
    }
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    val perms = permissions.zip(grantResults.toList()).associate { it }
    if(perms[Manifest.permission.ACCESS_FINE_LOCATION] == PackageManager.PERMISSION_GRANTED) {
        RoverCampaigns.shared?.resolveSingletonOrFail(PermissionsNotifierInterface::class.java)?.permissionGranted(
            Manifest.permission.ACCESS_FINE_LOCATION
        )
    }
    if(perms[Manifest.permission.ACCESS_BACKGROUND_LOCATION] == PackageManager.PERMISSION_GRANTED) {
        RoverCampaigns.shared?.resolveSingletonOrFail(PermissionsNotifierInterface::class.java)?.permissionGranted(
            Manifest.permission.ACCESS_BACKGROUND_LOCATION
        )
    }
}

Then you can call makePermissionsAttempt at the appropriate point in your user flow.

Rover will remember that the permission was granted across app restarts and will gracefully handle the permission being removed, but it remains prudent to continue checking each time from your main home screen or somewhere similarly appropriate.

Note: If your app does not target Android 10 or higher, then the ACCESS_BACKGROUND_LOCATION permission logic and manifest declaration are not needed.

More details on how to properly handle requesting app permissions can be found in the Android documentation: Request App Permissions.

Clone this wiki locally