public final class Ranging
- Object
- Ranging
Precision ranging: how far away another device is, and in which direction.
This is ultra-wideband ranging – Apple’s Nearby Interaction on iOS and Jetpack UWB on Android – which measures distance by timing a radio round trip rather than by guessing from signal strength. Where an RSSI estimate off a Bluetooth advertisement is worth a few meters on a good day, UWB is worth about ten centimeters, and on hardware with multiple antennas it also reports which way the peer is.
The shape of a session
Both platforms need the two devices to exchange a token over some channel they already share before any radio ranging can begin, so the API is in two steps and there is no way to collapse them:
if (!Ranging.isSupported()) {
return; // no UWB radio on this device
}
Ranging.prepareSession(RangingRole.CONTROLLER).onResult((session, err) -> {
if (err != null) {
return;
}
// 1. publish our token however the two apps already talk --
// a GATT characteristic from com.codename1.bluetooth is typical
characteristic.writeValue(session.getLocalToken().toByteArray());
// 2. when theirs arrives, start ranging
session.addRangingListener(new RangingAdapter() {
public void updated(RangingUpdate u) {
if (u.hasDistance()) {
label.setText(Math.round(u.getDistance(RangingUnit.CENTIMETERS)) + " cm");
}
}
});
session.start(RangingToken.fromByteArray(theirToken));
});
A session ranges exactly one peer. That is a hard limit of Apple’s
NINearbyPeerConfiguration rather than a simplification, so an app that
tracks several peers prepares several sessions – which is also what the
Android port does under the hood.
Threading
Every callback here – AsyncResource results and every
RangingListener method – is delivered on the EDT.
Platform support
- iOS – Nearby Interaction on devices with a U1 or newer chip (iPhone 11 and later). Peer and accessory ranging, direction where the hardware provides it. Not available on tvOS, watchOS or Mac Catalyst.
- Android – Jetpack UWB on devices that report the UWB hardware
feature. Peer ranging natively; an accessory is ranged by building a
token with
RangingToken.forUwbAddress. - Simulator, desktop and JavaScript – a simulated implementation
with peers that really move, so ranging UI is developable without
hardware. Reports
NearbyAvailability.LOCAL_ONLY. - Every other port –
isSupported()isfalseand every call fails withNearbyError.NOT_SUPPORTED.
Methods
public static boolean isSupported() | true when this port and this device can range at all. |
public static NearbyAvailability getAvailability() | How usable ranging is at this moment, which is a different question from isSupported(): a phone with a U1 chip whose owner denied the permission is supported and unavailable. |
public static RangingCapabilities getCapabilities() | What this device can actually measure. |
public static AsyncResource<Boolean> requestPermissions(NearbyPermission... permissions) | Asks for the runtime permissions ranging needs. |
public static AsyncResource<RangingSession> prepareSession(RangingRole role) | Allocates a ranging session and, with it, the local token to publish to the peer. |
Inherited methods
Method details
isSupported
public static boolean isSupported()true when this port and this device can range at all.
This answers for the hardware, not for whether a peer is nearby. It
is the query to hide a feature on; use getAvailability() to tell
a user why a supported feature is not working right now.
getAvailability
public static NearbyAvailability getAvailability()isSupported(): a phone with a U1 chip whose owner denied the
permission is supported and unavailable.Returns
getCapabilities
public static RangingCapabilities getCapabilities()RangingCapabilities.UNSUPPORTED, whose every query
is false.Returns
requestPermissions
public static AsyncResource<Boolean> requestPermissions(NearbyPermission... permissions)Asks for the runtime permissions ranging needs.
Safe to call on every platform: a port with nothing to ask for
resolves true without showing anything.
Parameters
permissionsNearbyPermission...- what the app intends to do
Returns
true when every requested permission is grantedprepareSession
public static AsyncResource<RangingSession> prepareSession(RangingRole role)RangingSession.start once the peer’s token arrives.Parameters
roleRangingRole- which end of the session this device is. Ignored on platforms that negotiate roles themselves, but pick one anyway: Android needs exactly one controller.
Returns
NearbyException