Wi-Fi 位置情報: RTT を使用したレンジング(距離測定)

Wi-Fi RTT(ラウンドトリップ時間)API が提供する Wi-Fi 位置情報機能を使用して、付近にある RTT 対応の Wi-Fi アクセス ポイントや Wi-Fi Aware ピア デバイスとの距離を測定できます。

3 つ以上のアクセス ポイントまでの距離を測定する場合は、マルチラテレーション アルゴリズムを使用して、測定に最適なデバイスの位置を推定できます。結果の精度は通常 1~2 メートルの誤差の範囲内です。

この精度を確保できることによって、屋内ナビゲーション、明確な音声操作(例: 「このライトをつけて」)、位置情報をベースとする情報(例: 「このサービスに関してスペシャル オファーはありますか?」)などの精度の高い、位置情報を利用したサービスを開発できます。

リクエスト元のデバイスは、Wi-Fi RTT で距離を測定するためにアクセス ポイントに接続する必要はありません。プライバシーを保護するために、アクセス ポイントまでの距離を判断できるのはリクエスト元のデバイスのみです。アクセス ポイントにはこの情報がありません。Wi-Fi RTT オペレーションでは、フォアグラウンド アプリに対する制限はありませんが、バックグラウンド アプリに対しては制限が課されます。

Wi-Fi RTT と関連するファインタイム測定(FTM)機能は、以下のとおりです。 準拠していますWi-Fi RTT では、パケットがデバイス間を往復する時間を測定し、測定された時間に光速を乗じることによって 2 つのデバイス間の距離を計算するため、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 オブジェクトとして表すことができます。Location Configuration Information / Location Civic Report(LCI / LCR データ)をサポートする Wi-Fi RTT AP の場合、プロトコルは距離測定プロセス中に ResponderLocation オブジェクトを返します。

この機能を使用すると、アプリは事前にこの情報を保存する代わりに、AP に直接クエリを実行して位置を問い合わせることができます。そのため、ユーザーがある建物に初めて入ったときなど、AP を事前に把握できていない場合でも、アプリは AP を見つけてその位置を特定できます。

IEEE 802.11az NTB 測距のサポートは、Android 15(API レベル 35)以降を搭載したデバイスで利用できます。つまり、デバイスが 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)以降を搭載している必要があります。デバイスで IEEE 802.11az ノントリガーベースの距離測定が有効になっている Android 15(API レベル 35)以降を搭載している。
  • 距離測定のリクエストを行うデバイスでは、[設定] > [位置情報] で位置情報サービスを有効にして Wi-Fi スキャンをオンにする必要があります。
  • 測距リクエストを行うアプリが 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 RTT が利用できない場合があります。ハードウェアとファームウェアの機能によっては、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);

詳細については、ブロードキャストをご覧ください。

距離測定のリクエストを作成する

圏内のリクエスト (RangingRequest)が作成されます 接続先の AP または Wi-Fi Aware ピアのリストを指定して、 が要求されます。1 つの距離測定リクエストで複数のアクセス ポイントまたは Wi-Fi Aware ピアを指定すると、すべてのデバイスまでの距離が測定され、返されます。

たとえば、リクエストでは 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 アドレスまたは MAC アドレスを使用して Wi-Fi Aware ピアを追加できます。 アドレスまたはその PeerHandle 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:

  • 距離測定オペレーション全体が失敗した場合、RangingResultCallback で説明されているステータス コードで onRangingFailure コールバックがトリガーされます。このような失敗は、Wi-Fi が無効になっている、アプリがリクエストした距離測定オペレーションが多すぎるため制限が課されている、または権限に問題があるなどの理由により、サービスで距離測定オペレーションが実行できない場合に発生します。
  • 距離測定オペレーションが完了すると、 onRangingResults 結果のリストと一致する結果のリストとともに、 リクエストごとに 1 つの結果を返すことができます。結果の順序は、リクエストの順序と一致しない場合があります。距離測定オペレーションが完了した場合でも、各結果が依然として特定の測定の失敗を示している可能性がある点に留意してください。

距離測定の結果を解釈する

この関数から返される結果は、 onRangingResults コールバックが RangingResult で指定される 渡されます。各リクエストで、次の操作を行います。

1. リクエストを特定する

作成時に提供された情報に基づいてリクエストを識別します。 RangingRequest: ほとんどの場合、アクセスを識別する ScanResult で提供される MAC アドレスです。 ありますMAC アドレスは、getMacAddress() メソッドを使用して距離測定の結果から取得できます。

距離測定の結果のリストにおける並び順は、距離測定リクエストで指定されたピア(アクセス ポイント)とは異なる場合があるため、結果の順序ではなく MAC アドレスを使用してピアを特定する必要があります。

2. 各測定が成功したかどうかを判断する

