Vị trí Wi-Fi: phạm vi có RTT

Bạn có thể sử dụng chức năng vị trí Wi-Fi do Wi-Fi RTT (Round-Trip-Time) API cung cấp để đo khoảng cách đến các điểm truy cập Wi-Fi có hỗ trợ RTT và các thiết bị Wi-Fi Aware ngang hàng ở gần.

Nếu đo khoảng cách đến ba điểm truy cập trở lên, bạn có thể sử dụng một thuật toán đa giác để ước tính vị trí thiết bị phù hợp nhất với các phép đo đó. Kết quả thường chính xác trong phạm vi 1 đến 2 mét.

Với độ chính xác này, bạn có thể phát triển các dịch vụ dựa trên vị trí chi tiết, chẳng hạn như điều hướng trong nhà, điều khiển bằng giọng nói rõ ràng (ví dụ: "Bật đèn này") và thông tin dựa trên vị trí (ví dụ: "Có ưu đãi đặc biệt nào cho sản phẩm này không?").

Thiết bị yêu cầu không cần kết nối với các điểm truy cập để đo khoảng cách bằng Wi-Fi RTT. Để bảo vệ quyền riêng tư, chỉ thiết bị yêu cầu mới có thể xác định khoảng cách đến điểm truy cập; các điểm truy cập không có thông tin này. Các thao tác RTT Wi-Fi không bị giới hạn đối với ứng dụng trên nền trước nhưng bị điều tiết đối với ứng dụng ở chế độ nền.

RTT Wi-Fi và các tính năng Đo lường thời gian chính xác (FTM) liên quan được quy định theo tiêu chuẩn IEEE 802.11-2016. Wi-Fi RTT yêu cầu thông tin đo lường thời gian chính xác do FTM cung cấp vì tính năng này tính toán khoảng cách giữa hai thiết bị bằng cách đo lường thời gian một gói tin cần để thực hiện một hành trình trọn vòng giữa các thiết bị và nhân thời gian đó với tốc độ ánh sáng.

Android 15 (API cấp 35) đã ra mắt tính năng hỗ trợ phạm vi dựa trên không kích hoạt (NTB) IEEE 802.11az.

Sự khác biệt về cách triển khai dựa trên phiên bản Android

RTT Wi-Fi được giới thiệu trong Android 9 (API cấp 28). Khi sử dụng giao thức này để xác định vị trí của thiết bị bằng cách sử dụng phương pháp đa giác với các thiết bị chạy Android 9, bạn cần có quyền truy cập vào dữ liệu vị trí điểm truy cập (AP) được xác định trước trong ứng dụng. Bạn có thể quyết định cách lưu trữ và truy xuất dữ liệu này.

Trên các thiết bị chạy Android 10 (API cấp 29) trở lên, dữ liệu vị trí của AP có thể được biểu thị dưới dạng đối tượng ResponderLocation, bao gồm vĩ độ, kinh độ và độ cao. Đối với các AP Wi-Fi RTT hỗ trợ Thông tin cấu hình vị trí/Báo cáo vị trí công cộng (dữ liệu LCI/LCR), giao thức sẽ trả về một đối tượng ResponderLocation trong quá trình định khoảng cách.

Tính năng này cho phép ứng dụng truy vấn AP để yêu cầu AP cung cấp vị trí của chúng trực tiếp thay vì cần lưu trữ thông tin này trước. Vì vậy, ứng dụng của bạn có thể tìm thấy các AP và xác định vị trí của chúng ngay cả khi trước đây không biết các AP đó, chẳng hạn như khi người dùng bước vào một toà nhà mới.

Tính năng hỗ trợ đo khoảng cách NTB IEEE 802.11az có trên các thiết bị chạy Android 15 (API cấp 35) trở lên. Điều đó có nghĩa là nếu thiết bị hỗ trợ chế độ trình khởi tạo NTB IEEE 802.11az (được biểu thị bằng WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR), thì ứng dụng của bạn có thể tìm thấy cả các AP có khả năng hỗ trợ IEEE 802.11mc và IEEE 802.11az bằng một yêu cầu phạm vi duy nhất. API RangingResult đã được mở rộng để cung cấp thông tin về giá trị tối thiểu và tối đa có thể được sử dụng cho khoảng thời gian giữa các phép đo phạm vi, để lại khoảng thời gian chính xác trong quyền kiểm soát của ứng dụng.

