Lokasi Wi-Fi: ranging dengan RTT

Anda dapat menggunakan fungsi lokasi Wi-Fi yang disediakan oleh Wi-Fi RTT (Round-Trip-Time) API untuk mengukur jarak ke titik akses Wi-Fi berkemampuan RTT terdekat dan perangkat Wi-Fi Aware peer.

Jika Anda mengukur jarak ke tiga titik akses atau lebih, Anda dapat menggunakan algoritme multilaterasi untuk memperkirakan posisi perangkat yang paling sesuai dengan pengukuran tersebut. Hasilnya biasanya akurat dalam 1-2 meter.

Dengan keakuratan ini, Anda dapat mengembangkan layanan berdasarkan lokasi yang sangat akurat, seperti navigasi dalam ruangan, kontrol suara yang diperjelas (misalnya, "Nyalakan lampu ini"), dan informasi berdasarkan lokasi (misalnya, "Apakah ada penawaran spesial untuk produk ini?").

Perangkat yang melakukan permintaan tidak perlu terhubung ke titik akses untuk mengukur jarak dengan Wi-Fi RTT. Untuk menjaga privasi, hanya perangkat yang meminta yang dapat menentukan jarak ke titik akses; titik akses tidak memiliki informasi ini. Operasi Wi-Fi RTT tidak terbatas untuk aplikasi latar depan tetapi dibatasi untuk aplikasi latar belakang.

Wi-Fi RTT dan kemampuan terkait Fine-Time-Measurement (FTM) ditentukan oleh standar IEEE 802.11-2016. Wi-Fi RTT memerlukan pengukuran waktu yang tepat yang disediakan oleh FTM karena menghitung jarak antara dua perangkat dengan mengukur waktu yang dibutuhkan paket untuk melakukan perjalanan bolak-balik antara perangkat dan mengalikan waktu itu dengan kecepatan cahaya.

Perbedaan implementasi berdasarkan versi Android

Wi-Fi RTT diperkenalkan di Android 9 (API level 28). Saat menggunakan protokol ini untuk menentukan posisi perangkat menggunakan multilaterasi dengan perangkat yang menjalankan Android 9, Anda harus memiliki akses ke data lokasi titik akses (AP) yang telah ditentukan sebelumnya di aplikasi. Anda bebas menentukan cara menyimpan dan mengambil data ini.

Pada perangkat yang menjalankan Android 10 (API level 29) dan lebih tinggi, data lokasi AP dapat direpresentasikan sebagai objek ResponderLocation, yang mencakup lintang, bujur, dan ketinggian. Untuk AP Wi-Fi RTT yang mendukung Location Configuration Information/Location Civic Report (data LCI/LCR), protokol akan menampilkan objek ResponderLocation selama proses ranging.

Fitur ini memungkinkan aplikasi meminta AP untuk menanyakan posisi mereka secara langsung tanpa perlu menyimpan informasi ini sebelumnya. Jadi, aplikasi Anda dapat menemukan AP dan menentukan posisi mereka meskipun AP tidak diketahui sebelumnya, seperti ketika pengguna memasuki gedung baru.

Persyaratan

  • Hardware perangkat yang membuat permintaan ranging harus menerapkan standar FTM 802.11-2016.
  • Perangkat yang membuat permintaan ranging harus menjalankan Android 9 (API level 28) atau yang lebih baru.
  • Perangkat yang membuat permintaan ranging harus mengaktifkan layanan lokasi dan pemindaian Wi-Fi (dalam Setelan > Lokasi).
  • Jika aplikasi yang membuat permintaan ranging menargetkan Android 13 (API level 33) atau yang lebih tinggi, aplikasi tersebut harus memiliki izin NEARBY_WIFI_DEVICES. Jika aplikasi semacam itu menargetkan versi Android yang lebih lama, aplikasi tersebut harus memiliki izin ACCESS_FINE_LOCATION.
  • Aplikasi harus meminta rentang titik akses saat aplikasi terlihat atau ada di layanan latar depan. Aplikasi tidak dapat mengakses informasi lokasi dari latar belakang.
  • Titik akses (AP) harus menerapkan standar FTM IEEE 802.11-2016.

Penyiapan

Untuk menyiapkan aplikasi Anda menggunakan Wi-Fi RTT, lakukan langkah-langkah berikut.

1. Minta izin

Minta izin berikut dalam manifes aplikasi Anda:

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

Izin NEARBY_WIFI_DEVICES dan ACCESS_FINE_LOCATION adalah izin yang berbahaya, jadi Anda harus memintanya saat runtime setiap kali pengguna ingin melakukan operasi pemindaian RTT. Aplikasi Anda harus meminta izin pengguna jika izin belum diberikan. Untuk informasi selengkapnya tentang izin runtime, lihat Meminta Izin Aplikasi.

2. Periksa apakah perangkat mendukung Wi-Fi RTT

Untuk memeriksa apakah perangkat mendukung Wi-Fi RTT, gunakan PackageManager API:

Kotlin

context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)

Java

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

3. Memeriksa apakah Wi-Fi RTT tersedia

Wi-Fi RTT mungkin ada pada perangkat, tetapi saat ini mungkin tidak tersedia karena pengguna telah menonaktifkan Wi-Fi. Bergantung pada kapabilitas hardware dan firmware mereka, beberapa perangkat mungkin tidak mendukung Wi-Fi RTT jika SoftAP atau tethering sedang digunakan. Untuk memeriksa apakah Wi-Fi RTT saat ini tersedia, panggil isAvailable().

Ketersediaan Wi-Fi RTT dapat berubah kapan saja. Aplikasi Anda harus mendaftarkan BroadcastReceiver untuk menerima ACTION_WIFI_RTT_STATE_CHANGED, yang dikirim ketika ketersediaan berubah. Ketika aplikasi Anda menerima intent siaran, aplikasi harus memeriksa kondisi ketersediaan saat ini dan menyesuaikan perilakunya dengan sesuai.

