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 API Wi-Fi RTT (Round-Trip-Time) cung cấp để đo khoảng cách đến các điểm truy cập Wi-Fi có thể dùng RTT ở gần và các thiết bị ngang hàng Nhận biết Wi-Fi.

Nếu đo lường khoảng cách đến 3 điểm truy cập trở lên, bạn có thể sử dụng thuật toán nhân hệ số để ước tính vị trí thiết bị phù hợp nhất với những phép đo đó. Kết quả thường chính xác trong vòng 1-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ư tính năng chỉ đường trong nhà, điều khiển bằng giọng nói riêng biệt (ví dụ: "Bật đèn này") và thông tin dựa trên vị trí (ví dụ: "Sản phẩm này có ưu đãi đặc biệt 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 lường khoảng cách bằng tính năng Tin nhắn theo thời gian thực (RTT) Wi-Fi. Để đảm bảo 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. Hoạt động qua Wi-Fi RTT không giới hạn đối với các ứng dụng trên nền trước nhưng sẽ được điều tiết đối với các ứng dụng ở chế độ nền.

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

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

Tính năng Tin nhắn theo thời gian thực (RTT) Wi-Fi được ra mắt trong Android 9 (API cấp 28). Khi dùng giao thức này để xác định vị trí của thiết bị bằng tính năng đa chức năng 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) xác định trước trong ứng dụng của mình. Bạn là người 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 các đối tượng ResponderLocation, bao gồm vĩ độ, kinh độ và độ cao. Đối với các AP chứa RTT Wi-Fi có hỗ trợ Thông tin cấu hình vị trí/Báo cáo dân sự vị trí (dữ liệu LCI/LCR), giao thức sẽ trả về một đối tượng ResponderLocation trong quá trình xác định phạm vi.

Tính năng này cho phép các ứng dụng truy vấn các AP để hỏi trực tiếp vị trí của chúng thay vì cần lưu trữ trước thông tin này. 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 các AP này chưa được xác định trước đó, chẳng hạn như khi người dùng bước vào một toà nhà mới.

Yêu cầu

  • Phần cứng của thiết bị đưa ra yêu cầu về phạm vi phải triển khai tiêu chuẩn FTM 802.11-2016.
  • Thiết bị đưa ra yêu cầu sắp xếp phải đang chạy Android 9 (API cấp 28) trở lên.
  • Thiết bị đưa ra yêu cầu sắp xếp phải bật dịch vụ vị trí và bật tính năng quét tìm Wi-Fi (trong phần Cài đặt > Vị trí).
  • Nếu ứng dụng đang tạo yêu cầu phạm vi 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 một ứng dụng như vậy nhắm đến một phiên bản Android cũ, thì ứng dụng đó phải có quyền ACCESS_FINE_LOCATION.
  • Ứng dụng phải truy vấn phạm vi các điểm truy cập khi ứng dụng đang 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 vào 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.

Thiết lập

Để thiết lập cho ứng dụng sử dụng tính năng Tin nhắn theo thời gian thực (RTT) Wi-Fi, 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 đây 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" />

Các quyền NEARBY_WIFI_DEVICESACCESS_FINE_LOCATION là các quyền 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 tin nhắn theo thời gian thực (RTT). Ứng dụng của bạn sẽ cần yêu cầu quyền của người dùng nếu quyền chưa được cấp. Để biết thêm thông tin về quyền khi bắt đầu chạy, hãy xem bài viết Yêu cầu quyền cho ứng dụng.

2. Kiểm tra xem thiết bị có hỗ trợ tính năng Tin nhắn theo thời gian thực (RTT) qua Wi-Fi hay không

Để kiểm tra xem thiết bị có hỗ trợ tính năng Tin nhắn theo thời gian thực (RTT) của Wi-Fi 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ó tính năng Tin nhắn theo thời gian thực (RTT) Wi-Fi không

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

Khả năng sử dụng tính năng Tin nhắn theo thời gian thực (RTT) qua Wi-Fi có thể thay đổi bất cứ lúc nào. Ứng dụng của bạn nên đăng ký một BroadcastReceiver để nhận ACTION_WIFI_RTT_STATE_CHANGED. Thông tin này được gửi khi tình trạng rảnh/bận thay đổi. Khi nhận được ý định truyền tin, ứng dụng sẽ kiểm tra trạng thái có sẵn hiện tại 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 Chương trình phát sóng.

Tạo một yêu cầu về phạm vi

Một yêu cầu xác định phạm vi (RangingRequest) được tạo bằng cách chỉ định danh sách các AP hoặc Wi-Fi Aware ngang hàng mà phạm vi được yêu cầu. Bạn có thể chỉ định nhiều điểm truy cập hoặc các thiết bị ngang hàng dựa trên Wi-Fi trong một yêu cầu; khoảng cách đến tất cả các thiết bị sẽ được đo 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 lường 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ể thu được điểm truy cập này bằng cách gọi WifiManager.getScanResults(). Bạn có thể sử dụng addAccessPoints(List)) để thêm nhiều điểm truy cập trong một lô.

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

