您可以使用 Wi-Fi RTT (Round-Trip-Time) API 提供的 Wi-Fi 定位功能,測量與附近支援 RTT 的 Wi-Fi 存取點和對等互連 Wi-Fi Aware 裝置之間的距離。
如果您測量到三個以上的存取點之間的距離,可以使用乘法演算法預估最適合這些測量的裝置位置。結果通常在 1-2 公尺以內。
有了這項準確率,您就可以開發精細的位置相關服務,例如室內導航、清晰的語音控制 (例如「打開這個燈」),以及位置資訊 (例如「這項產品有特價優惠嗎?」)。
要求的裝置不需要連線至存取點,就能透過 Wi-Fi RTT 測量距離。為維護隱私,只有要求的裝置才能判斷到存取點之間的距離,而存取點不提供這項資訊。前景應用程式的 Wi-Fi RTT 作業沒有限制,但背景應用程式的 Wi-Fi RTT 作業會受到限制。
Wi-Fi RTT 和相關的 Fine-Time-Measurement (FTM) 功能是由 IEEE 802.11-2016 標準指定。Wi-Fi RTT 需要精確的時間測量,因為 FTM 計算封包從裝置之間往返傳輸所需的時間,並將該時間乘以光速,所以需要精確的時間測量。
依 Android 版本實作的差異
Wi-Fi RTT 是在 Android 9 (API 級別 28) 中導入。如果在搭載 Android 9 的裝置中使用這項通訊協定來決定裝置位置,您必須具備應用程式中預先決定的存取點 (AP) 位置資料的存取權。您可以自行決定如何儲存及擷取這些資料。
在搭載 Android 10 (API 級別 29) 以上版本的裝置中,AP 位置資料可以使用 ResponderLocation
物件表示,包括緯度、經度和海拔高度。針對支援位置資訊設定資訊/位置公民報告 (LCI/LCR 資料) 的 Wi-Fi RTT AP,通訊協定會在排序程序中傳回 ResponderLocation
物件。
這項功能可讓應用程式查詢 AP 並直接要求其位置,而不用事先儲存這項資訊。因此,即使 AP 先前不知道 (例如使用者進入新建築物),您的應用程式仍可尋找 AP 並判斷其位置。
相關規定
- 提出範圍要求的裝置硬體必須實作 802.11-2016 FTM 標準。
- 提出範圍要求的裝置必須搭載 Android 9 (API 級別 28) 以上版本。
- 提出範圍要求的裝置必須啟用定位服務並開啟 Wi-Fi 掃描功能 (位於「設定」>「位置」下方)。
- 如果提出範圍要求的應用程式指定 Android 13 (API 級別 33) 以上版本,則必須具備
NEARBY_WIFI_DEVICES
權限。如果這類應用程式以舊版 Android 為目標,就必須改為具備ACCESS_FINE_LOCATION
權限。 - 當應用程式可見或在前景服務時,應用程式必須查詢存取點的範圍。應用程式無法從背景存取位置資訊。
- 存取點必須採用 IEEE 802.11-2016 FTM 標準。
設定
如要將應用程式設為使用 Wi-Fi RTT,請執行下列步驟。
1. 要求權限
請在應用程式資訊清單中要求下列權限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<!-- If your app targets Android 13 (API level 33)
or higher, you must declare the NEARBY_WIFI_DEVICES permission. -->
<uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES"
<!-- If your app derives location information from Wi-Fi APIs,
don't include the "usesPermissionFlags" attribute. -->
android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"
<!-- If any feature in your app relies on precise location
information, don't include the "maxSdkVersion"
attribute. -->
android:maxSdkVersion="32" />
NEARBY_WIFI_DEVICES
和 ACCESS_FINE_LOCATION
權限是危險的權限,因此每當使用者要執行 RTT 掃描作業時,您就必須在執行階段提出要求。如果您的應用程式尚未授予權限,則應用程式必須要求使用者的權限。如要進一步瞭解執行階段權限,請參閱「要求應用程式權限」。
2. 檢查裝置是否支援 Wi-Fi RTT
如要檢查裝置是否支援 Wi-Fi RTT,請使用 PackageManager API:
Kotlin
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);
3. 檢查是否可使用 Wi-Fi 即時文字訊息
裝置上可能已有 Wi-Fi RTT,但使用者已停用 Wi-Fi,因此目前無法使用這項功能。如果裝置使用 SoftAP 或網路共用功能,則某些裝置可能不支援 Wi-Fi RTT,具體取決於其硬體和韌體功能。如要查看目前是否可使用 Wi-Fi RTT,請呼叫 isAvailable()。
Wi-Fi RTT 的可用性隨時可能變動。應用程式應註冊 BroadcastReceiver,以便接收 ACTION_WIFI_RTT_STATE_CHANGED,並在可用性變更時傳送該值。應用程式收到廣播意圖時,應用程式應檢查目前的可用性狀態,並據此調整其行為。
例如:
Kotlin
val filter = IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED) val myReceiver = object: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { if (wifiRttManager.isAvailable) { … } else { … } } } context.registerReceiver(myReceiver, filter)
Java
IntentFilter filter = new IntentFilter(WifiRttManager.ACTION_WIFI_RTT_STATE_CHANGED); BroadcastReceiver myReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (wifiRttManager.isAvailable()) { … } else { … } } }; context.registerReceiver(myReceiver, filter);
詳情請參閱「廣播」。
建立範圍要求
指定範圍要求 (RangingRequest) 清單的 AP 或 Wi-Fi Aware 對等點清單建立而成。您可在單一範圍要求中指定多個存取點或 Wi-Fi Aware 同類群組,且系統會測量並傳回所有裝置的距離。
舉例來說,要求可以使用 addAccessPoint() 方法指定用於測量距離的存取點:
Kotlin
val req: RangingRequest = RangingRequest.Builder().run { addAccessPoint(ap1ScanResult) addAccessPoint(ap2ScanResult) build() }
Java
RangingRequest.Builder builder = new RangingRequest.Builder(); builder.addAccessPoint(ap1ScanResult); builder.addAccessPoint(ap2ScanResult); RangingRequest req = builder.build();
存取點是以 ScanResult 物件識別,可透過呼叫 WifiManager.getScanResults() 取得。您可以使用 addAccessPoints(List
同樣地,範圍擴大要求可使用 addWifiAwarePeer(MacAddress peer) 和 addWifiAwarePeer(PeerHandle peer) 新增 Wi-Fi 連線的對等點。如要進一步瞭解如何探索 Wi-Fi Aware 對等互連,請參閱 Wi-Fi Aware 說明文件。
要求範圍
應用程式使用 WifiRttManager.startRanging() 方法發出範圍要求要求,並提供以下內容:使用 RangingRequest 指定作業、使用 Executor 指定回呼情境,以及使用 RangingResultCallback 接收結果。
例如:
Kotlin
val mgr = context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE) as WifiRttManager val request: RangingRequest = myRequest mgr.startRanging(request, executor, object : RangingResultCallback() { override fun onRangingResults(results: List<RangingResult>) { … } override fun onRangingFailure(code: Int) { … } })
Java
WifiRttManager mgr = (WifiRttManager) Context.getSystemService(Context.WIFI_RTT_RANGING_SERVICE); RangingRequest request ...; mgr.startRanging(request, executor, new RangingResultCallback() { @Override public void onRangingFailure(int code) { … } @Override public void onRangingResults(List<RangingResult> results) { … } });
測距作業會以非同步方式執行,而範圍結果會在 RangingResultCallback 的其中一個回呼中傳回:
- 如果整個範圍作業失敗,系統會透過 RangingResultCallback 中所述的狀態碼觸發 onRangingFailure 回呼。如果服務無法同時執行範圍運算,例如因為應用程式要求太多範圍作業、受到限縮,或是因為權限問題等原因,導致 Wi-Fi 停用,就可能會發生這類失敗。
- 範圍作業完成後,系統會觸發 onRangingResults 回呼,並取得與要求清單相符的結果清單,也就是每項要求各有一個結果。結果的順序與要求的順序不相符。請注意,測距作業可能已完成,但每項結果可能仍代表該特定測量作業失敗。
解讀測距結果
onRangingResults 回呼所傳回的每個結果都是由 RangingResult 物件指定。請針對每個要求執行下列操作。
1. 辨別要求
根據建立 RangingRequest 時提供的資訊識別要求:通常 ScanResult
中提供的 MAC 位址,用於識別存取點。可使用 getMacAddress() 方法從測得結果中取得 MAC 位址。
範圍結果清單的順序可能會與範圍要求中指定的對等點 (存取點) 不同,因此建議您使用 MAC 位址來識別對等點,而非結果順序。
2. 判斷每項評估是否成功
如要判斷測量是否成功,請使用 getStatus() 方法。STATUS_SUCCESS 以外的任何值都表示失敗。失敗代表此結果的所有其他欄位 (上述要求識別除外) 無效,對應的 get*
方法也會失敗,並顯示 IllegalStateException 例外狀況。
3. 取得每項成功的評估結果
針對每項成功的測量,您可以使用相應的 get
方法擷取結果值:
距離 (以公釐為單位),以及測量的標準差:
用於測量的封包 RSSI:
測量時間 (以毫秒為單位) (表示啟動後的時間):
嘗試的測量次數和成功的測量次數 (以及距離測量的基礎):
支援 Wi-RTT 的 Android 裝置
下表列出一些支援 Wi-RTT 的手機、存取點,以及零售、倉儲和配送中心裝置。然而,這些資訊還不夠全面。建議您與我們聯絡,在此處列出支援 RTT 的產品。
存取點
製造商和型號 | 支援日期 |
---|---|
Nest Wifi Pro (Wi-Fi 6E) | 有權限 |
Compulab WILD AP | 有權限 |
Google Wi-Fi | 有權限 |
Google Nest Wi-Fi 路由器 | 有權限 |
Google Nest Wi-Fi Point | 有權限 |
阿魯巴 AP-635 | 有權限 |
思科 9130 | 有權限 |
Cisco 9136 | 有權限 |
Cisco 9166 | 有權限 |
Cisco 9164 | 有權限 |
阿魯巴 AP-505 | 有權限 |
阿魯巴 AP-515 | 有權限 |
阿魯巴 AP-575 | 有權限 |
阿魯巴 AP-518 | 有權限 |
阿魯巴 AP-505H | 有權限 |
阿魯巴 AP-565 | 有權限 |
阿魯巴 AP-535 | 有權限 |
手機
製造商和型號 | Android 版本 |
---|---|
Pixel 6 | 9.0 以上版本 |
Pixel 6 Pro | 9.0 以上版本 |
Pixel 5 | 9.0 以上版本 |
Pixel 5a | 9.0 以上版本 |
Pixel 5a (5G) | 9.0 以上版本 |
小米 Mi 10 Pro | 9.0 以上版本 |
小米 Mi 10 | 9.0 以上版本 |
小米 Redmi Mi 9T Pro | 9.0 以上版本 |
小米 Mi 9T | 9.0 以上版本 |
小米 Mi 9 | 9.0 以上版本 |
Xiaomi Mi Note 10 | 9.0 以上版本 |
Xiaomi Mi Note 10 Lite | 9.0 以上版本 |
小米 Redmi Note 9S | 9.0 以上版本 |
Xiaomi Redmi Note 9 Pro | 9.0 以上版本 |
小米 Redmi Note 8T | 9.0 以上版本 |
小米 Redmi Note 8 | 9.0 以上版本 |
小米 Redmi K30 Pro | 9.0 以上版本 |
小米 Redmi K20 Pro | 9.0 以上版本 |
小米 Redmi K20 | 9.0 以上版本 |
小米 Redmi Note 5 Pro | 9.0 以上版本 |
小米 Mi CC9 Pro | 9.0 以上版本 |
LG G8X ThinQ | 9.0 以上版本 |
LG V50S ThinQ | 9.0 以上版本 |
LG V60 ThinQ | 9.0 以上版本 |
LG V30 | 9.0 以上版本 |
Samsung Galaxy Note 10+ 5G | 9.0 以上版本 |
Samsung Galaxy S20+ 5G | 9.0 以上版本 |
Samsung Galaxy S20 以上版本 | 9.0 以上版本 |
Samsung Galaxy S20 5G | 9.0 以上版本 |
Samsung Galaxy S20 Ultra 5G | 9.0 以上版本 |
Samsung Galaxy S20 | 9.0 以上版本 |
Samsung Galaxy Note 10 以上版本 | 9.0 以上版本 |
Samsung Galaxy Note 10 5G | 9.0 以上版本 |
Samsung Galaxy Note 10 | 9.0 以上版本 |
Samsung A9 Pro | 9.0 以上版本 |
Google Pixel 4 XL | 9.0 以上版本 |
Google Pixel 4 | 9.0 以上版本 |
Google Pixel 4a | 9.0 以上版本 |
Google Pixel 3 XL | 9.0 以上版本 |
Google Pixel 3 | 9.0 以上版本 |
Google Pixel 3a XL | 9.0 以上版本 |
Google Pixel 3a | 9.0 以上版本 |
Google Pixel 2 XL | 9.0 以上版本 |
Google Pixel 2 | 9.0 以上版本 |
Google Pixel 1 XL | 9.0 以上版本 |
Google Pixel 1 | 9.0 以上版本 |
Poco X2 | 9.0 以上版本 |
Sharp Aquos R3 SH-04L | 9.0 以上版本 |
零售、倉儲與配送中心裝置
製造商和型號 | Android 版本 |
---|---|
PS20 斑馬 | 10.0 以上版本 |
Zebra TC52/TC52HC | 10.0 以上版本 |
Zebra TC57 | 10.0 以上版本 |
Zebra TC72 | 10.0 以上版本 |
Zebra TC77 | 10.0 以上版本 |
Zebra MC93 | 10.0 以上版本 |
Zebra TC8300 | 10.0 以上版本 |
Zebra VC8300 | 10.0 以上版本 |
Zebra EC30 | 10.0 以上版本 |
Zebra ET51 | 10.0 以上版本 |
Zebra ET56 | 10.0 以上版本 |
Zebra L10 | 10.0 以上版本 |
Zebra CC600/CC6000 | 10.0 以上版本 |
Zebra MC3300x | 10.0 以上版本 |
Zebra MC330x | 10.0 以上版本 |
Zebra TC52x | 10.0 以上版本 |
Zebra TC57x | 10.0 以上版本 |
Zebra EC50 (LAN 和 HC) | 10.0 以上版本 |
Zebra EC55 (WAN) | 10.0 以上版本 |
Zebra WT6300 | 10.0 以上版本 |
Skorpio X5 | 10.0 以上版本 |