Yêu cầu

  • Phần cứng của thiết bị đưa ra yêu cầu đo khoảng cách phải triển khai tiêu chuẩn FTM 802.11-2016 hoặc tiêu chuẩn 802.11az (đo khoảng cách không dựa trên điều kiện kích hoạt).
  • Thiết bị đưa ra yêu cầu đo khoảng cách phải chạy Android 9 (API cấp 28) trở lên. Tính năng đo khoảng cách dựa trên không kích hoạt IEEE 802.11az được bật trên các thiết bị chạy Android 15 (API cấp 35) trở lên.
  • Thiết bị đưa ra yêu cầu đo khoảng cách phải bật dịch vụ vị trí và bật tính năng quét Wi-Fi (trong phần Cài đặt > Vị trí).
  • Nếu ứng dụng đang thực hiện yêu cầu đo khoảng cách nhắm đến Android 13 (API cấp 33) trở lên, thì ứng dụng đó phải có quyền NEARBY_WIFI_DEVICES. Nếu nhắm đến một phiên bản Android cũ hơn, thì ứng dụng đó phải có quyền ACCESS_FINE_LOCATION.
  • Ứng dụng phải truy vấn phạm vi điểm truy cập trong khi ứng dụng hiển thị hoặc trong một dịch vụ trên nền trước. Ứng dụng không thể truy cập thông tin vị trí ở chế độ nền.
  • Điểm truy cập phải triển khai tiêu chuẩn FTM IEEE 802.11-2016 hoặc tiêu chuẩn IEEE 802.11az (đo khoảng cách không dựa trên điều kiện kích hoạt).

Thiết lập

Để thiết lập ứng dụng sử dụng Wi-Fi RTT, hãy thực hiện các bước sau.

1. Yêu cầu cấp quyền

Yêu cầu các quyền sau trong tệp kê khai của ứng dụng:

<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" />

Quyền NEARBY_WIFI_DEVICESACCESS_FINE_LOCATION là các quyền có mức độ bảo vệ nguy hiểm, vì vậy, bạn cần yêu cầu các quyền này trong thời gian chạy mỗi khi người dùng muốn thực hiện thao tác quét RTT. Ứng dụng của bạn sẽ cần yêu cầu người dùng cấp quyền nếu quyền này chưa được cấp. Để biết thêm thông tin về quyền khi bắt đầu chạy, hãy xem phần Yêu cầu quyền cho ứng dụng.

2. Kiểm tra xem thiết bị có hỗ trợ Wi-Fi RTT hay không

Để kiểm tra xem thiết bị có hỗ trợ Wi-Fi RTT hay không, hãy sử dụng API PackageManager:

Kotlin

context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)

Java

context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_RTT);

3. Kiểm tra xem có Wi-Fi RTT hay không

Wi-Fi RTT có thể tồn tại trên thiết bị nhưng có thể không hoạt động vì người dùng đã tắt Wi-Fi. Tuỳ thuộc vào khả năng phần cứng và phần mềm, một số thiết bị có thể không hỗ trợ Wi-Fi RTT nếu đang sử dụng SoftAP hoặc tính năng chia sẻ Internet. Để kiểm tra xem có thể sử dụng Wi-Fi RTT hay không, hãy gọi isAvailable().

Phạm vi cung cấp Wi-Fi RTT có thể thay đổi bất cứ lúc nào. Ứng dụng của bạn phải đăng ký BroadcastReceiver để nhận ACTION_WIFI_RTT_STATE_CHANGED. Lệnh này được gửi khi phạm vi cung cấp thay đổi. Khi nhận được ý định truyền tin, ứng dụng của bạn sẽ kiểm tra trạng thái hiện tại của tính năng này và điều chỉnh hành vi cho phù hợp.

Ví dụ:

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);

Để biết thêm thông tin, hãy xem phần Thông báo truyền tin.

Tạo yêu cầu đo khoảng cách