Phạm vi yêu cầu

Một ứng dụng đưa ra một yêu cầu sắp xếp bằng phương thức WifiRttManager.startRanging() và cung cấp các yêu cầu sau: RangingRequest để chỉ định thao tác, Executor để chỉ định ngữ cả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 sắp xếp được thực hiện không đồng bộ và việc sắp xếp các kết quả sẽ được trả về trong một trong các lệnh gọi lại của RangingResultCallback:

  • Nếu toàn bộ toán tử bị lỗi, lệnh gọi lại onRangingFailure sẽ được kích hoạt bằng mã trạng thái như 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 một thao tác trong phạm vi tại thời điểm đó, chẳng hạn như do Wi-Fi bị tắt, do ứng dụng đã yêu cầu quá nhiều thao tác và bị điều tiết, hoặc do vấn đề về quyền.
  • Khi thao tác sắp xếp hoàn tất, lệnh gọi lại onRangingResults sẽ được kích hoạt với 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 sắp xếp có thể hoàn tất nhưng mỗi kết quả vẫn có thể cho biết phép đo cụ thể đó không thành công.

Diễn giải phạm vi các kết quả

Mỗi kết quả mà lệnh gọi lại onRangingResults trả về được chỉ định bởi một đối tượng RangingResult. Đối với 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ả sắp xếp bằng cách sử dụng phương thức getMacAddress().

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

2. Xác định xem mỗi phép đo có thành công hay không

Để xác định xem quá trình đo lường có thành công hay không, hãy sử dụng phương thức getStatus(). Bất kỳ giá trị nào khác ngoài STATUS_ tái hiện thành công đều cho biết lỗi. Lỗi có nghĩa là tất cả các trường khác của kết quả này (ngoại trừ thông tin 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 một ngoại lệ IllegalStateException .

3. Nhận kết quả cho mỗi phép đo thành công

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

Các thiết bị Android hỗ trợ tính năng Wi-Fi-RTT

Bảng dưới đây liệt kê một số điện thoại, điểm truy cậpthiết bị bán lẻ, lưu kho và phân phối có hỗ trợ tính năng Wi-Fi-RTT. Các chỉ số này chưa đầy đủ. Bạn nên liên hệ với chúng tôi để liệt kê các sản phẩm có hỗ trợ tin nhắn theo thời gian thực (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
AP WILD của Compulab Có thể làm
Google Wi-Fi Có thể làm
Bộ định tuyến Wi-Fi Google Nest Có thể làm
Điểm phát sóng Wi-Fi Google Nest 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 Trên 9
Pixel 6 Pro Trên 9
Pixel 5 Trên 9
Pixel 5a Trên 9
Pixel 5a (5G) Trên 9
Xiaomi Mi 10 Pro Trên 9
Xiaomi Mi 10 Trên 9
Xiaomi Redmi Mi 9T Pro Trên 9
Xiaomi Mi 9T Trên 9
Xiaomi Mi 9 Trên 9
Xiaomi Mi Note 10 Trên 9
Xiaomi Mi Note 10 Lite Trên 9
Xiaomi Redmi Note 9S Trên 9
Xiaomi Redmi Note 9 Pro Trên 9
Xiaomi Redmi Note 8T Trên 9
Xiaomi Redmi Note 8 Trên 9
Xiaomi Redmi K30 Pro Trên 9
Xiaomi Redmi K20 Pro Trên 9
Xiaomi Redmi K20 Trên 9
Xiaomi Redmi Note 5 Pro Trên 9
Xiaomi Mi CC9 Pro Trên 9
LG G8X ThinQ Trên 9
LG V50S ThinQ Trên 9
LG V60 ThinQ Trên 9
LG V30 Trên 9
Samsung Galaxy Note 10 trở lên 5G Trên 9
Samsung Galaxy S20+ 5G Trên 9
Samsung Galaxy S20 trở lên Trên 9
Samsung Galaxy S20 5G Trên 9
Samsung Galaxy S20 Ultra 5G Trên 9
Samsung Galaxy S20 Trên 9
Samsung Galaxy Note 10 trở lên Trên 9
Samsung Galaxy Note 10 5G Trên 9
Samsung Galaxy Note 10 Trên 9
Samsung A9 Pro Trên 9
Google Pixel 4 XL Trên 9
Google Pixel 4 Trên 9
Google Pixel 4a Trên 9
Google Pixel 3 XL Trên 9
Google Pixel 3 Trên 9
Google Pixel 3a XL Trên 9
Google Pixel 3a Trên 9
Google Pixel 2 XL Trên 9
Google Pixel 2 Trên 9
Google Pixel 1 XL Trên 9
Google Pixel 1 Trên 9
Poco X2 Trên 9
Sharp Aquos R3 SH-04L Trên 9

Thiết bị cho trung tâm bán lẻ, lưu kho và phân phối

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