Contoh:

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

Untuk informasi selengkapnya, lihat Siaran.

Membuat permintaan ranging

Permintaan ranging (RangingRequest) dibuat dengan menentukan daftar AP atau peer Wi-Fi Aware yang dimintai range. Beberapa titik akses atau peer Wi-Fi Aware dapat ditentukan dalam satu permintaan ranging; jarak ke semua perangkat diukur dan dikembalikan.

Misalnya, permintaan dapat menggunakan metode addAccessPoint() untuk menentukan titik akses guna mengukur jarak:

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

Titik akses diidentifikasi oleh objek ScanResult, yang dapat diperoleh dengan memanggil WifiManager.getScanResult(). Anda dapat menggunakan addAccessPoints(List) untuk menambahkan beberapa titik akses dalam suatu batch.

Demikian pula, permintaan ranging dapat menambahkan peer Wi-Fi Aware menggunakan alamat MAC atau PeerHandle, menggunakan metode addWifiAwarePeer(MacAddress peer) dan addWifiAwarePeer(PeerHandle peer), secara berturut-turut. Untuk informasi lebih lanjut tentang menemukan peer Wi-Fi Aware, lihat dokumentasi Wi-Fi Aware.

Permintaan ranging

Aplikasi mengeluarkan permintaan ranging menggunakan metode WifiRttManager.startRanging() dan menyediakan hal berikut: RangingRequest untuk menentukan operasinya, Executor untuk menentukan konteks callback, dan RangingResultCallback untuk menerima hasil.

Contoh:

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

Operasi ranging dilakukan secara asinkron, dan hasil ranging dikembalikan dalam salah satu callback dari RangingResultCallback:

  • Jika keseluruhan operasi ranging gagal, callback onRangingFailure dipicu dengan kode status yang dijelaskan dalam RangingResultCallback. Kegagalan tersebut dapat terjadi jika layanan tidak dapat melakukan operasi ranging pada saat itu. Misalnya, karena Wi-Fi dinonaktifkan, karena aplikasi telah meminta terlalu banyak operasi ranging dan dibatasi, atau karena masalah izin.
  • Ketika operasi ranging selesai, callback onRangingResults dipicu dengan daftar hasil yang cocok dengan daftar permintaan, satu hasil untuk setiap permintaan. Urutan hasil tidak harus sesuai dengan urutan permintaan. Perhatikan bahwa operasi ranging mungkin selesai tetapi setiap hasil mungkin masih menunjukkan kegagalan pengukuran spesifik tersebut.

Menginterpretasikan hasil ranging

Setiap hasil yang dikembalikan oleh callback onRangingResults ditentukan oleh objek RangingResult. Pada setiap permintaan, lakukan hal berikut.

1. Identifikasi permintaan

Identifikasi permintaan berdasarkan informasi yang diberikan saat membuat RangingRequest: alamat MAC paling sering tersedia di ScanResult mengidentifikasi titik akses. Alamat MAC dapat diperoleh dari hasil ranging menggunakan metode getMacAddress().

Daftar hasil ranging mungkin berada dalam urutan berbeda dari peer (titik akses) yang ditentukan dalam permintaan ranging, jadi Anda harus menggunakan alamat MAC untuk mengidentifikasi peer, bukan urutan hasil.

2. Menentukan apakah setiap pengukuran berhasil

Untuk menentukan apakah suatu pengukuran berhasil, gunakan metode getStatus(). Nilai apa pun selain STATUS_SUCCESS menunjukkan kegagalan. Kegagalan berarti semua kolom lain dari hasil ini (kecuali identifikasi permintaan di atas) tidak valid, dan metode get* yang sesuai akan gagal dengan pengecualian IllegalStateException.

3. Mendapatkan hasil untuk setiap pengukuran yang berhasil

Untuk setiap pengukuran yang berhasil, Anda dapat mengambil nilai hasil dengan masing-masing metode get:

Perangkat Android yang mendukung Wi-Fi RTT

Tabel di bawah mencantumkan beberapa ponsel, titik akses, dan perangkat retail, pergudangan, dan pusat distribusi yang mendukung Wi-Fi RTT. Ini jauh dari komprehensif. Sebaiknya hubungi kami untuk mencantumkan produk dengan kemampuan RTT di sini.

Titik Akses (AP)

Produsen dan Model Tanggal Dukungan
Nest Wifi Pro (Wi-Fi 6E) Didukung
Compulab WILD AP Didukung
Google Wi-Fi Didukung
Router Google Nest Wi-Fi Didukung
Titik Google Nest Wi-Fi Didukung
Aruba AP-635 Didukung
Cisco 9130 Didukung
Cisco 9136 Didukung
Cisco 9166 Didukung
Cisco 9164 Didukung
Aruba AP-505 Didukung
Aruba AP-515 Didukung
Aruba AP-575 Didukung
Aruba AP-518 Didukung
Aruba AP-505H Didukung
Aruba AP-565 Didukung
Aruba AP-535 Didukung

Ponsel

Produsen dan Model Versi Android
Pixel 6 9.0+
Pixel 6 Pro 9.0+
Pixel 5 9.0+
Pixel 5a 9.0+
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 9 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 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+

Perangkat Pusat Retail, Pergudangan, dan Distribusi

Produsen dan Model Versi Android
PS20 Zebra 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+
EC30 Zebra 10,0+
Zebra ET51 10,0+
Zebra ET56 10,0+
Sepatu 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 dan HC) 10,0+
Zebra EC55 (WAN) 10,0+
Zebra WT6300 10,0+
Skorpio X5 10,0+