通过 RTT 确定 WLAN 位置信息

您可以利用 Wi-Fi RTT(往返时间)API 提供的 Wi-Fi 位置功能测量距附近支持 RTT 的 Wi-Fi 接入点和 Wi-Fi 感知对等设备的距离。

如果您测量与三个或更多接入点的距离,可以使用多点定位算法来预估与这些测量值最相符的设备位置。结果通常可以精确到 1 至 2 米。

凭借这种精准度,您可以开发基于精确位置的服务,例如室内导航、无歧义语音控制(例如,“打开这盏灯”)以及基于位置的信息(例如,“此产品是否有特别优惠?”)。

请求发出设备无需连接到接入点即可通过 Wi-Fi RTT 测量距离。为保护隐私,只有发出请求的设备可以 确定与接入点的距离;这些接入点没有 这些信息。前台应用执行 Wi-Fi RTT 操作不受限制,但后台应用执行此类操作时会受限。

WLAN RTT 和相关的精确时间测量 (FTM) 功能 符合 IEEE 802.11-2016 标准。Wi-Fi RTT 需要 FTM 提供的精确时间测量,因为前者通过测量数据包在设备之间往返所需的时间,并将该时间乘以光速来计算两个设备之间的距离。

Android 15(API 级别 35)引入了对 IEEE 802.11az 非基于触发器的支持 (NTB) 范围。

实现差异因 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(例如用户进入新建筑物时),您的应用也可以找到 AP 并确定其位置。

IEEE 802.11az NTB 范围支持在搭载 Android 15 的设备上提供 (API 级别 35)及更高版本。这意味着,如果设备支持 IEEE 802.11az NTB 响应模式(用 WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_STA_RESPONDER), 只要一个 AP, 范围请求。RangingResult API 已经过扩展,可提供 可以使用的时间间隔 测距,将精确的时间间隔由您的应用控制。

要求

  • 测距请求发出设备的硬件必须实现 802.11-2016 FTM 标准或 802.11az 标准(非基于触发器的测距)。
  • 测距请求发出设备必须搭载 Android 9(API 级别) 28) 或更高版本。在设备上启用了 IEEE 802.11az 非基于触发器的测距 搭载 Android 15(API 级别 35)及更高版本。
  • 测距请求发出设备必须启用位置信息服务并打开 WLAN 扫描(位于设置 > 位置信息下)。
  • 如果测距请求发出目标的应用 Android 13(API 级别 33)或更高版本,必须具有 NEARBY_WIFI_DEVICES 权限。如果此类应用以较低版本的 Android 为目标平台,则必须 拥有 ACCESS_FINE_LOCATION 权限。
  • 当应用可见或在前台服务中时,应用必须查询接入点的范围。应用无法在后台访问位置信息
  • 接入点必须实现 IEEE 802.11-2016 FTM 标准或 IEEE 802.11az 标准(非基于触发器的测距)。

设置

如需将应用设置为使用 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_DEVICESACCESS_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 RTT 是否可用

设备上可能存在 Wi-Fi RTT,但可能无法使用 Wi-Fi RTT,因为用户 已停用 Wi-Fi。根据其硬件和固件功能, 如果正在使用 SoftAP 或网络共享,则设备可能不支持 Wi-Fi RTT。检查 是否提供 Wi-Fi RTT、呼叫 isAvailable()

Wi-Fi RTT 的可用性随时都可能发生变化。您的应用应注册 BroadcastReceiver 接收 ACTION_WIFI_RTT_STATE_CHANGED、 。应用收到该广播 intent 后,应检查可用性的当前状态并相应地调整其行为。

例如:

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 感知对等设备, 请求。您可以在单个测距请求中指定多个接入点或 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<ScanResult>) 来批量添加多个接入点

ScanResult 对象可同时包含 IEEE 802.11mc (is80211mcResponder()) 和 支持 IEEE 802.11az 非基于触发器的测距 (is80211azNtbResponder()) AP。支持 IEEE 802.11az NTB 测距的设备可执行 802.11mc 或 802.11az 范围取决于 AP 的功能,默认为 802.11az AP 同时支持这两种模式。不支持 IEEE 802.11az 的设备在执行全部操作时 使用 IEEE 802.11mc 协议测距。

