In the Awareness API, the concept of fences is taken from geofencing, in which a geographic region, or geofence, is defined, and an app receives callbacks when a user enters or leaves the geofence region. The Fence API expands on the concept of geofencing to include many other context conditions in addition to geographical proximity. An app receives callbacks whenever the context state transitions. For example, if your app defines a fence for headphones, it gets callbacks when the headphones are plugged in and when they're unplugged.
You can use the Fence API to define fences based on context signals, such as the following:
- The user's current location (latitude/longitude)
- The user's current activity, like walking or driving.
- Device-specific conditions, such as whether the headphones are plugged in.
- Proximity to nearby beacons
The Fence API lets you combine multiple
context signals
to create fences with AND
, OR
, and NOT
boolean operators. Your app then
receives callbacks whenever the fence conditions are met. Some examples of
possible fences include the following:
- User plugs in headphones and starts to walk.
- User enters a 100-meter geofence before 5 PM on a weekday.
- User enters range of a specific BLE beacon.
The following example shows how to define a fence that activates whenever the user walks:
AwarenessFence walkingFence = DetectedActivityFence.during(DetectedActivityFence.WALKING);
Once you've defined a fence, you must do the following:
- Call
updateFences
to register the fence to receive callbacks. - Define a callback that can be invoked when the fence state changes.
The following example shows a method that creates and registers a fence. In
this example, a custom subclass of BroadcastReceiver
is used to handle the
intent when the fence is triggered.
Awareness.getFenceClient(this).updateFences(new FenceUpdateRequest.Builder()
.addFence(FENCE_KEY, exercisingWithHeadphonesFence, mPendingIntent)
.build())
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Log.i(TAG, "Fence was successfully registered.");
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.e(TAG, "Fence could not be registered: " + e);
}
});
public class FenceReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
FenceState fenceState = FenceState.extract(intent);
if (TextUtils.equals(fenceState.getFenceKey(), FENCE_KEY)) {
String fenceStateStr;
switch (fenceState.getCurrentState()) {
case FenceState.TRUE:
fenceStateStr = "true";
break;
case FenceState.FALSE:
fenceStateStr = "false";
break;
case FenceState.UNKNOWN:
fenceStateStr = "unknown";
break;
default:
fenceStateStr = "unknown value";
}
mLogFragment.getLogView().println("Fence state: " + fenceStateStr);
}
}
}