Yêu cầu đo khoảng cách (RangingRequest) được tạo bằng cách chỉ định danh sách các AP hoặc thiết bị ngang hàng có tính năng Wi-Fi Aware mà bạn yêu cầu đo khoảng cách. Bạn có thể chỉ định nhiều điểm truy cập hoặc thiết bị ngang hàng có tính năng Wi-Fi Aware trong một yêu cầu đo khoảng cách; khoảng cách đến tất cả thiết bị sẽ được đo lường và trả về.

Ví dụ: một yêu cầu có thể sử dụng phương thức addAccessPoint() để chỉ định một điểm truy cập cần đo khoảng cách:

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();

Một điểm truy cập được xác định bằng đối tượng ScanResult. Bạn có thể lấy đối tượng này bằng cách gọi WifiManager.getScanResults(). Bạn có thể sử dụng addAccessPoints(List<ScanResult>) để thêm nhiều điểm truy cập cùng một lúc.

Các đối tượng ScanResult có thể chứa cả IEEE 802.11mc (is80211mcResponder()) và AP hỗ trợ tính năng đo khoảng cách dựa trên không kích hoạt IEEE 802.11az (is80211azNtbResponder()). Các thiết bị hỗ trợ phạm vi NTB IEEE 802.11az thực hiện phạm vi 802.11mc hoặc 802.11az tuỳ thuộc vào khả năng của AP, mặc định là 802.11az khi AP hỗ trợ cả hai. Các thiết bị không hỗ trợ IEEE 802.11az sẽ thực hiện tất cả các hoạt động đo khoảng cách bằng giao thức IEEE 802.11mc.

Tương tự, yêu cầu đo khoảng cách có thể thêm một thiết bị ngang hàng có tính năng Tìm hiểu Wi-Fi bằng cách sử dụng địa chỉ MAC hoặc PeerHandle của thiết bị đó, sử dụng các phương thức addWifiAwarePeer(MacAddress peer)addWifiAwarePeer(PeerHandle peer) tương ứng. Để biết thêm thông tin về cách khám phá các thiết bị ngang hàng có tính năng Nhận biết Wi-Fi, hãy xem tài liệu về tính năng Nhận biết Wi-Fi.

Yêu cầu phạm vi

Ứng dụng đưa ra yêu cầu đo khoảng cách bằng phương thức WifiRttManager.startRanging() và cung cấp những thông tin sau: RangingRequest để chỉ định thao tác, Executor để chỉ định ngữ cảnh lệnh gọi lại và RangingResultCallback để nhận kết quả.

Ví dụ:

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) { … }
});

Thao tác đo khoảng cách được thực hiện không đồng bộ và kết quả đo khoảng cách được trả về trong một trong các lệnh gọi lại của RangingResultCallback:

  • Nếu toàn bộ thao tác đo khoảng cách không thành công, lệnh gọi lại onRangingFailure sẽ được kích hoạt bằng mã trạng thái được mô tả trong RangingResultCallback. Lỗi như vậy có thể xảy ra nếu dịch vụ không thể thực thi thao tác đo khoảng cách tại thời điểm đó, ví dụ: do Wi-Fi bị tắt, do ứng dụng đã yêu cầu quá nhiều thao tác đo khoảng cách và bị điều tiết hoặc do vấn đề về quyền.
  • Khi thao tác đo khoảng cách hoàn tất, lệnh gọi lại onRangingResults sẽ được kích hoạt bằng một danh sách kết quả khớp với danh sách yêu cầu – một kết quả cho mỗi yêu cầu. Thứ tự của kết quả không nhất thiết phải khớp với thứ tự của các yêu cầu. Xin lưu ý rằng thao tác đo khoảng cách có thể hoàn tất nhưng mỗi kết quả vẫn có thể cho biết kết quả đo lường cụ thể đó không thành công.

Diễn giải kết quả đo khoảng cách

Mỗi kết quả do lệnh gọi lại onRangingResults trả về được chỉ định bằng một đối tượng RangingResult. Trên mỗi yêu cầu, hãy làm như sau.

1. Xác định yêu cầu

Xác định yêu cầu dựa trên thông tin được cung cấp khi tạo RangingRequest: thường là địa chỉ MAC được cung cấp trong ScanResult xác định một điểm truy cập. Bạn có thể lấy địa chỉ MAC từ kết quả đo khoảng cách bằng cách sử dụng phương thức getMacAddress().

