通过 RTT 确定 WLAN 位置信息

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

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

借助这种精确度,您可以开发精细的基于位置的服务,例如室内导航、消除歧义的语音控制(例如“打开这盏灯”)和基于位置的信息(例如“此商品有特别优惠吗?”)。

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

Wi-Fi 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 并确定其位置。

搭载 Android 15(API 级别 35)及更高版本的设备支持 IEEE 802.11az NTB 测距。这意味着,如果设备支持 IEEE 802.11az NTB 发起方模式(由 WifiRttManager.CHARACTERISTICS_KEY_BOOLEAN_NTB_INITIATOR 指示),您的应用可以通过单个测距请求找到支持 IEEE 802.11mc 和 IEEE 802.11az 的 AP。RangingResult API 已扩展,可提供有关测距测量之间间隔的最小值和最大值的信息,从而让您的应用能够控制确切的间隔。

要求

  • 发出测距请求的设备的硬件必须实现 802.11-2016 FTM 标准或 802.11az 标准(非基于触发器的测距)。
  • 发出测距请求的设备必须搭载 Android 9(API 级别 28)或更高版本。在搭载 Android 15(API 级别 35)及更高版本的设备上,IEEE 802.11az 非触发式测距功能处于启用状态。
  • 发出测距请求的设备必须启用位置信息服务并开启 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_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 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);

如需了解详情,请参阅广播。

创建测距请求

通过指定要测距的 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<ScanResult>) 批量添加多个接入点。

ScanResult 对象可以同时包含支持 IEEE 802.11mc (is80211mcResponder()) 和 IEEE 802.11az 非触发式测距 (is80211azNtbResponder()) 的 AP。支持 IEEE 802.11az NTB 测距的设备会根据 AP 的功能执行 802.11mc 或 802.11az 测距,当 AP 同时支持这两种测距时,默认执行 802.11az 测距。不支持 IEEE 802.11az 的设备会使用 IEEE 802.11mc 协议执行所有测距。

同样,测距请求可以使用 MAC 地址或 PeerHandle 添加 Wi-Fi Aware 对等设备,分别使用 addWifiAwarePeer(MacAddress peer) 和 addWifiAwarePeer(PeerHandle peer) 方法。如需详细了解如何发现 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 的其中一个回调中返回:

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

解读测距结果

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

1. 识别请求

根据创建 RangingRequest 时提供的信息识别请求:最常见的是在 ScanResult 中提供用于标识接入点的 MAC 地址。您可以使用 getMacAddress() 方法从测距结果中获取 MAC 地址。

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

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

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

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

对于每次成功的测量 (RangingResult),您都可以使用相应的 get 方法检索结果值:

支持 Wi-Fi RTT 的 Android 设备

下表列出了一些支持 WiFi-RTT 的手机、接入点以及零售、仓储和配送中心设备。这些远远不够全面。我们建议您与我们联系,以便在此处列出支持 RTT 的产品。

接入点

制造商和型号 支持日期 协议
Nest Wifi Pro (Wi-Fi 6E) 支持 mc
Compulab WILD AP 支持 mc
Google Wi-Fi 支持 mc
Google Nest Wi-Fi 路由器 支持 mc
Google Nest Wi-Fi 盒子 支持 mc
Aruba AP-635 支持 mc
Cisco 9130 支持 mc
Cisco 9136 支持 mc
Cisco 9166 支持 mc
Cisco 9164 支持 mc
Cisco CW9172I 支持 mc/az
Cisco CW9172H 支持 mc/az
Cisco CW9176I 支持 mc/az
Cisco CW9178I 支持 mc/az
Aruba AP-505 支持 mc
Aruba AP-515 支持 mc
Aruba AP-575 支持 mc
Aruba AP-518 支持 mc
Aruba AP-505H 支持 mc
Aruba AP-565 支持 mc
Aruba AP-535 支持 mc
Aruba AP567 支持 mc
Aruba AP577 支持 mc
Aruba AP555 支持 mc
Aruba AP635 支持 mc
Aruba AP655 支持 mc
Aruba AP615 支持 mc
Aruba AP734 支持 mc/az
Aruba AP735 支持 mc/az
Aruba AP754 支持 mc/az
Aruba AP755 支持 mc/az

手机

制造商和型号 Android 版本
Google Pixel 9 Pro XL 14+
Google Pixel 9 14+
Google Pixel 9 Pro 14+
Google Pixel 9 Pro XL 14+
Google Pixel 7a 14+
Google Pixel 7 14+
Google Pixel 8 14+
Google Pixel 8 Pro 14+
Google Pixel 8a 14+
三星 SM-S918B 14+
Samsung SM-A515F 14+
Google Pixel 9 Pro 14+
三星 SM-A546E 14+
Samsung SM-S928B 14+
Samsung SM-A217F 14+
Samsung SM-A715F 14+
Samsung SM-A528B 14+
Samsung SM-A135F 14+
Samsung SM-S911B 14+
小米 21091116AI 14+
Google Pixel 9 14+
Samsung SM-A127F 14+
Google Pixel 7 Pro 14+
Samsung SM-A556E 14+
Pixel 6 9.0 及更高版本
Pixel 6 Pro 9.0 及更高版本
Pixel 5 9.0 及更高版本
Pixel 5a 9.0 及更高版本
Pixel 5a 5G 9.0 及更高版本
小米 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 及更高版本
小米 Redmi 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 及更高版本
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 及更高版本
三星 Galaxy S20 9.0 及更高版本
Samsung Galaxy Note 10+ 9.0 及更高版本
Samsung 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 及更高版本
Sharp Aquos R3 SH-04L 9.0 及更高版本

零售、仓储和配送中心设备

制造商和型号 Android 版本
Zebra 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+