同样,测距请求可以使用其 MAC 添加 WLAN 感知对等设备 地址或其 PeerHandle,使用 addWifiAwarePeer(MacAddress peer)addWifiAwarePeer(PeerHandle peer) 方法。如需详细了解如何发现 Wi-Fi 感知对等设备, 请参阅 Wi-Fi 感知文档

请求测距

应用使用 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:

  • 如果整个测距操作失败, onRangingFailure 回调,系统会使用 RangingResultCallback。 如果该服务当时出于某些原因(例如 WLAN 已停用、应用请求的测距操作过多并受到限制,或者存在权限问题)无法执行测距操作,可能会发生此类失败。
  • 测距操作完成后, onRangingResults 回调函数,系统会返回与 个请求 - 每个请求一个结果。结果的顺序不一定与请求的顺序一致。请注意,测距操作可能已经完成,但每个结果仍有可能提示该特定测量失败。

解读测距结果

调用返回的每个结果, onRangingResults 回调由 RangingResult 指定 对象。请对每个请求执行以下操作。

1. 识别请求

根据在创建 RangingRequest: 通常是 ScanResult 中提供的 MAC 地址,用于标识访问权限 。您可以使用 getMacAddress() 方法。

测距结果列表的顺序可能与测距请求中指定的对等设备(接入点)的顺序不同,因此您应使用 MAC 地址而非结果的顺序来识别对等设备。

2. 确定每个测量是否成功

要确定测量是否成功,请使用 getStatus() 方法。除以下项之外的任何值: STATUS_SUCCESS 表示失败。失败意味着此结果的所有其他字段 (上述请求标识除外)无效,而相应的 get* 方法将失败,并显示 IllegalStateException 异常。

3. 获取每个成功测量的结果

对于每个成功的测量 (RangingResult),您可以检索结果 值与相应的 get 方法分别对应:

支持 Wi-Fi 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 盒子 支持
阿鲁巴 AP-635 支持
思科 9130 支持
思科 9136 支持
思科 9166 支持
思科 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 及更高版本
小米 Redmi Note 9S 9.0 及更高版本
小米 Redmi Note 9 Pro 9.0 及更高版本
小米 Redmi Note 8T 9.0 及更高版本
小米红米 NOTE 8 9.0 及更高版本
小米 Redmi K30 Pro 9.0 及更高版本
小米 Redmi K20 Pro 9.0 及更高版本
小米红米 K20 9.0 及更高版本
Xiaomi 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 及更高版本
三星 Galaxy Note 10+ 5G 9.0 及更高版本
三星 Galaxy S20+ 5G 9.0 及更高版本
三星 Galaxy S20+ 9.0 及更高版本
三星 Galaxy S20 5G 9.0 及更高版本
三星 Galaxy S20 Ultra 5G 9.0 及更高版本
三星 Galaxy S20 9.0 及更高版本
三星 Galaxy Note 10+ 9.0 及更高版本
三星 Galaxy Note 10 5G 9.0 及更高版本
三星 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 10.0 及更高版本
斑马 TC52/TC52HC 10.0 及更高版本
斑马 TC57 10.0 及更高版本
斑马 TC72 10.0 及更高版本
斑马 TC77 10.0 及更高版本
斑马 MC93 10.0 及更高版本
斑马 TC8300 10.0 及更高版本
斑马 VC8300 10.0 及更高版本
斑马 EC30 10.0 及更高版本
斑马 ET51 10.0 及更高版本
斑马 ET56 10.0 及更高版本
斑马线 L10 10.0 及更高版本
斑马 CC600/CC6000 10.0 及更高版本
斑马 MC3300x 10.0 及更高版本
斑马 MC330x 10.0 及更高版本
斑马 TC52x 10.0 及更高版本
斑马 TC57x 10.0 及更高版本
Zebra EC50(LAN 和 HC) 10.0 及更高版本
斑马 EC55 (WAN) 10.0 及更高版本
斑马 WT6300 10.0 及更高版本
Skorpio X5 10.0 及更高版本