Danh sách kết quả đo khoảng cách có thể theo thứ tự khác với các thiết bị đồng cấp (điểm truy cập) được chỉ định trong yêu cầu đo khoảng cách, vì vậy, bạn nên sử dụng địa chỉ MAC để xác định thiết bị đồng cấp, chứ không phải thứ tự kết quả.

2. Xác định xem mỗi lần đo lường có thành công hay không

Để xác định xem một phép đo có thành công hay không, hãy sử dụng phương thức getStatus(). Mọi giá trị khác với STATUS_SUCCESS đều cho biết không thành công. Kết quả không thành công có nghĩa là tất cả các trường khác của kết quả này (ngoại trừ mã nhận dạng yêu cầu ở trên) đều không hợp lệ và phương thức get* tương ứng sẽ không thành công với ngoại lệ IllegalStateException.

3. Nhận kết quả cho mỗi lần đo lường thành công

Đối với mỗi lần đo lường thành công (RangingResult), bạn có thể truy xuất giá trị kết quả bằng các phương thức get tương ứng:

  • Khoảng cách, tính bằng mm và độ lệch chuẩn của phép đo:

    getDistanceMm()

    getDistanceStdDevMm()

  • RSSI của các gói được dùng để đo lường:

    getRssi()

  • Thời gian tính bằng mili giây tại thời điểm đo lường (cho biết thời gian kể từ khi khởi động):

    getRangingTimestampMillis()

  • Số lần đo đã thử và số lần đo thành công (và dựa trên đó để đo khoảng cách):

    getNumAttemptedMeasurements()

    getNumSuccessfulMeasurements()

  • Thời gian tối thiểu và tối đa mà thiết bị khách phải đợi giữa 11 lần đo NTB:

    getMinTimeBetweenNtbMeasurementsMicros()getMaxTimeBetweenNtbMeasurementsMicros() trả về thời gian tối thiểu và tối đa. Nếu bạn yêu cầu đo khoảng cách tiếp theo trước khi hết thời gian tối thiểu, thì API sẽ trả về kết quả đo khoảng cách đã lưu vào bộ nhớ đệm. Nếu bạn yêu cầu đo khoảng cách tiếp theo sau khi thời gian tối đa đã trôi qua, thì API sẽ chấm dứt phiên đo khoảng cách không kích hoạt và đàm phán một phiên đo khoảng cách mới với trạm phản hồi. Bạn nên tránh yêu cầu một phiên đo khoảng cách mới, vì điều này sẽ làm tăng hao tổn thời gian đo khoảng cách. Để tận dụng tối đa hiệu suất đo khoảng cách không dựa trên điều kiện kích hoạt của 802.11az, hãy kích hoạt yêu cầu đo khoảng cách tiếp theo giữa thời gian đo tối thiểu và tối đa được chỉ định trong phép đo RangingResult trước đó.

  • Các lần lặp lại Trường huấn luyện dài (LTF) mà trạm phản hồi và trạm khởi tạo sử dụng trong phần mở đầu cho kết quả NTB IEEE 802.11az:

    get80211azResponderTxLtfRepetitionsCount()

    get80211azInitiatorTxLtfRepetitionsCount()

  • Số lượng luồng thời gian không gian (STS) truyền và nhận mà trạm khởi tạo sử dụng cho kết quả NTB IEEE 802.11az:

    get80211azNumberOfTxSpatialStreams()

    get80211azNumberOfRxSpatialStreams()

Thiết bị Android hỗ trợ WiFi-RTT

Các bảng sau đây liệt kê một số điện thoại, điểm truy cậpthiết bị bán lẻ, kho hàng và trung tâm phân phối hỗ trợ WiFi-RTT. Những thông tin này chưa đầy đủ. Bạn nên liên hệ với chúng tôi để đăng sản phẩm có hỗ trợ RTT tại đây.

Điểm truy cập

Nhà sản xuất và kiểu máy Ngày hỗ trợ
Nest Wifi Pro (Wi-Fi 6E) Có thể làm
Compulab WILD AP Có thể làm
Google Wi-Fi Có thể làm
Bộ định tuyến Google Nest Wi-Fi Có thể làm
Điểm phát sóng Google Nest Wi-Fi Có thể làm
Aruba AP-635 Có thể làm
Cisco 9130 Có thể làm
Cisco 9136 Có thể làm
Cisco 9166 Có thể làm
Cisco 9164 Có thể làm
Aruba AP-505 Có thể làm
Aruba AP-515 Có thể làm
Aruba AP-575 Có thể làm
Aruba AP-518 Có thể làm
Aruba AP-505H Có thể làm
Aruba AP-565 Có thể làm
Aruba AP-535 Có thể làm

