Android 16 wprowadza moduł Ranging, który zapewnia ujednolicony i standardowy interfejs do precyzyjnego pomiaru odległości między urządzeniami. Za pomocą tego interfejsu API możesz mierzyć odległość i położenie urządzeń równorzędnych bez konieczności obsługi każdej technologii pomiaru odległości osobno.
Moduł Ranging obsługuje te technologie:
- łącze ultraszerokopasmowe,
- sondowanie kanału Bluetooth,
- Wi-Fi NAN RTT,
- pomiar odległości za pomocą RSSI Bluetooth.
Możliwości i dostępność pomiaru odległości
Klasa RangingManager udostępnia aplikacjom informacje o technologiach pomiaru odległości obsługiwanych przez urządzenie lokalne, a także o dostępności i możliwościach każdej technologii. Aplikacje mogą zarejestrować Callback aby
otrzymywać aktualizacje dotyczące zmian w dostępności lub możliwościach obsługiwanych technologii.
Role urządzeń
Urządzenie biorące udział w sesji pomiaru odległości musi być inicjatorem lub odbiorcą. Urządzenie inicjujące rozpoczyna sesję pomiaru odległości z co najmniej 1 urządzeniem odbiorczym. Urządzenie odbiorcze odpowiada na żądania pomiaru odległości tylko od 1 inicjatora naraz. Rolę danego urządzenia w sesji pomiaru odległości
możesz określić za pomocą klasy RangingPreference.
Typy sesji pomiaru odległości
Podczas rozpoczynania sesji pomiaru odległości między urządzeniami często konieczne jest ustanowienie transportu danych poza pasmem (OOB) w celu wymiany parametrów sesji.
Moduł Ranging może obsługiwać negocjacje OOB, ale obsługuje też niestandardowe implementacje OOB.
Domyślna implementacja OOB
W przypadku tego typu sesji (RANGING_SESSION_OOB) moduł Ranging obsługuje
negocjacje OOB w celu rozpoczęcia sesji pomiaru odległości. Wybiera odpowiednie parametry na podstawie ustawień pomiaru odległości podanych przez aplikację i używa odpowiednich technologii na podstawie tego, co obsługują oba urządzenia. Ten typ sesji
korzysta ze standardowej OOB specification.
Moduł Ranging definiuje tylko format danych OOB i sekwencję, które mają być używane do interakcji z urządzeniem równorzędnym. Nie obsługuje wykrywania urządzeń równorzędnych ani nawiązywania połączenia.
Niestandardowa implementacja OOB
W przypadku tego typu sesji (RANGING_SESSION_RAW) aplikacja pomija przepływ OOB modułu Ranging
i obsługuje własne negocjacje OOB oraz parametry. Oznacza to, że aplikacja musi określić, które technologie obsługuje urządzenie równorzędne, wynegocjować parametry pomiaru odległości i rozpocząć sesję pomiaru odległości.
Ustawienia pomiaru odległości
Użyj obiektu RangingPreference, aby określić wybrane parametry sesji pomiaru odległości. Obejmuje to:
- Rola urządzenia. Określa, czy urządzenie będzie inicjatorem czy odbiorcą.
- Konfiguracja pomiaru odległości. Obiekt
RangingConfigokreśla typ sesji pomiaru odległości i inne parametry potrzebne do rozpoczęcia sesji pomiaru odległości. - Konfiguracja sesji. Obiekt
SessionConfigokreśla parametry, które mają być wymuszane w sesji pomiaru odległości, takie jak limit pomiaru, fuzja czujników, konfiguracja geofence i inne.
Uprawnienia do pomiaru odległości
Moduł Ranging wymaga nowego ujednoliconego uprawnienia (android.permission.RANGING), aby uzyskać dostęp do wszystkich obecnych i przyszłych technologii pomiaru odległości. To uprawnienie znajduje się na liście NEARBY_DEVICES_PERMISSIONS.
<uses-permission android:name="android.permission.RANGING" />
Ograniczenia
Moduł Ranging może ograniczyć pomiar odległości z kilku powodów, w tym:
- Aplikacje innych firm mogą wykonywać pomiar odległości w tle tylko za pomocą łącza ultraszerokopasmowego i tylko na obsługiwanych urządzeniach. Pomiar odległości w tle za pomocą innych technologii jest niedozwolony.
- Pomiar odległości jest niedozwolony, gdy osiągnięto maksymalną liczbę równoczesnych sesji pomiaru odległości na urządzeniu.
- Pomiar odległości może być ograniczony ze względu na stan systemu, np. baterię, wydajność lub pamięć.
Moduł Ranging ma też te znane ograniczenia:
- Moduł Ranging obsługuje tylko dostarczanie danych pomiaru odległości do urządzeń równorzędnych za pomocą łącza ultraszerokopasmowego. W przypadku innych technologii moduł Ranging dostarcza dane pomiaru odległości tylko do urządzenia inicjującego.
- Moduł Ranging obsługuje tylko dynamiczne dodawanie urządzeń w trybie pomiaru odległości RAW i tylko w przypadku łącza ultraszerokopasmowego.
- Moduł Ranging nie obsługuje sesji łącza ultraszerokopasmowego typu „jeden do wielu” w przypadku domyślnych implementacji OOB. Jeśli przekażesz kilka uchwytów urządzeń, moduł utworzy sesję typu „jeden do jednego” dla każdego urządzenia równorzędnego, które obsługuje łącze ultraszerokopasmowe.
Przeprowadzanie sesji pomiaru odległości
Aby przeprowadzić sesję pomiaru odległości za pomocą modułu Ranging, wykonaj te czynności:
- Sprawdź, czy wszystkie urządzenia działają w Androidzie 16 lub nowszym.
- Poproś o
android.permission.RANGINGuprawnienie w pliku manifestu aplikacji. - Oceń możliwości i dostępność technologii pomiaru odległości.
- Wykryj urządzenie równorzędne do operacji pomiaru odległości.
- Ustanów połączenie do wymiany poza pasmem, używając jednego z typów sesji opisanych w sekcji Typy sesji pomiaru odległości.
- Zainicjuj pomiar odległości i ciągle pobieraj dane pomiaru odległości.
- Zakończ sesję pomiaru odległości.
Poniższy przykładowy kod pokazuje te czynności zarówno w przypadku roli inicjatora, jak i odbiorcy.
Kotlin
class RangingApp {
// Starts a ranging session on the initiator side.
fun startRangingInitiator(
context: Context,
deviceHandle: DeviceHandle,
executor: Executor,
callback: RangingSessionCallback
) {
// Get the RangingManager which is the entry point for ranging module.
val manager = context.getSystemService(RangingManager::class.java)
// Create a new RangingSession using the provided executor and callback.
val session = manager.createRangingSession(executor, callback)
// Create an OobInitiatorRangingConfig, which specifies the ranging parameters for
// the initiator role.
val config = OobInitiatorRangingConfig.Builder()
.setFastestRangingInterval(Duration.ofMillis(100))
.setSlowestRangingInterval(Duration.ofMillis(5000))
.setRangingMode(RANGING_MODE_AUTO)
.setSecurityLevel(SECURITY_LEVEL_BASIC)
.addDeviceHandle(deviceHandle)
.build()
// Create a RangingPreference, which specifies the role (initiator) and
// configuration for the ranging session.
val preference =
RangingPreference.Builder(DEVICE_ROLE_INITIATOR, config).build()
// Start ranging session.
session.start(preference)
// If successful, the ranging data will be sent through callback#onResults
// Stop ranging session
session.stop()
}
// Starts a ranging session on the responder side.
fun startRangingResponder(
context: Context,
deviceHandle: DeviceHandle,
executor: Executor,
callback: RangingSessionCallback
) {
// Get the RangingManager which is the entry point for ranging module.
val manager = context.getSystemService(RangingManager::class.java)
// Create a new RangingSession using the provided executor and callback.
val session = manager.createRangingSession(executor, callback)
// Create an OobResponderRangingConfig, which specifies the ranging parameters for
// the responder role.
val config = OobResponderRangingConfig.Builder(deviceHandle).build()
// Create a RangingPreference, which specifies the role (responder) and
// configuration for the ranging session.
val preference =
RangingPreference.Builder(DEVICE_ROLE_RESPONDER, config).build()
// Start the ranging session.
session.start(preference)
// Stop the ranging session
session.stop()
}
}
Java
public class RangingApp {
// Starts a ranging session on the initiator side.
void startRangingInitiator(Context context, DeviceHandle deviceHandle, Executor executor, RangingSessionCallback callback) {
// Get the RangingManager which is the entry point for ranging module.
RangingManager manager = context.getSystemService(RangingManager.class);
// Create a new RangingSession using the provided executor and callback.
RangingSession session = manager.createRangingSession(executor, callback);
// Create an OobInitiatorRangingConfig, which specifies the ranging parameters for
// the initiator role.
OobInitiatorRangingConfig config = new OobInitiatorRangingConfig.Builder()
.setFastestRangingInterval(Duration.ofMillis(100))
.setSlowestRangingInterval(Duration.ofMillis(5000))
.setRangingMode(RANGING_MODE_AUTO)
.setSecurityLevel(SECURITY_LEVEL_BASIC)
.addDeviceHandle(deviceHandle)
.build();
// Create a RangingPreference, which specifies the role (initiator) and
// configuration for the ranging session.
RangingPreference preference =
new RangingPreference.Builder(DEVICE_ROLE_INITIATOR, config).build();
// Start ranging session.
session.start(preference);
// If successful, the ranging data will be sent through callback#onResults
// Stop ranging session
session.stop();
}
// Starts a ranging session on the responder side.
void startRangingResponder(Context context, DeviceHandle deviceHandle, Executor executor, RangingSessionCallback callback) {
// Get the RangingManager which is the entry point for ranging module.
RangingManager manager = context.getSystemService(RangingManager.class);
// Create a new RangingSession using the provided executor and callback.
RangingSession session = manager.createRangingSession(executor, callback);
// Create an OobResponderRangingConfig, which specifies the ranging parameters for
// the responder role.
OobResponderRangingConfig config = new OobResponderRangingConfig.Builder( deviceHandle).build();
// Create a RangingPreference, which specifies the role (responder) and
// configuration for the ranging session.
RangingPreference preference =
new RangingPreference.Builder(DEVICE_ROLE_RESPONDER, config).build();
// Start the ranging session.
session.start(preference);
// Stop the ranging session
session.stop();
}
}
Współdziałanie łącza ultraszerokopasmowego z urządzeniami z iOS
Moduł Ranging obsługuje interoperacyjność z urządzeniami z iOS za pomocą łącza ultraszerokopasmowego (UWB). Aby zmierzyć odległość za pomocą urządzenia z iOS, musisz użyć niestandardowej implementacji OOB i skonfigurować sesję pomiaru odległości za pomocą określonych parametrów zgodnych z protokołem Apple Nearby Interaction Accessory Protocol. Więcej informacji znajdziesz w przykładowej aplikacji.
Podczas tworzenia RangingPreference użyj RawRangingDevice i UwbRangingParams, aby określić konfigurację. Te parametry są kluczowe dla interoperacyjności z iOS:
- Configuration ID (Identyfikator konfiguracji): użyj
UwbRangingParams.CONFIG_UNICAST_DS_TWR. - Session Key Info (Informacje o kluczu sesji): podaj tablicę bajtów zawierającą identyfikator dostawcy i statyczny STS IV.
- Complex Channel (Kanał złożony): ustaw numer kanału i indeks preambuły tak, aby pasowały do konfiguracji urządzenia z iOS.
Ten fragment kodu pokazuje, jak utworzyć RangingPreference dla urządzenia inicjującego, które mierzy odległość za pomocą odbiorcy z iOS:
Kotlin
// Create UwbRangingParams with iOS-specific configuration
val uwbRangingParams = UwbRangingParams.Builder(
sessionId,
UwbRangingParams.CONFIG_UNICAST_DS_TWR,
sourceAddress,
destinationAddress
)
.setComplexChannel(
UwbComplexChannel.Builder()
.setChannel(channelNumber)
.setPreambleIndex(preambleIndex)
.build()
)
.setRangingUpdateRate(updateRate)
.setSessionKeyInfo(sessionKeyInfo) // Vendor ID + STS IV
.setSlotDuration(slotDuration)
.build()
// Create RawRangingDevice
val rawRangingDevice = RawRangingDevice.Builder()
.setRangingDevice(RangingDevice.Builder().build())
.setUwbRangingParams(uwbRangingParams)
.build()
// Create SessionConfig
val sessionConfig = SessionConfig.Builder()
.setAngleOfArrivalNeeded(true)
.setDataNotificationConfig(DataNotificationConfig.Builder()
.setNotificationConfigType(DataNotificationConfig.NOTIFICATION_CONFIG_ENABLE)
.build())
.build()
// Create RangingPreference for the initiator
val preference = RangingPreference.Builder(
RangingPreference.DEVICE_ROLE_INITIATOR,
RawInitiatorRangingConfig.Builder()
.addRawRangingDevice(rawRangingDevice)
.build()
)
.setSessionConfig(sessionConfig)
.build()
Java
// Create UwbRangingParams with iOS-specific configuration
UwbRangingParams uwbRangingParams = new UwbRangingParams.Builder(
sessionId,
UwbRangingParams.CONFIG_UNICAST_DS_TWR,
sourceAddress,
destinationAddress)
.setComplexChannel(new UwbComplexChannel.Builder()
.setChannel(channelNumber)
.setPreambleIndex(preambleIndex)
.build())
.setRangingUpdateRate(updateRate)
.setSessionKeyInfo(sessionKeyInfo) // Vendor ID + STS IV
.setSlotDuration(slotDuration)
.build();
// Create RawRangingDevice
RawRangingDevice rawRangingDevice = new RawRangingDevice.Builder()
.setRangingDevice(new RangingDevice.Builder().build())
.setUwbRangingParams(uwbRangingParams)
.build();
// Create SessionConfig
SessionConfig sessionConfig = new SessionConfig.Builder()
.setAngleOfArrivalNeeded(true)
.setDataNotificationConfig(new DataNotificationConfig.Builder()
.setNotificationConfigType(DataNotificationConfig.NOTIFICATION_CONFIG_ENABLE)
.build())
.build();
// Create RangingPreference for the initiator
RangingPreference preference = new RangingPreference.Builder(
RangingPreference.DEVICE_ROLE_INITIATOR,
new RawInitiatorRangingConfig.Builder()
.addRawRangingDevice(rawRangingDevice)
.build())
.setSessionConfig(sessionConfig)
.build();
Interfejs UWB Downlink-TDoA API
Informacje o interfejsie UWB DL-TDoA API znajdziesz w artykule Nowości w Androidzie 17.
Przykładowa aplikacja
Aby zobaczyć kompleksowy przykład użycia modułu Ranging, zapoznaj się z przykładową aplikacją w AOSP. Ta przykładowa aplikacja obejmuje wszystkie technologie pomiaru odległości obsługiwane przez moduł Ranging oraz przepływy dla obu obsługiwanych typów sesji.
Współdziałanie łącza ultraszerokopasmowego z urządzeniami z iOS
Przykładowa aplikacja na Androida obsługuje rozpoczynanie sesji pomiaru odległości za pomocą łącza ultraszerokopasmowego z przykładową aplikacją na iOS.