How To Set Up A Geofence
Geofencing combines awareness of the user's current location with awareness of the user's proximity to locations that may be of interest. To mark a location of interest, you specify its latitude and longitude. To suit the proximity for the location, yous add a radius. The latitude, longitude, and radius ascertain a geofence, creating a circular area, or contend, around the location of interest.
You can have multiple agile geofences, with a limit of 100 per app, per device user. For each geofence, y'all tin can ask Location Services to send you lot archway and go out events, or you lot tin can specify a elapsing within the geofence surface area to wait, or dwell, before triggering an consequence. Y'all can limit the duration of whatever geofence by specifying an expiration duration in milliseconds. After the geofence expires, Location Services automatically removes it.
This lesson shows you how to add and remove geofences, then listen for geofence transitions using a BroadcastReceiver
.
Set up for geofence monitoring
The outset step in requesting geofence monitoring is to asking the necessary permissions. To utilize geofencing, your app must request the following:
-
ACCESS_FINE_LOCATION
-
ACCESS_BACKGROUND_LOCATION
if your app targets Android x (API level 29) or higher
To learn more than, encounter the guide on how to asking location permissions.
If you want to utilise a BroadcastReceiver
to mind for geofence transitions, add an element specifying the service proper name. This element must be a child of the <application>
element:
<application android:allowBackup="true"> ... <receiver android:name=".GeofenceBroadcastReceiver"/> <awarding/>
To admission the location APIs, you demand to create an case of the Geofencing customer. To learn how to connect your customer:
Kotlin
lateinit var geofencingClient: GeofencingClient override fun onCreate(savedInstanceState: Bundle?) { // ... geofencingClient = LocationServices.getGeofencingClient(this) }
Java
private GeofencingClient geofencingClient; @Override public void onCreate(Bundle savedInstanceState) { // ... geofencingClient = LocationServices.getGeofencingClient(this); }
Create and add geofences
Your app needs to create and add geofences using the location API'due south builder class for creating Geofence objects, and the convenience class for adding them. Also, to handle the intents sent from Location Services when geofence transitions occur, you lot can define a PendingIntent
as shown in this section.
Note: On single-user devices, in that location is a limit of 100 geofences per app. For multi-user devices, the limit is 100 geofences per app per device user.
Create geofence objects
Get-go, use Geofence.Builder
to create a geofence, setting the desired radius, duration, and transition types for the geofence. For case, to populate a list object:
Kotlin
geofenceList.add together(Geofence.Architect() // Ready the request ID of the geofence. This is a cord to identify this // geofence. .setRequestId(entry.key) // Set up the round region of this geofence. .setCircularRegion( entry.value.breadth, entry.value.longitude, Constants.GEOFENCE_RADIUS_IN_METERS ) // Fix the expiration duration of the geofence. This geofence gets automatically // removed subsequently this menses of time. .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS) // Set the transition types of interest. Alerts are only generated for these // transition. We rails entry and exit transitions in this sample. .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER or Geofence.GEOFENCE_TRANSITION_EXIT) // Create the geofence. .build())
Java
geofenceList.add(new Geofence.Builder() // Set the request ID of the geofence. This is a cord to place this // geofence. .setRequestId(entry.getKey()) .setCircularRegion( entry.getValue().latitude, entry.getValue().longitude, Constants.GEOFENCE_RADIUS_IN_METERS ) .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS) .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT) .build());
This example pulls data from a constants file. In actual practice, apps might dynamically create geofences based on the user'south location.
Specify geofences and initial triggers
The following snippet uses the GeofencingRequest
class and its nested GeofencingRequestBuilder
class to specify the geofences to monitor and to prepare how related geofence events are triggered:
Kotlin
private fun getGeofencingRequest(): GeofencingRequest { return GeofencingRequest.Builder().apply { setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER) addGeofences(geofenceList) }.build() }
Coffee
private GeofencingRequest getGeofencingRequest() { GeofencingRequest.Builder builder = new GeofencingRequest.Builder(); builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER); builder.addGeofences(geofenceList); return builder.build(); }
This example shows the apply of two geofence triggers. The GEOFENCE_TRANSITION_ENTER
transition triggers when a device enters a geofence, and the GEOFENCE_TRANSITION_EXIT
transition triggers when a device exits a geofence. Specifying INITIAL_TRIGGER_ENTER
tells Location services that GEOFENCE_TRANSITION_ENTER
should be triggered if the device is already inside the geofence.
In many cases, it may be preferable to use instead INITIAL_TRIGGER_DWELL
, which triggers events only when the user stops for a defined duration within a geofence. This arroyo can help reduce "warning spam" resulting from large numbers notifications when a device briefly enters and exits geofences. Another strategy for getting best results from your geofences is to set a minimum radius of 100 meters. This helps account for the location accuracy of typical Wi-Fi networks, and also helps reduce device power consumption.
Ascertain a broadcast receiver for geofence transitions
An Intent
sent from Location Services tin trigger various actions in your app, merely you should not have it offset an activeness or fragment, because components should simply go visible in response to a user action. In many cases, a BroadcastReceiver
is a adept way to handle a geofence transition. A BroadcastReceiver
gets updates when an event occurs, such every bit a transition into or out of a geofence, and can start long-running background work.
The following snippet shows how to define a PendingIntent
that starts a BroadcastReceiver
:
Kotlin
class MainActivity : AppCompatActivity() { // ... private val geofencePendingIntent: PendingIntent past lazy { val intent = Intent(this, GeofenceBroadcastReceiver::class.java) // Nosotros utilise FLAG_UPDATE_CURRENT and so that nosotros get the same pending intent back when calling // addGeofences() and removeGeofences(). PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT) } }
Java
public grade MainActivity extends AppCompatActivity { // ... individual PendingIntent getGeofencePendingIntent() { // Reuse the PendingIntent if we already have it. if (geofencePendingIntent != null) { return geofencePendingIntent; } Intent intent = new Intent(this, GeofenceBroadcastReceiver.class); // We use FLAG_UPDATE_CURRENT and so that we get the aforementioned pending intent back when // calling addGeofences() and removeGeofences(). geofencePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent. FLAG_UPDATE_CURRENT); return geofencePendingIntent; }
Add geofences
To add together geofences, use the
method. Provide the GeofencingClient.addGeofences()
GeofencingRequest
object, and the PendingIntent
. The post-obit snippet demonstrates processing the results:
Kotlin
geofencingClient?.addGeofences(getGeofencingRequest(), geofencePendingIntent)?.run { addOnSuccessListener { // Geofences added // ... } addOnFailureListener { // Failed to add geofences // ... } }
Java
geofencingClient.addGeofences(getGeofencingRequest(), getGeofencePendingIntent()) .addOnSuccessListener(this, new OnSuccessListener<Void>() { @Override public void onSuccess(Void avoid) { // Geofences added // ... } }) .addOnFailureListener(this, new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Failed to add geofences // ... } });
Handle geofence transitions
When Location Services detects that the user has entered or exited a geofence, it sends out the Intent
contained in the PendingIntent
you included in the request to add geofences. A broadcast receiver similar GeofenceBroadcastReceiver
notices that the Intent
was invoked and tin then obtain the geofencing effect from the intent, determine the type of Geofence transition(s), and decide which of the divers geofences was triggered. The broadcast receiver can direct an app to start performing background work or, if desired, transport a notification equally output.
Annotation: On Android 8.0 (API level 26) and higher, if an app is running in the background while monitoring a geofence, then the device responds to geofencing events every couple of minutes. To learn how to adapt your app to these response limits, see Background Location Limits.
The following snippet shows how to define a BroadcastReceiver
that posts a notification when a geofence transition occurs. When the user clicks the notification, the app'southward main action appears:
Kotlin
course GeofenceBroadcastReceiver : BroadcastReceiver() { // ... override fun onReceive(context: Context?, intent: Intent?) { val geofencingEvent = GeofencingEvent.fromIntent(intent) if (geofencingEvent.hasError()) { val errorMessage = GeofenceStatusCodes .getStatusCodeString(geofencingEvent.errorCode) Log.e(TAG, errorMessage) return } // Get the transition type. val geofenceTransition = geofencingEvent.geofenceTransition // Test that the reported transition was of involvement. if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER | geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) { // Get the geofences that were triggered. A single consequence tin can trigger // multiple geofences. val triggeringGeofences = geofencingEvent.triggeringGeofences // Go the transition details as a String. val geofenceTransitionDetails = getGeofenceTransitionDetails( this, geofenceTransition, triggeringGeofences ) // Send notification and log the transition details. sendNotification(geofenceTransitionDetails) Log.i(TAG, geofenceTransitionDetails) } else { // Log the error. Log.e(TAG, getString(R.cord.geofence_transition_invalid_type, geofenceTransition)) } } }
Coffee
public class GeofenceBroadcastReceiver extends BroadcastReceiver { // ... protected void onReceive(Context context, Intent intent) { GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent); if (geofencingEvent.hasError()) { String errorMessage = GeofenceStatusCodes .getStatusCodeString(geofencingEvent.getErrorCode()); Log.e(TAG, errorMessage); return; } // Go the transition type. int geofenceTransition = geofencingEvent.getGeofenceTransition(); // Test that the reported transition was of involvement. if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) { // Get the geofences that were triggered. A single event can trigger // multiple geofences. List<Geofence> triggeringGeofences = geofencingEvent.getTriggeringGeofences(); // Get the transition details as a String. String geofenceTransitionDetails = getGeofenceTransitionDetails( this, geofenceTransition, triggeringGeofences ); // Ship notification and log the transition details. sendNotification(geofenceTransitionDetails); Log.i(TAG, geofenceTransitionDetails); } else { // Log the error. Log.eastward(TAG, getString(R.cord.geofence_transition_invalid_type, geofenceTransition)); } } }
Afterward detecting the transition event via the PendingIntent
, the BroadcastReceiver
gets the geofence transition blazon and tests whether it is one of the events the app uses to trigger notifications -- either GEOFENCE_TRANSITION_ENTER
or GEOFENCE_TRANSITION_EXIT
in this instance. The service and so sends a notification and logs the transition details.
Stop geofence monitoring
Stopping geofence monitoring when it is no longer needed or desired can aid save battery power and CPU cycles on the device. You can finish geofence monitoring in the master action used to add together and remove geofences; removing a geofence stops information technology immediately. The API provides methods to remove geofences either by asking IDs, or past removing geofences associated with a given PendingIntent
.
The following snippet removes geofences by PendingIntent
, stopping all further notification when the device enters or exits previously added geofences:
Kotlin
geofencingClient?.removeGeofences(geofencePendingIntent)?.run { addOnSuccessListener { // Geofences removed // ... } addOnFailureListener { // Failed to remove geofences // ... } }
Java
geofencingClient.removeGeofences(getGeofencePendingIntent()) .addOnSuccessListener(this, new OnSuccessListener<Void>() { @Override public void onSuccess(Void avoid) { // Geofences removed // ... } }) .addOnFailureListener(this, new OnFailureListener() { @Override public void onFailure(@NonNull Exception e) { // Failed to remove geofences // ... } });
You lot tin combine geofencing with other location-enlightened features, such as periodic location updates. For more information, see the other lessons in this course.
Utilize best practices for geofencing
This section outlines recommendations for using geofencing with the location APIs for Android.
Reduce ability consumption
Y'all can use the following techniques to optimize power consumption in your apps that utilize geofencing:
-
Prepare the notification responsiveness to a higher value. Doing so improves power consumption by increasing the latency of geofence alerts. For example, if you lot set a responsiveness value of five minutes your app but checks for an archway or get out warning in one case every 5 minutes. Setting lower values doesn't necessarily mean that users are notified inside that time period (for case, if you set a value of 5 seconds it may take a fleck longer than that to receive the alarm).
-
Employ a larger geofence radius for locations where a user spends a meaning corporeality of time, such as dwelling or work. While a larger radius doesn't directly reduce power consumption, information technology reduces the frequency at which the app checks for entrance or get out, effectively lowering overall power consumption.
Choose the optimal radius for your geofence
For best results, the minimum radius of the geofence should be set up between 100 - 150 meters. When Wi-Fi is available location accuracy is usually betwixt twenty - fifty meters. When indoor location is available, the accuracy range can exist as small every bit five meters. Unless you know indoor location is available inside the geofence, presume that Wi-Fi location accuracy is virtually fifty meters.
When Wi-Fi location isn't available (for example, when you are driving in rural areas) the location accuracy degrades. The accurateness range can be as large as several hundred meters to several kilometers. In cases like this, you should create geofences using a larger radius.
Explain to users why your app uses geofencing
Because your app accesses location in the background when you lot use geofencing, consider how your app delivers benefits to users. Explain to them conspicuously why your app needs this admission to increase user understanding and transparency.
For more data about best practices related to location access, including geofencing, meet the privacy best practices page.
Use the dwell transition type to reduce alert spam
If you receive a large number of alerts when driving briefly past a geofence, the all-time way to reduce the alerts is to use a transition type of GEOFENCE_TRANSITION_DWELL
instead of GEOFENCE_TRANSITION_ENTER
. This manner, the habitation alert is sent merely when the user stops inside a geofence for a given menstruation of fourth dimension. You tin choose the elapsing by setting a loitering delay.
Re-annals geofences merely when required
Registered geofences are kept in the com.google.process.location
procedure endemic by the com.google.android.gms
bundle. The app doesn't need to practice anything to handle the post-obit events, because the system restores geofences later on these events:
- Google Play services is upgraded.
- Google Play services is killed and restarted by the organisation due resource brake.
- The location process crashes.
The app must re-annals geofences if they're notwithstanding needed later the following events, since the system cannot recover the geofences in the following cases:
- The device is rebooted. The app should mind for the device'south kick complete activeness, and then re- register the geofences required.
- The app is uninstalled and re-installed.
- The app'southward data is cleared.
- Google Play services data is cleared.
- The app has received a
GEOFENCE_NOT_AVAILABLE
alert. This typically happens after NLP (Android'due south Network Location Provider) is disabled.
Troubleshoot the geofence entrance event
If geofences aren't existence 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.
Hither are some possible reasons for alerts non working as expected:
- Accurate location isn't bachelor inside your geofence or your geofence is as well small. On most devices, the geofence service uses only network location for geofence triggering. The service uses this approach because network location consumes much less ability, it takes less time to get detached locations, and virtually importantly information technology's available indoors.
-
Wi-Fi is turned off on the device. Having Wi-Fi on can significantly improve the location accuracy, then 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 xviii), we added the capability of "Wi-Fi scan only mode" which allows users to disable Wi-Fi but still get good network location. Information technology's adept practice to prompt the user and provide a shortcut for the user to enable Wi-Fi or Wi-Fi browse just mode if both of them are disabled. Use SettingsClient to ensure that the device's system settings are properly configured for optimal location detection.
Notation: If your app targets Android ten (API level 29) or higher, you lot cannot call
WifiManager.setEnabled()
straight unless your app is a organization app or a device policy controller (DPC). Instead, utilize a settings panel. - There is no reliable network connectivity within your geofence. If in that location is no reliable data connection, alerts might not exist generated. This is because the geofence service depends on the network location provider which in turn requires a information connection.
- Alerts can exist 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, fifty-fifty less when the device has been moving. If Groundwork Location Limits are in consequence, the latency is about 2-3 minutes on boilerplate. If the device has been stationary for a pregnant period of time, the latency may increase (upwards to 6 minutes).
Source: https://developer.android.com/training/location/geofencing
0 Response to "How To Set Up A Geofence"
Post a Comment