Điện thoại

Nhà sản xuất và kiểu máy Phiên bản Android
Pixel 6 9.0 trở lên
Pixel 6 Pro 9.0 trở lên
Pixel 5 9.0 trở lên
Pixel 5a 9.0 trở lên
Pixel 5a (5G) 9.0 trở lên
Xiaomi Mi 10 Pro 9.0 trở lên
Xiaomi Mi 10 9.0 trở lên
Xiaomi Redmi Mi 9T Pro 9.0 trở lên
Xiaomi Mi 9T 9.0 trở lên
Xiaomi Mi 9 9.0 trở lên
Xiaomi Mi Note 10 9.0 trở lên
Xiaomi Mi Note 10 Lite 9.0 trở lên
Xiaomi Redmi Note 9S 9.0 trở lên
Xiaomi Redmi Note 9 Pro 9.0 trở lên
Xiaomi Redmi Note 8T 9.0 trở lên
Xiaomi Redmi Note 8 9.0 trở lên
Xiaomi Redmi K30 Pro 9.0 trở lên
Xiaomi Redmi K20 Pro 9.0 trở lên
Xiaomi Redmi K20 9.0 trở lên
Xiaomi Redmi Note 5 Pro 9.0 trở lên
Xiaomi Mi CC9 Pro 9.0 trở lên
LG G8X ThinQ 9.0 trở lên
LG V50S ThinQ 9.0 trở lên
LG V60 ThinQ 9.0 trở lên
LG V30 9.0 trở lên
Samsung Galaxy Note 10+ 5G 9.0 trở lên
Samsung Galaxy S20+ 5G 9.0 trở lên
Samsung Galaxy S20+ 9.0 trở lên
Samsung Galaxy S20 5G 9.0 trở lên
Samsung Galaxy S20 Ultra 5G 9.0 trở lên
Samsung Galaxy S20 9.0 trở lên
Samsung Galaxy Note 10+ 9.0 trở lên
Samsung Galaxy Note 10 5G 9.0 trở lên
Samsung Galaxy Note 10 9.0 trở lên
Samsung A9 Pro 9.0 trở lên
Google Pixel 4 XL 9.0 trở lên
Google Pixel 4 9.0 trở lên
Google Pixel 4a 9.0 trở lên
Google Pixel 3 XL 9.0 trở lên
Google Pixel 3 9.0 trở lên
Google Pixel 3a XL 9.0 trở lên
Google Pixel 3a 9.0 trở lên
Google Pixel 2 XL 9.0 trở lên
Google Pixel 2 9.0 trở lên
Google Pixel 1 XL 9.0 trở lên
Google Pixel 1 9.0 trở lên
Poco X2 9.0 trở lên
Sharp Aquos R3 SH-04L 9.0 trở lên

Thiết bị tại cửa hàng bán lẻ, kho hàng và trung tâm phân phối

Nhà sản xuất và kiểu máy Phiên bản Android
Zebra PS20 10.0 trở lên
Zebra TC52/TC52HC 10.0 trở lên
Zebra TC57 10.0 trở lên
Zebra TC72 10.0 trở lên
Zebra TC77 10.0 trở lên
Zebra MC93 10.0 trở lên
Zebra TC8300 10.0 trở lên
Zebra VC8300 10.0 trở lên
Zebra EC30 10.0 trở lên
Zebra ET51 10.0 trở lên
Zebra ET56 10.0 trở lên
Zebra L10 10.0 trở lên
Zebra CC600/CC6000 10.0 trở lên
Zebra MC3300x 10.0 trở lên
Zebra MC330x 10.0 trở lên
Zebra TC52x 10.0 trở lên
Zebra TC57x 10.0 trở lên
Zebra EC50 (LAN và HC) 10.0 trở lên
Zebra EC55 (WAN) 10.0 trở lên
Zebra WT6300 10.0 trở lên
Skorpio X5 10.0 trở lên