Monitor geofences - Android
This document explains how to set up your app to receive Push notifications via Mapp Cloud when a user is in a location of interest.
In the AndroidManifest file, you must declare ACCESS_FINE_LOCATION and ACCESS_BACKGROUND_LOCATION
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> |
If your app targets Android 10 (API level 29) or higher ACCESS_BACKGROUND_LOCATION is mandatory.
Ask for runtime permission when the user interacts with a feature in your application which demands location access.
private boolean isGeoPermissionGranted() {
if (Build.VERSION.SDK_INT >= 29) {
return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED ;
}
else {
return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
}
private void askForGeoPermission() {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION,},
MY_PERMISSIONS_ACCESS_FINE_LOCATION);
}
private void askForGeoPermissionWithBackgroundLocation() {
boolean permissionAccessFineLocationApproved =
ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED;
if (permissionAccessFineLocationApproved) {
boolean backgroundLocationPermissionApproved =
ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_BACKGROUND_LOCATION)
== PackageManager.PERMISSION_GRANTED;
if (backgroundLocationPermissionApproved) {
} else {
ActivityCompat.requestPermissions(this, new String[] {
Manifest.permission.ACCESS_BACKGROUND_LOCATION},
MY_PERMISSIONS_ACCESS_FINE_AND_BACKGROUND_LOCATION);
}
} else {
ActivityCompat.requestPermissions(this, new String[] {
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
},
MY_PERMISSIONS_ACCESS_FINE_AND_BACKGROUND_LOCATION);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (MY_PERMISSIONS_ACCESS_FINE_LOCATION == requestCode) {
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Appoxee.instance().startGeoFencing();
Log.w("MainActivity", "startGeoFencing()");
}
else {
Log.w("MainActivity", "Geo permission not granted");
}
}
} |
To start geofence call (deprecated, without receiving Geofence status or errors)
@Deprecated("Use method bellow for better error and status handling of geofence starting.")
Appoxee.instance().startGeoFencing(); |
To start geofence call (with receiving geofence status or errors)
List of all possible statuses when starting Geofence:
In the example below, you can see how to ask for permission and start geofencing:
To stop geofence call (deprecated, without receiving Geofence status or errors)
To stop geofence call (with receiving Geofence status or errors)
Best practices to improve geofencing:
enable Wi-Fi or Wi-Fi scanning
enable Bluetooth or Bluetooth scanning
enable Mobile data
disable Airplane Mode (the phone must NOT be in Airplane Mode)
avoid using Power Saving Mode
enable Mobile data
Use code below to enable Wi-Fi scanning from code
Or you can use code below to redirect the user to Location Service in Settings:
On this page user should enable:
Wi-FI scanning,
Bluetooth scanning,
Emergency Location Service and
Google Location Accuracy
In the screenshots above you can see which options should be enabled when the user is redirected to Location Service in Settings.
Recommendations
Setting a minimum radius of 100 meters (150 is recommended ) will get you the best results from your geofences. This helps account for the location accuracy of typical Wi-Fi networks, and also helps reduce device power consumption.
Troubleshoot the geofence entrance event: (https://developer.android.com/training/location/geofencing#Troubleshooting). If geofences aren't being triggered when the device enters a geofence (the GEOFENCE_TRANSITION_ENTER alert isn’t triggered), first, ensure that your geofences are registered properly as described in this guide.
Here are some possible reasons for alerts not working as expected:
Accurate location isn't available inside your geofence or your geofence is too small. On most devices, the geofence service uses only the network location for geofence triggering. The service uses this approach because network location consumes much less power, it takes less time to get discrete locations, and most importantly it’s available indoors.
Wi-Fi is turned off on the device. Having Wi-Fi on can significantly improve the location accuracy, so if Wi-Fi is turned off, your application might never get geofence alerts depending on several settings including the radius of the geofence, the device model, or the Android version. Starting from Android 4.3 (API level 18), we added the capability of “Wi-Fi scan only mode” which allows users to disable Wi-Fi but still get a good network location. It’s good practice to prompt the user and provide a shortcut for the user to enable Wi-Fi or Wi-Fi scan only mode if both of them are disabled. Use SettingsClient to ensure that the device's system settings are properly configured for optimal location detection.
Note: If your app targets Android 10 (API level 29) or higher, you cannot call WifiManager.setEnabled() (deprecated from API 28!!!) directly unless your app is a system app or a device policy controller (DPC). Instead, use a settings panel.
There is no reliable network connectivity inside your geofence. If there is no reliable data connection, alerts might not be generated. This is because the geofence service depends on the network location provider which in turn requires a data connection.
Alerts can be late. The geofence service doesn't continuously query for location, so expect some latency when receiving alerts. Usually, the latency is less than 2 minutes, even less when the device has been moving. If Background Location Limits are in effect, the latency is about 2-3 minutes on average. If the device has been stationary for a significant period of time, the latency may increase (up to 6 minutes).
Additional information on handling geofencing transitions can be found here.
Location settings
Android 9.0+
To change location settings:
Open your device's Settings app.
Tap Security & Location → Location.
If you have a work profile, tap Advanced.
Then, choose the option:
Turn Location on or off: Tap Location.
Scan for nearby networks: Tap Advanced → Scanning. Turn Wi-Fi scanning and Bluetooth scanning on.
Turn emergency location service on or off: Tap Advanced → Google Emergency Location Service. Turn Emergency Location Service on.
Android 4.4 - 8.1
You can choose your location mode based on accuracy, speed, and battery use.
Open your phone's Settings app.
Tap Security & Location → Location. If you don't see "Security & Location," tap Location.
Tap Mode. Then pick:
High accuracy: Use GPS, Wi-Fi, mobile networks, and sensors to get the most accurate location. Use Google Location Services to help estimate your phone's location faster and more accurately.
Battery saving: Use sources that use less battery, like Wi-Fi and mobile networks. Use Google Location Services to help estimate your phone's location faster and more accurately.
Device only: Use the only GPS. Don’t use Google Location Services to provide location information. This can estimate your phone's location more slowly and use more battery.