Android 16 引進了測距模組,可提供統一且標準化的介面,用於裝置之間的測距。您可以使用這個 API 途徑來測量對等裝置的距離和位置,而不需要個別處理每種測距技術。
測距模組支援下列技術:
- 超寬頻
- 藍牙通道測試
- Wi-Fi NAN RTT
- 藍牙 RSSI 測距
測距功能和可用性
RangingManager
類別會向應用程式提供本機裝置支援的測距技術相關資訊,以及每項技術的可用性和功能。應用程式可以註冊 Callback
,以便接收任何支援技術的供應情形或功能變更的更新。
裝置角色
參與測距工作階段的裝置必須是發起端或回應端。啟動裝置會與一或多個回應裝置啟動測距工作階段。回應裝置一次只回應來自單一啟動端的測距要求。您可以使用 RangingPreference
類別,在測距工作階段中指定特定裝置的角色。
測試工作階段類型
在裝置之間啟動測距工作階段時,通常需要建立非頻道 (OOB) 資料傳輸,以便交換工作階段的參數。
測距模組可處理 OOB 協商,但也支援自訂 OOB 實作。

預設 OOB 實作
在這個工作階段類型 (RANGING_SESSION_OOB
) 中,測距模組會處理 OOB 協商,以便啟動測距工作階段。它會根據應用程式提供的測距偏好設定,選取合適的參數,並根據兩部裝置支援的技術,使用適當的技術。這個工作階段類型使用標準化的 OOB specification
。
測距模組只會定義用於與對等裝置互動的 OOB 資料格式和序列。不會處理對等裝置探索或連線建立作業。
自訂 OOB 實作
在這個工作階段類型 (RANGING_SESSION_RAW
) 中,應用程式會略過 Ranging 模組的 OOB 流程,並處理自己的 OOB 協商和參數。也就是說,應用程式必須判斷對等裝置支援哪些技術、協商測距參數,並開始測距工作階段。
排序偏好設定
使用 RangingPreference
物件,指定測距工作階段所需的參數。此時你應該可以執行下列操作:
- 裝置角色。這表示裝置是發起端還是回應端。
- 測距設定。
RangingConfig
物件會指定測距工作階段類型,以及啟動測距工作階段所需的其他參數。 - 工作階段設定。
SessionConfig
物件會指定要對測距工作階段強制執行的參數,例如測量限制、感應器融合、地理邊界設定等等。
測距權限
測距模組需要新的統一權限 (android.permission.RANGING
),才能存取所有現有和未來的測距技術。這個權限位於 NEARBY_DEVICES_PERMISSIONS
清單中。
<uses-permission android:name="android.permission.RANGING" />
限制
測距模組可能會因多種原因而限制測距,包括:
- 第三方應用程式只能在支援的裝置上,使用超寬頻技術執行背景測距。不允許使用其他技術在背景執行測距。
- 當裝置的並行測距工作階段數量已達上限時,系統就不會允許測距。
- 由於電池、效能或記憶體等系統健康問題,可能會限制測距功能。
測距模組也有下列已知限制:
- 測距模組僅支援將測距資料傳送至超寬頻的對等裝置。對於其他技術,測距模組只會將測距資料傳送至啟動裝置。
- 測距模組僅支援在原始測距模式下動態新增裝置,且僅限超寬頻。
- 測距模組不支援預設 OOB 實作的一對多超寬頻工作階段。如果您傳入多個裝置句柄,模組會為每部支援超寬頻的對等裝置建立一對一的工作階段。
進行測距工作階段
如要使用測距模組進行測距工作階段,請按照下列步驟操作:
- 確認所有裝置皆搭載 Android 16 以上版本。
- 在應用程式資訊清單中要求
android.permission.RANGING
權限。 - 評估各種技術的功能和可用性。
- 探索用於測距作業的對等裝置。
- 使用「Ranging 工作階段類型」一節所述的任一工作階段類型,為頻外交換建立連線。
- 啟動測距功能,並持續取得測距資料。
- 終止測距工作階段。
以下程式碼範例會示範發起者角色和回應者角色的這些步驟。
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();
}
}
範例應用程式
如需使用測距模組的端對端範例,請參閱 AOSP 中的範例應用程式。這個範例應用程式涵蓋 Ranging 模組支援的所有測距技術,並包含兩種支援的工作階段類型的流程。