Lokasi Wi-Fi: ranging dengan RTT

Anda dapat menggunakan fungsionalitas 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 atau lebih titik akses, Anda dapat menggunakan algoritma 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 berbasis lokasi berbutir halus, seperti navigasi dalam ruangan, kontrol suara yang disatukan (misalnya, "Nyalakan lampu ini"), dan informasi berbasis lokasi (misalnya, "Apakah ada penawaran khusus untuk produk ini?").

Perangkat yang meminta 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. Wi-Fi RTT operasi 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.11mc. Wi-Fi RTT membutuhkan 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 ditentukan sebelumnya di aplikasi Anda. Anda yang memutuskan bagaimana menyimpan dan mengambil data ini.

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

Fitur ini memungkinkan aplikasi untuk meminta AP untuk menanyakan posisi mereka secara langsung daripada 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

  • Perangkat keras perangkat yang membuat permintaan ranging harus menerapkan standar FTM 802.11mc.
  • Perangkat yang membuat permintaan ranging harus menjalankan Android 9 (API level 28) atau lebih baru.
  • Perangkat yang membuat permintaan ranging harus mengaktifkan layanan lokasi dan pemindaian Wi-Fi dihidupkan (dalam Setelan > Lokasi).
  • Aplikasi yang membuat permintaan ranging harus memiliki izin ACCESS_FINE_LOCATION.
  • Jalur akses harus menerapkan standar FTEE IEEE 802.11mc.

Penyiapan

Untuk mengatur 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" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Izin ACCESS_FINE_LOCATION adalah izin berbahaya, jadi Anda harus memintanya saat runtime setiap kali pengguna ingin melakukan operasi pemindaian RTT. Aplikasi Anda perlu meminta izin pengguna jika izin belum diberikan. Untuk informasi lebih lanjut tentang izin runtime, lihat Minta Izin Aplikasi.

2. Periksa apakah perangkat mendukung Wi-Fi RTT

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

Kotlin

context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)

Java

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

3. Periksa 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 perangkat keras 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 maksud siaran, aplikasi harus memeriksa kondisi ketersediaan saat ini dan menyesuaikan perilakunya sesuai.

Sebagai 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 lebih lanjut, lihat Siaran.

Membuat permintaan ranging

Permintaan ranging (RangingRequest) dibuat dengan menentukan daftar AP atau rekan Wi-Fi Aware yang diminta range. Beberapa titik akses atau rekan 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 untuk 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();

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

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

Permintaan ranging

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

Sebagai 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 tidak sinkron, dan hasil rentang dikembalikan dalam salah satu panggilan balik 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 rentang 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 itu.

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: paling sering alamat MAC yang disediakan di ScanResult mengidentifikasi titik akses. Alamat MAC dapat diperoleh dari hasil ranging menggunakan metode getMacAddress().

Daftar hasil rentang mungkin dalam urutan berbeda dari rekan-rekan (jalur akses) yang ditentukan dalam permintaan ranging, jadi Anda harus menggunakan alamat MAC untuk mengidentifikasi rekan, bukan urutan hasil.

2. Tentukan apakah setiap pengukuran berhasil

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

3. Dapatkan hasil untuk setiap pengukuran yang berhasil

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