您可以使用 Wi-Fi RTT (Round-Trip-Time) API 提供的 Wi-Fi 定位功能,測量與附近支援 RTT 的 Wi-Fi 存取點和對等互連 Wi-Fi Aware 裝置之間的距離。
如果您測量到三個以上存取點之間的距離,可以使用乘法演算法來估算最適合這些測量的裝置位置。測量結果通常在 1 到 2 公尺以內。
有了這種精確度,您可以開發精細的適地性服務,例如室內導航、消歧義 (例如「打開這個燈」) 和根據位置資訊 (例如「這項產品有特價優惠嗎?」) 等位置資訊。
提出要求的裝置不需要連線到存取點即可測量使用 Wi-Fi RTT 的距離。為維護隱私,只有提出要求的裝置才能判斷與存取點之間的距離,存取點則沒有這項資訊。對於前景應用程式,Wi-Fi RTT 作業沒有上限,但對背景應用程式而言,系統會節流作業。
IEEE 802.11-2016 標準會指定 Wi-Fi RTT 和相關的 Fine-Time-Measurement (FTM) 功能。Wi-Fi RTT 需要 FTM 提供精準的時間測量,因為它會測量封包在裝置之間來回往返的時間,並將時間乘以光速,藉此計算兩部裝置之間的距離。
各 Android 版本的實作差異
Android 9 (API 級別 28) 已導入 Wi-Fi RTT。如果在搭載 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 即時文字訊息
如要檢查裝置是否支援 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);
詳情請參閱廣播的相關說明。
建立測距要求
透過指定要求範圍的 AP 或 Wi-Fi Aware 對等點清單,建立範圍劃分要求 (RangingRequest)。在單一測距要求中指定多個存取點或 Wi-Fi 感知對等項目,系統會測量並傳回所有裝置的距離。
舉例來說,要求可以使用 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 對等點) 和 addWifiAwarePeer(對等對等互連) 方法,透過其 MAC 位址或 PeerHandle 新增 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 裝置
下表列出部分支援 WiFi-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 | 有權限 |
思科 9136 | 有權限 |
思科 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 以上版本 |
小米 Mi Note 10 | 9.0 以上版本 |
小米 Mi Note 10 Lite | 9.0 以上版本 |
Xiaomi Redmi Note 9S | 9.0 以上版本 |
Xiaomi Redmi Note 9 Pro | 9.0 以上版本 |
Xiaomi Redmi Note 8T | 9.0 以上版本 |
Xiaomi 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 以上版本 |
夏普 Aquos R3 SH-04L | 9.0 以上版本 |
零售、倉儲與配送中心裝置
製造商和型號 | Android 版本 |
---|---|
賽布拉 PS20 (PS20) | 10.0 以上版本 |
Zebra TC52/TC52HC | 10.0 以上版本 |
Zebra TC57 | 10.0 以上版本 |
Zebra TC72 | 10.0 以上版本 |
Zebra TC77 | 10.0 以上版本 |
斑馬 MC93 | 10.0 以上版本 |
Zebra TC8300 | 10.0 以上版本 |
Zebra VC8300 | 10.0 以上版本 |
斑馬 EC30 | 10.0 以上版本 |
斑馬 ET51 | 10.0 以上版本 |
斑馬 ET56 | 10.0 以上版本 |
賽布拉第 10 級 | 10.0 以上版本 |
薩布拉 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 以上版本 |
澤布拉 WT6300 | 10.0 以上版本 |
Skorpio X5 | 10.0 以上版本 |