Fence API overview

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 this 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 will get 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 (lat/lng)
  • The user's current activity (walking, driving, etc.)
  • 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:

  • User plugs in headphones and starts walking.
  • 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 is walking:

AwarenessFence walkingFence = DetectedActivityFence.during(DetectedActivityFence.WALKING);

Once you have 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);
        }
    }
}