測定が成功したかどうかを判断するには、getStatus() メソッドを使用します。以外の値 STATUS_SUCCESS 失敗を示します。失敗した場合、この結果の他のすべてのフィールド(上記のリクエスト ID を除く)は無効になり、対応する get* メソッドは IllegalStateException 例外で失敗します。

3. 成功した各測定の結果を取得する

成功した測定(RangingResult)ごとに、それぞれの get メソッドを使用して結果の値を取得できます。

  • 距離(mm)と測定の標準偏差:

    getDistanceMm()

    getDistanceStdDevMm()

  • 測定に使用されたパケットの RSSI:

    getRssi()

  • 測定が行われた時間(ミリ秒。起動からの経過時間を示します):

    getRangingTimestampMillis()

  • 試行された測定回数と成功した測定回数(距離測定はこれに基づきます):

    getNumAttemptedMeasurements()

    getNumSuccessfulMeasurements()

  • クライアント デバイスが 11az NTB 測定の間に待機する最小時間と最大時間:

    getMinTimeBetweenNtbMeasurementsMicros() および getMaxTimeBetweenNtbMeasurementsMicros() 最小時間と最大時間を返します。最小時間が経過する前に次の測定がリクエストされた場合、API はキャッシュに保存された測定結果を返します。最大時間が経過した後に次の測距測定がリクエストされた場合、API はトリガー以外の測距セッションを終了し、応答ステーションで新しい測距セッションをネゴシエートします。新しい圏内のセッションは追加されないため、リクエストしないようにしてください。 距離測定時間に対するオーバーヘッドが大きくなります。802.11az を最大限に活用するには 非トリガー ベースの距離測定の効率性、次の距離測定リクエストをトリガー 前の期間で RangingResult の測定。

  • レスポンダー ステーションとイニシエータ ステーションによる長いトレーニング フィールド(LTF)の繰り返し IEEE 802.11az NTB 結果のプリアンブルで使用されています。

    get80211azResponderTxLtfRepetitionsCount()

    get80211azInitiatorTxLtfRepetitionsCount()

  • イニシエータが送受信した空間タイムストリーム(STS)の数 IEEE 802.11az NTB の結果に使用されたステーション

    get80211azNumberOfTxSpatialStreams()

    get80211azNumberOfRxSpatialStreams()

Wi-Fi-RTT 対応の Android デバイス

次の表に、スマートフォンアクセス ポイント小売店、倉庫、配送センターのデバイスの一覧を示します。 100 ミリ秒以内にサポートします。これらはごく一部を示したものです。こちらに RTT 対応プロダクトを掲載される場合は、お問い合わせいただくことをおすすめします。

アクセス ポイント

メーカーとモデル サポート日
Google Nest Wifi Pro(Wi-Fi 6E) サポート対象
Compulab WILD AP サポート対象
Google WiFi サポート対象
Google Nest Wifi ルーター サポート対象
Google Nest Wifi 拡張ポイント サポート対象
Aruba AP-635 サポート対象
Cisco 9130 サポート対象
Cisco 9136 サポート対象
Cisco 9166 サポート対象
Cisco 9164 サポート対象
Aruba AP-505 サポート対象
Aruba AP-515 サポート対象
Aruba AP-575 サポート対象
Aruba AP-518 サポート対象
Aruba AP-505H サポート対象
Aruba AP-565 サポート対象
Aruba AP-535 サポート対象

スマートフォン

メーカーとモデル Android バージョン
Google Pixel 6 9.0+
Google Pixel 6 Pro 9.0+
Google Pixel 5 9.0+
Google Pixel 5a 9.0+
Google Pixel 5a (5G) 9.0+
Xiaomi Mi 10 Pro 9.0+
Xiaomi Mi 10 9.0+
Xiaomi Redmi Mi 9T Pro 9.0+
Xiaomi Mi 9T 9.0+
Xiaomi Mi 9 9.0+
Xiaomi Mi Note 10 9.0+
Xiaomi 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+
Xiaomi Redmi K30 Pro 9.0+
Xiaomi Redmi K20 Pro 9.0+
Xiaomi Redmi K20 9.0+
Xiaomi Redmi Note 5 Pro 9.0+
Xiaomi 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 Note10 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+
ポコ X2 9.0+
シャープ Aquos R3 SH-04L 9.0+

小売、倉庫、配送センターのデバイス

メーカーとモデル Android バージョン
Zebra PS20 10.0 以降
Zebra TC52、TC52HC 10.0 以降
ゼブラ TC57 10.0 以降
Zebra TC72 10.0 以降
Zebra TC77 10.0 以降
Zebra MC93 10.0 以降
Zebra TC8300 10.0 以降
ゼブラ VC8300 10.0 以降
ゼブラ EC30 10.0 以降
ゼブラ ET51 10.0 以降
ゼブラ ET56 10.0 以降
Zebra L10 10.0 以降
Zebra CC600/CC6000 10.0 以降
Zebra MC3300x 10.0 以降
ゼブラ 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 以降