Android 16 wprowadza moduł Ranging, który zapewnia ujednolicony i standardowy interfejs do precyzyjnego określania odległości między urządzeniami. Za pomocą tego interfejsu API możesz mierzyć odległość i pozycję urządzeń w pobliżu bez konieczności obsługiwania poszczególnych technologii pomiaru odległości.
Moduł Ranging obsługuje te technologie:
- Łącze ultraszerokopasmowe
- Sondowanie kanału Bluetooth
- Wi-Fi NAN RTT
- Określanie zasięgu 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 z nich. Aplikacje mogą zarejestrować się w Callback, aby otrzymywać aktualizacje dotyczące zmian w dostępności lub możliwości dowolnych obsługiwanych technologii.
Role urządzenia
Urządzenie biorące udział w sesji pomiaru odległości musi być inicjatorem lub odpowiadającym. Urządzenie inicjujące rozpoczyna sesję pomiaru odległości z 1 lub większą liczbą urządzeń odpowiadających. Urządzenie odpowiadające odpowiada na żądania pomiaru odległości tylko jednego inicjatora naraz. Rolę danego urządzenia w sesji pomiaru odległości możesz określić za pomocą klasy RangingPreference.
Typy sesji pomiarowych
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 tym typie sesji (RANGING_SESSION_OOB) moduł Ranging obsługuje negocjacje OOB w celu rozpoczęcia sesji pomiaru odległości. Wybiera odpowiednie parametry na podstawie preferencji dotyczących pomiaru odległości podanych przez aplikację i korzysta z odpowiednich technologii w zależności od tego, co obsługują oba urządzenia. Ten typ sesji korzysta ze standardowego OOB specification.
Moduł Ranging określa 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ń w pobliżu ani nawiązywania połączenia.
Niestandardowa implementacja OOB
W tym typie sesji (RANGING_SESSION_RAW) aplikacja pomija proces OOB modułu Ranging i samodzielnie obsługuje negocjacje i parametry OOB. Oznacza to, że aplikacja musi określić, jakie technologie obsługuje urządzenie w pobliżu, wynegocjować parametry pomiaru odległości i rozpocząć sesję pomiaru.
Ustawienia pomiaru odległości
Użyj obiektu RangingPreference, aby określić wybrane parametry sesji pomiarowej. między innymi na następujące działania:
- 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 jej rozpoczęcia. - Konfiguracja sesji Obiekt
SessionConfigokreśla parametry, które mają być stosowane w sesji pomiaru odległości, takie jak limit pomiaru, fuzja czujników, konfiguracja geofencingu i inne.
Uprawnienia do pomiaru odległości
Moduł pomiaru odległości wymaga nowego, ujednoliconego uprawnienia (android.permission.RANGING), aby mieć 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ł pomiaru odległości może ograniczać pomiar z kilku powodów, w tym:
- Aplikacje innych firm mogą wykonywać pomiary w tle tylko za pomocą technologii UWB i tylko na obsługiwanych urządzeniach. Określanie odległości w tle za pomocą innych technologii jest niedozwolone.
- Określanie odległości jest niedozwolone, gdy osiągnięto maksymalną liczbę równoczesnych sesji określania odległości na urządzenie.
- Zakres może być ograniczony ze względu na stan systemu, np. baterię, wydajność lub pamięć.
Moduł pomiaru odległości ma też te znane ograniczenia:
- Moduł pomiaru odległości obsługuje tylko przesyłanie danych pomiaru odległości do urządzeń równorzędnych w przypadku ultraszerokopasmowego. W przypadku innych technologii moduł pomiaru odległości dostarcza dane o odległości tylko do urządzenia inicjującego.
- Moduł pomiaru odległości obsługuje tylko dynamiczne dodawanie urządzeń w trybie pomiaru odległości w formacie surowym i tylko w przypadku technologii UWB.
- Moduł Ranging nie obsługuje sesji ultraszerokopasmowych typu „jeden do wielu” w przypadku domyślnych implementacji OOB. Jeśli przekażesz kilka uchwytów urządzeń, moduł utworzy sesję 1:1 dla każdego urządzenia równorzędnego, które obsługuje technologię UWB.
Przeprowadzanie sesji pomiarowej
Aby przeprowadzić sesję pomiaru odległości za pomocą modułu Ranging, wykonaj te czynności:
- Sprawdź, czy wszystkie urządzenia działają na Androidzie 16 lub nowszym.
- Poproś o
android.permission.RANGINGuprawnienia w pliku manifestu aplikacji. - Ocena możliwości i dostępności technologii pomiaru odległości.
- Wykrywanie urządzenia równorzędnego do pomiarów odległości.
- Nawiąż połączenie w celu wymiany danych poza pasmem, korzystając z jednego z typów sesji opisanych w sekcji Typy sesji pomiarowych.
- Rozpocznij pomiar odległości i ciągle zbieraj dane o odległości.
- Zakończ sesję pomiaru odległości.
Poniższy przykładowy kod pokazuje te kroki w przypadku roli inicjatora i roli odpowiadającego.
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 UWB z urządzeniami z iOS
Moduł Ranging obsługuje współdziałanie z urządzeniami z iOS za pomocą łącza ultraszerokopasmowego (UWB). Aby określić odległość za pomocą urządzenia z iOS, musisz użyć niestandardowej implementacji OOB i skonfigurować sesję określania odległości za pomocą określonych parametrów, które są zgodne z protokołem akcesoriów Apple Nearby Interaction. W celu uzyskania dodatkowych informacji zapoznaj się z przykładową aplikacją.
Podczas tworzenia elementu RangingPreference użyj elementów RawRangingDevice i UwbRangingParams, aby określić konfigurację. Te parametry są kluczowe dla interoperacyjności z iOS:
- Identyfikator konfiguracji: użyj
UwbRangingParams.CONFIG_UNICAST_DS_TWR. - Informacje o kluczu sesji: podaj tablicę bajtów zawierającą identyfikator dostawcy i statyczny wektor inicjujący STS.
- Złożony kanał: ustaw numer kanału i indeks preambuły tak, aby pasowały do konfiguracji urządzenia z iOS.
Poniższy fragment kodu pokazuje, jak utworzyć RangingPreference na potrzeby określania odległości od urządzenia inicjującego za pomocą urządzenia odpowiadającego 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();
UWB Downlink-TDoA API
Informacje o interfejsie UWB DL-TDoA API znajdziesz w artykule Nowe funkcje Androida 17.
Przykładowa aplikacja
Kompletny przykład użycia modułu Ranging znajdziesz w przykładowej aplikacji w AOSP. Ta przykładowa aplikacja obejmuje wszystkie technologie pomiaru odległości obsługiwane przez moduł Ranging i zawiera przepływy dla obu obsługiwanych typów sesji.
Współdziałanie UWB z urządzeniami z iOS
Przykładowa aplikacja na Androida obsługuje rozpoczynanie sesji pomiaru odległości UWB za pomocą przykładowej aplikacji na iOS.