Kemampuan Wi-Fi Aware memungkinkan perangkat yang menjalankan Android 8.0 (API level 26) dan yang lebih tinggi untuk menemukan dan terhubung langsung satu sama lain tanpa jenis konektivitas lain di antaranya. Wi-Fi Aware juga dikenal sebagai Neighbor Awareness Networking (NAN).
Jaringan Wi-Fi Aware berfungsi dengan membentuk cluster dengan perangkat di sekitar, atau dengan membuat cluster baru jika perangkat tersebut adalah yang pertama di suatu area. Perilaku pengelompokan ini berlaku untuk seluruh perangkat dan dikelola oleh layanan sistem Wi-Fi Aware; aplikasi tidak memiliki kontrol atas perilaku pengelompokan. Aplikasi menggunakan Wi-Fi Aware API untuk berkomunikasi dengan layanan sistem Wi-Fi Aware, yang mengelola hardware Wi-Fi Aware di perangkat.
API Wi-Fi Aware memungkinkan aplikasi menjalankan operasi berikut:
Menemukan perangkat di sekitar: API memiliki mekanisme untuk menemukan perangkat di sekitar. Proses ini dimulai saat satu perangkat memublikasikan satu atau beberapa layanan yang dapat ditemukan. Kemudian, saat perangkat berlangganan ke satu atau beberapa layanan dan memasuki jangkauan Wi-Fi penayang, pelanggan akan menerima notifikasi bahwa penayang yang cocok telah ditemukan. Setelah pelanggan menemukan penayang, pelanggan dapat mengirim pesan singkat atau membuat koneksi jaringan dengan perangkat yang ditemukan. Perangkat dapat menjadi penayang dan pelanggan secara bersamaan.
Membuat koneksi jaringan: Setelah dua perangkat saling menemukan, keduanya dapat membuat koneksi jaringan Wi-Fi Aware dua arah tanpa titik akses.
Koneksi jaringan Wi-Fi Aware mendukung tingkat throughput yang lebih tinggi dalam jarak yang lebih jauh daripada koneksi Bluetooth. Jenis koneksi ini berguna untuk aplikasi yang berbagi data dalam jumlah besar antar-pengguna, seperti aplikasi berbagi foto.
Peningkatan Android 13 (API level 33)
Di perangkat yang menjalankan Android 13 (API level 33) dan yang lebih tinggi yang mendukung mode komunikasi
instan, aplikasi dapat menggunakan metode
PublishConfig.Builder.setInstantCommunicationModeEnabled() dan
SubscribeConfig.Builder.setInstantCommunicationModeEnabled() untuk
mengaktifkan atau menonaktifkan mode komunikasi instan untuk sesi penemuan penayang atau
pelanggan. Mode komunikasi instan mempercepat pertukaran pesan,
penemuan layanan, dan penyiapan jalur data apa pun sebagai bagian dari sesi penemuan
penerbit atau pelanggan. Untuk menentukan apakah perangkat mendukung mode komunikasi instan, gunakan metode isInstantCommunicationModeSupported().
Peningkatan Android 12 (level API 31)
Android 12 (level API 31) menambahkan beberapa peningkatan pada Wi-Fi Aware:
- Pada perangkat yang menjalankan Android 12 (API level 31) atau yang lebih tinggi, Anda dapat menggunakan
callback
onServiceLost()untuk mendapatkan notifikasi saat layanan yang telah ditemukan oleh aplikasi Anda hilang karena layanan tersebut berhenti atau keluar dari jangkauan. - Penyiapan jalur data Wi-Fi Aware telah disederhanakan. Versi sebelumnya menggunakan pesan L2 untuk memberikan alamat MAC pembuat, yang menyebabkan latensi. Pada perangkat yang menjalankan Android 12 dan yang lebih tinggi, penjawab (server) dapat dikonfigurasi untuk menerima pembanding yang artinya bahwa alamat MAC awal tidak perlu diketahui. Hal ini dapat mempercepat pengumpulan data dan memungkinkan beberapa link point-to-point hanya dengan satu permintaan jaringan.
- Aplikasi yang berjalan di Android 12 atau yang lebih tinggi dapat menggunakan
metode
WifiAwareManager.getAvailableAwareResources()untuk mendapatkan jumlah jalur data, sesi publikasi, dan sesi berlangganan yang saat ini tersedia. Hal ini dapat membantu aplikasi menentukan apakah ada cukup resource yang tersedia untuk menjalankan fungsi yang diinginkan.
Penyiapan awal
Untuk menyiapkan aplikasi agar menggunakan penemuan dan jaringan Wi-Fi Aware, lakukan langkah-langkah berikut:
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.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <!-- 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" />
Periksa apakah perangkat mendukung Wi-Fi Aware dengan
PackageManagerAPI, seperti yang ditunjukkan di bawah:Kotlin
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
Periksa apakah Wi-Fi Aware saat ini tersedia. Wi-Fi Aware mungkin ada di perangkat, tetapi mungkin tidak tersedia saat ini karena pengguna telah menonaktifkan Wi-Fi atau Lokasi. Bergantung pada kemampuan hardware dan firmware-nya, beberapa perangkat mungkin tidak mendukung Wi-Fi Aware jika Wi-Fi Langsung, SoftAP, atau tethering sedang digunakan. Untuk memeriksa apakah Wi-Fi Aware saat ini tersedia, panggil
isAvailable().Ketersediaan Wi-Fi Aware dapat berubah setiap saat. Aplikasi Anda harus mendaftarkan
BroadcastReceiveruntuk menerimaACTION_WIFI_AWARE_STATE_CHANGED, yang dikirim setiap kali ketersediaan berubah. Saat aplikasi Anda menerima intent siaran, aplikasi harus menghapus semua sesi yang ada (asumsikan bahwa layanan Wi-Fi Aware terganggu), lalu memeriksa status ketersediaan saat ini dan menyesuaikan perilakunya. Contoh:Kotlin
val wifiAwareManager = context.getSystemService(Context.WIFI_AWARE_SERVICE) as WifiAwareManager? val filter = IntentFilter(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED) val myReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { // discard current sessions if (wifiAwareManager?.isAvailable) { ... } else { ... } } } context.registerReceiver(myReceiver, filter)
Java
WifiAwareManager wifiAwareManager = (WifiAwareManager)context.getSystemService(Context.WIFI_AWARE_SERVICE) IntentFilter filter = new IntentFilter(WifiAwareManager.ACTION_WIFI_AWARE_STATE_CHANGED); BroadcastReceiver myReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // discard current sessions if (wifiAwareManager.isAvailable()) { ... } else { ... } } }; context.registerReceiver(myReceiver, filter);
Untuk informasi selengkapnya, lihat Siaran.
Mendapatkan sesi
Untuk mulai menggunakan Wi-Fi Aware, aplikasi Anda harus mendapatkan
WifiAwareSession dengan memanggil
attach(). Metode ini
melakukan hal berikut:
- Mengaktifkan hardware Wi-Fi Aware.
- Bergabung atau membentuk kumpulan Wi-Fi Aware.
- Membuat sesi Wi-Fi Aware dengan namespace unik yang berfungsi sebagai penampung untuk semua sesi penemuan yang dibuat di dalamnya.
Jika aplikasi berhasil dilampirkan, sistem akan menjalankan callback onAttached().
Callback ini menyediakan objek WifiAwareSession
yang harus digunakan aplikasi Anda untuk semua operasi sesi berikutnya. Aplikasi dapat menggunakan
sesi untuk memublikasikan layanan atau
berlangganan ke layanan.
Aplikasi Anda hanya boleh memanggil
attach() satu kali. Jika
aplikasi Anda memanggil attach()
beberapa kali, aplikasi akan menerima sesi yang berbeda untuk setiap panggilan, masing-masing dengan
namespace-nya sendiri. Hal ini dapat berguna dalam skenario yang kompleks, tetapi
umumnya harus dihindari.
Memublikasikan layanan
Agar layanan dapat ditemukan, panggil
metode publish(), yang
menggunakan parameter berikut:
PublishConfigmenentukan nama layanan dan properti konfigurasi lainnya, seperti filter pencocokan.DiscoverySessionCallbackmenentukan tindakan yang akan dijalankan saat peristiwa terjadi, seperti saat pelanggan menerima pesan.
Berikut contohnya:
Kotlin
val config: PublishConfig = PublishConfig.Builder() .setServiceName(AWARE_FILE_SHARE_SERVICE_NAME) .build() awareSession.publish(config, object : DiscoverySessionCallback() { override fun onPublishStarted(session: PublishDiscoverySession) { ... } override fun onMessageReceived(peerHandle: PeerHandle, message: ByteArray) { ... } })
Java
PublishConfig config = new PublishConfig.Builder() .setServiceName(“Aware_File_Share_Service_Name”) .build(); awareSession.publish(config, new DiscoverySessionCallback() { @Override public void onPublishStarted(PublishDiscoverySession session) { ... } @Override public void onMessageReceived(PeerHandle peerHandle, byte[] message) { ... } }, null);
Jika publikasi berhasil, metode callback
onPublishStarted()
akan dipanggil.
Setelah publikasi, saat perangkat yang menjalankan aplikasi pelanggan yang cocok berpindah ke
jangkauan Wi-Fi perangkat publikasi, pelanggan akan menemukan layanan tersebut. Saat
pelanggan menemukan penayang, penayang tidak akan menerima
notifikasi; namun, jika pelanggan mengirim pesan ke penayang, penayang akan menerima notifikasi. Jika hal itu terjadi, metode callback
onMessageReceived()
akan dipanggil. Anda dapat menggunakan argumen PeerHandle dari metode ini untuk mengirim pesan kembali ke pelanggan atau membuat koneksi ke pelanggan.
Untuk berhenti memublikasikan layanan, panggil
DiscoverySession.close().
Sesi penemuan dikaitkan dengan induknya,
WifiAwareSession. Jika sesi induk ditutup, sesi penemuan terkait juga akan ditutup. Meskipun objek yang dihapus juga ditutup, sistem tidak menjamin kapan sesi di luar cakupan ditutup, jadi sebaiknya Anda memanggil metode close() secara eksplisit.
Berlangganan ke layanan
Untuk berlangganan layanan, panggil
metode subscribe(),
yang menggunakan parameter berikut:
-
SubscribeConfigmenentukan nama layanan yang akan di-subscribe dan properti konfigurasi lainnya, seperti filter pencocokan. DiscoverySessionCallbackmenentukan tindakan yang akan dijalankan saat peristiwa terjadi, seperti saat penayang ditemukan.
Berikut contohnya:
Kotlin
val config: SubscribeConfig = SubscribeConfig.Builder() .setServiceName(AWARE_FILE_SHARE_SERVICE_NAME) .build() awareSession.subscribe(config, object : DiscoverySessionCallback() { override fun onSubscribeStarted(session: SubscribeDiscoverySession) { ... } override fun onServiceDiscovered( peerHandle: PeerHandle, serviceSpecificInfo: ByteArray, matchFilter: List<ByteArray> ) { ... } }, null)
Java
SubscribeConfig config = new SubscribeConfig.Builder() .setServiceName("Aware_File_Share_Service_Name") .build(); awareSession.subscribe(config, new DiscoverySessionCallback() { @Override public void onSubscribeStarted(SubscribeDiscoverySession session) { ... } @Override public void onServiceDiscovered(PeerHandle peerHandle, byte[] serviceSpecificInfo, List<byte[]> matchFilter) { ... } }, null);
Jika operasi berlangganan berhasil, sistem akan memanggil callback onSubscribeStarted() di aplikasi Anda. Karena Anda dapat menggunakan argumen SubscribeDiscoverySession dalam callback untuk berkomunikasi dengan penayang setelah aplikasi Anda menemukannya, Anda harus menyimpan referensi ini. Anda dapat memperbarui sesi berlangganan kapan saja dengan
memanggil
updateSubscribe()
pada sesi penemuan.
Pada tahap ini, langganan Anda menunggu penayang yang cocok masuk ke
jangkauan Wi-Fi. Jika hal ini terjadi, sistem akan menjalankan metode callback
onServiceDiscovered(). Anda dapat menggunakan argumen PeerHandle
dari callback ini untuk mengirim pesan atau
membuat koneksi ke penayang tersebut.
Untuk berhenti berlangganan layanan, panggil
DiscoverySession.close().
Sesi penemuan dikaitkan dengan induknya,
WifiAwareSession. Jika sesi induk ditutup, sesi penemuan yang terkait juga akan ditutup. Meskipun objek yang dihapus juga ditutup, sistem tidak menjamin kapan sesi di luar cakupan ditutup, jadi sebaiknya Anda memanggil metode close() secara eksplisit.
Kirim pesan
Untuk mengirim pesan ke perangkat lain, Anda memerlukan beberapa objek berikut:
DiscoverySession. Objek ini memungkinkan Anda memanggilsendMessage(). Aplikasi Anda mendapatkanDiscoverySessiondengan memublikasikan layanan atau berlangganan ke layanan.PeerHandleperangkat lain, untuk merutekan pesan. Aplikasi Anda mendapatkanPeerHandleperangkat lain dengan salah satu dari dua cara berikut:- Aplikasi Anda memublikasikan layanan dan menerima pesan dari pelanggan.
Aplikasi Anda mendapatkan
PeerHandlepelanggan dari callbackonMessageReceived(). - Aplikasi Anda berlangganan ke layanan. Kemudian, saat menemukan penayang yang cocok, aplikasi Anda akan mendapatkan
PeerHandlepenayang dari callbackonServiceDiscovered().
- Aplikasi Anda memublikasikan layanan dan menerima pesan dari pelanggan.
Aplikasi Anda mendapatkan
Untuk mengirim pesan, panggil
sendMessage(). Callback
berikut mungkin akan terjadi:
- Saat pesan berhasil diterima oleh peer, sistem akan memanggil callback
onMessageSendSucceeded()di aplikasi pengirim. - Saat peer menerima pesan, sistem akan memanggil callback
onMessageReceived()di aplikasi penerima.
Meskipun PeerHandle diperlukan untuk berkomunikasi dengan peer, Anda tidak boleh
mengandalkannya sebagai ID permanen peer. ID tingkat yang lebih tinggi dapat digunakan oleh aplikasi--disematkan dalam layanan penemuan itu sendiri atau dalam pesan berikutnya. Anda dapat menyematkan ID di layanan penemuan dengan
metode
setMatchFilter()
atau
setServiceSpecificInfo()
dari PublishConfig atau
SubscribeConfig. Metode
setMatchFilter() memengaruhi penemuan, sedangkan metode
setServiceSpecificInfo() tidak memengaruhi penemuan.
Menyematkan ID dalam pesan berarti mengubah array byte pesan untuk menyertakan ID (misalnya, sebagai beberapa byte pertama).
Membuat koneksi
Wi-Fi Aware mendukung jaringan klien-server antara dua perangkat Wi-Fi Aware.
Untuk menyiapkan koneksi klien-server:
Gunakan penemuan Wi-Fi Aware untuk memublikasikan layanan (di server) dan berlangganan ke layanan (di klien).
Setelah pelanggan menemukan penayang, kirim pesan dari pelanggan ke penayang.
Mulai
ServerSocketdi perangkat penayang dan tetapkan atau dapatkan portnya:Kotlin
val ss = ServerSocket(0) val port = ss.localPort
Java
ServerSocket ss = new ServerSocket(0); int port = ss.getLocalPort();
Gunakan
ConnectivityManageruntuk meminta jaringan Wi-Fi Aware pada penayang menggunakanWifiAwareNetworkSpecifier, dengan menentukan sesi penemuan danPeerHandlepelanggan, yang Anda peroleh dari pesan yang dikirim oleh pelanggan:Kotlin
val networkSpecifier = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle) .setPskPassphrase("somePassword") .setPort(port) .build() val myNetworkRequest = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(networkSpecifier) .build() val callback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { ... } override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { ... } override fun onLost(network: Network) { ... } } connMgr.requestNetwork(myNetworkRequest, callback);
Java
NetworkSpecifier networkSpecifier = new WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle) .setPskPassphrase("somePassword") .setPort(port) .build(); NetworkRequest myNetworkRequest = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(networkSpecifier) .build(); ConnectivityManager.NetworkCallback callback = new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { ... } @Override public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { ... } @Override public void onLost(Network network) { ... } }; ConnectivityManager connMgr.requestNetwork(myNetworkRequest, callback);
Setelah penayang meminta jaringan, penayang harus mengirim pesan kepada pelanggan.
Setelah pelanggan menerima pesan dari penayang, minta jaringan Wi-Fi Aware pada pelanggan menggunakan metode yang sama seperti pada penayang. Jangan tentukan port saat membuat
NetworkSpecifier. Metode callback yang sesuai akan dipanggil saat koneksi jaringan tersedia, berubah, atau terputus.Setelah metode
onAvailable()dipanggil pada pelanggan, objekNetworkakan tersedia, yang dapat Anda gunakan untuk membukaSocketuntuk berkomunikasi denganServerSocketdi penayang, tetapi Anda perlu mengetahui alamat dan port IPv6ServerSocket. Anda mendapatkannya dari objekNetworkCapabilitiesyang disediakan dalam callbackonCapabilitiesChanged():Kotlin
val peerAwareInfo = networkCapabilities.transportInfo as WifiAwareNetworkInfo val peerIpv6 = peerAwareInfo.peerIpv6Addr val peerPort = peerAwareInfo.port ... val socket = network.getSocketFactory().createSocket(peerIpv6, peerPort)
Java
WifiAwareNetworkInfo peerAwareInfo = (WifiAwareNetworkInfo) networkCapabilities.getTransportInfo(); Inet6Address peerIpv6 = peerAwareInfo.getPeerIpv6Addr(); int peerPort = peerAwareInfo.getPort(); ... Socket socket = network.getSocketFactory().createSocket(peerIpv6, peerPort);
Setelah selesai dengan koneksi jaringan, panggil
unregisterNetworkCallback().
Menentukan jarak peer dan penemuan kemampuan penentuan lokasi
Perangkat dengan kemampuan lokasi Wi-Fi RTT dapat langsung mengukur jarak ke peer dan menggunakan informasi ini untuk membatasi penemuan layanan Wi-Fi Aware.
Wi-Fi RTT API memungkinkan pengukuran jarak langsung ke peer Wi-Fi Aware menggunakan alamat MAC atau PeerHandle-nya.
Penemuan Wi-Fi Aware dapat dibatasi hanya untuk menemukan layanan dalam
geofence tertentu. Misalnya, Anda dapat menyiapkan pembatasan wilayah yang memungkinkan penemuan
perangkat yang memublikasikan layanan "Aware_File_Share_Service_Name" yang tidak
lebih dekat dari 3 meter (ditentukan sebagai 3.000 mm) dan tidak lebih jauh dari 10 meter
(ditentukan sebagai 10.000 mm).
Untuk mengaktifkan pembatasan wilayah, baik penayang dan pelanggan harus melakukan tindakan:
Penayang harus mengaktifkan pengukuran jarak pada layanan yang dipublikasikan menggunakan setRangingEnabled(true).
Jika penayang tidak mengaktifkan rentang, batasan pembatasan wilayah apa pun yang ditentukan oleh pelanggan akan diabaikan dan penemuan normal akan dilakukan, dengan mengabaikan jarak.
Pelanggan harus menentukan pembatasan wilayah menggunakan beberapa kombinasi setMinDistanceMm dan setMaxDistanceMm.
Untuk kedua nilai tersebut, jarak yang tidak ditentukan menunjukkan bahwa tidak ada batas. Hanya menentukan jarak maksimum berarti jarak minimumnya adalah 0. Hanya menentukan jarak minimum berarti tidak ada jarak maksimum.
Saat layanan peer ditemukan dalam pembatasan wilayah, callback onServiceDiscoveredWithinRange akan dipicu, yang memberikan jarak terukur ke peer. Wi-Fi RTT API langsung kemudian dapat dipanggil seperlunya untuk mengukur jarak di lain waktu.