Bergabunglah bersama kami di ⁠#Android11: The Beta Launch Show pada tanggal 3 Juni!

Ringkasan Wi-Fi Aware

Kemampuan Wi-Fi Aware memungkinkan perangkat yang menjalankan Android 8.0 (API level 26) dan yang lebih tinggi untuk saling menemukan dan terhubung langsung tanpa ada jenis konektivitas lain di antara keduanya. Wi-Fi Aware juga dikenal sebagai Neighbor Awareness Networking (NAN).

Jaringan Wi-Fi Aware berfungsi dengan membentuk kumpulan perangkat sekitar, atau dengan membuat kumpulan baru jika hanya ada satu perangkat baru di suatu area. Perilaku pengelompokan ini berlaku untuk seluruh perangkat dan dikelola oleh layanan sistem Wi-Fi Aware; aplikasi tidak memiliki kontrol terhadap perilaku pengelompokan. Aplikasi menggunakan API Wi-Fi Aware 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 lain: API tersebut memiliki mekanisme untuk menemukan perangkat lain di sekitar. Prosesnya dimulai saat satu perangkat memublikasikan satu atau beberapa layanan yang dapat ditemukan. Lalu, ketika perangkat berlangganan ke satu atau beberapa layanan dan memasuki jangkauan Wi-Fi penayang, pelanggan tersebut akan menerima notifikasi bahwa penayang yang cocok telah ditemukan. Setelah 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 saling menemukan, kedua perangkat dapat membuat koneksi jaringan Wi-Fi Aware dua arah tanpa titik akses.

Koneksi jaringan Wi-Fi Aware mendukung tingkat throughput yang lebih tinggi dengan jarak yang lebih jauh dibandingkan dengan koneksi Bluetooth . Jenis sambungan ini berguna untuk aplikasi yang berbagi data dalam jumlah besar di antara pengguna, seperti aplikasi berbagi foto.

Penyiapan awal

Untuk menyiapkan aplikasi Anda dalam menggunakan penemuan dan jaringan Wi-Fi Aware, lakukan beberapa langkah berikut:

  1. 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" />
        
  2. Periksa apakah perangkat mendukung Wi-Fi Aware dengan PackageManager API, seperti yang ditampilkan di bawah ini:

    Kotlin

        context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)
        

    Java

        context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
        
  3. 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, 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 BroadcastReceiver untuk menerima ACTION_WIFI_AWARE_STATE_CHANGED yang dikirim setiap ketersediaan berubah. Saat aplikasi Anda menerima intent siaran, intent tersebut harus menghapus semua sesi yang ada (asumsikan bahwa layanan Wi-Fi Aware diganggu), lalu periksa status ketersediaan saat ini dan sesuaikan perilakunya dengan tepat. Misalnya:

    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 beberapa 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 terhubung, sistem akan menjalankan callback onAttached(). Callback ini memberikan objek WifiAwareSession yang harus digunakan aplikasi Anda untuk semua operasi sesi berikutnya. Aplikasi dapat menggunakan sesi tersebut untuk memublikasikan layanan atau berlangganan ke layanan.

Aplikasi Anda seharusnya hanya memanggil attach() sebanyak satu kali. Jika memanggil attach() beberapa kali, aplikasi Anda akan menerima sesi yang berbeda untuk setiap panggilan, masing-masing dengan namespace-nya sendiri. Tindakan ini dapat berguna dalam skenario yang kompleks, tetapi secara umum harus dihindari.

Memublikasikan layanan

Untuk membuat layanan dapat ditemukan, panggil metode publish() yang menggunakan beberapa parameter berikut:

  • PublishConfig menentukan nama layanan dan properti konfigurasi lainnya, seperti filter pencocokan.
  • DiscoverySessionCallback menentukan tindakan yang akan dijalankan saat peristiwa terjadi, seperti saat pelanggan menerima sebuah 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, maka metode callback onPublishStarted() akan dipanggil.

Setelah publikasi, saat perangkat yang menjalankan aplikasi pelanggan yang cocok memasuki jangkauan Wi-Fi perangkat penayang, pelanggan tersebut akan menemukan layanan. Saat pelanggan menemukan penayang, penayang itu tidak akan menerima notifikasi; tetapi, jika pelanggan mengirim pesan ke penayang, maka penayang itu akan menerima sebuah notifikasi. Saat 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 dengannya.

Untuk berhenti memublikasikan layanan, panggil DiscoverySession.close(). Sesi penemuan dikaitkan dengan WifiAwareSession induknya. Jika sesi induk ditutup, sesi penemuan terkaitnya juga akan ditutup. Meskipun objek yang dihapus juga ditutup, sistem tidak menjamin saat sesi di luar cakupan juga ditutup, sehingga kami merekomendasikan Anda memanggil metode close() secara eksplisit.

Berlangganan ke layanan

Untuk berlangganan layanan, panggil metode subscribe(), yang akan menggunakan beberapa parameter berikut:

  • SubscribeConfig menentukan nama layanan yang akan dijadikan langganan dan properti konfigurasi lainnya, seperti filter pencocokan.
  • DiscoverySessionCallback menentukan 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 dapat menggunakan argumen SubscribeDiscoverySession di callback tersebut untuk berkomunikasi dengan penayang setelah aplikasi Anda ditemukan, Anda harus menyimpan referensi ini. Anda dapat memperbarui sesi berlangganan kapan saja dengan memanggil updateSubscribe() di sesi penemuan.

Pada tahap ini, langganan Anda menunggu penayang yang cocok untuk masuk ke dalam jangkauan Wi-Fi. Saat 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 WifiAwareSession induknya. Jika sesi induk ditutup, sesi penemuan terkaitnya juga akan ditutup. Meskipun objek yang dihapus juga ditutup, sistem tidak menjamin saat sesi di luar cakupan juga ditutup, sehingga kami merekomendasikan Anda memanggil metode close() secara eksplisit.

Mengirim pesan

Untuk mengirim pesan ke perangkat lain, Anda memerlukan beberapa objek berikut:

Untuk mengirim pesan, panggil sendMessage(). Beberapa callback berikut mungkin terjadi:

  • Saat pesan berhasil diterima oleh peer, sistem akan memanggil callback onMessageSendSucceeded() di aplikasi yang mengirim.
  • Saat peer menerima pesan, sistem akan memanggil callback onMessageReceived() di aplikasi yang menerima.

Meskipun PeerHandle diperlukan untuk berkomunikasi dengan peer, Anda tidak boleh mengandalkannya sebagai ID peer permanen. ID dengan tingkat lebih tinggi dapat digunakan oleh aplikasi--disematkan dalam layanan penemuan itu sendiri atau di pesan berikutnya. Anda dapat menyematkan ID di layanan penemuan dengan metode setMatchFilter() atau setServiceSpecificInfo() pada PublishConfig atau SubscribeConfig. Metode setMatchFilter() akan memengaruhi penemuan, sedangkan metode setServiceSpecificInfo() tidak.

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:

  1. Gunakan penemuan Wi-Fi Aware untuk memublikasikan layanan (di server) dan berlangganan ke layanan (di klien).

  2. Setelah pelanggan menemukan penayang, kirim pesan dari pelanggan ke penayang.

  3. Mulai ServerSocket di 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();
        
  4. Gunakan ConnectivityManager untuk meminta jaringan Wi-Fi Aware di penayang menggunakan WifiAwareNetworkSpecifier, yang menentukan sesi penemuan dan PeerHandle pelanggan, yang Anda dapatkan dari pesan yang dikirimkan 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(networkRequest, 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(networkRequest, callback);
        
  5. Meminta jaringan Wi-Fi Aware di pelanggan menggunakan metode yang sama seperti di penayang. Jangan menentukan port saat membuat NetworkSpecifier. Metode callback yang sesuai akan dipanggil saat koneksi jaringan tersedia, diubah, atau hilang.

  6. Setelah metode onAvailable() dipanggil di pelanggan, objek Network akan tersedia yang dapat membuka Socket untuk berkomunikasi dengan ServerSocket di penayang, tetapi Anda harus mengetahui alamat dan port IPv6 ServerSocket. Dapatkan semua itu dari objek NetworkCapabilities yang diberikan dalam callback onCapabilitiesChanged():

    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);
        
  7. Setelah selesai dengan koneksi jaringan, panggil unregisterNetworkCallback().

Menentukan jarak peer dan penemuan kemampuan penentuan lokasi

Perangkat dengan kemampuan lokasi Wi-Fi RTT dapat mengukur langsung jarak ke peer dan menggunakan informasi ini untuk membatasi penemuan layanan Wi-Fi Aware.

Wi-Fi RTT API memungkinkan penentuan langsung jarak ke peer Wi-Fi Aware menggunakan alamat MAC atau PeerHandle-nya.

Penemuan Wi-Fi Aware dapat dibatasi hanya untuk menemukan layanan dalam pembatasan wilayah tertentu. Misalnya, Anda dapat menyiapkan pembatasan wilayah yang memungkinkan penemuan perangkat yang memublikasikan layanan "Aware_File_Share_Service_Name" yang berjarak minimal 3 meter (ditentukan sebagai 3.000 mm) dan maksimal 10 meter (ditentukan sebagai 10.000 mm).

Untuk mengaktifkan pembatasan wilayah, baik penayang dan pelanggan harus melakukan tindakan:

  • Penayang harus mengaktifkan penentuan jarak pada layanan yang dipublikasikan menggunakan setRangingEnabled(true).

    Jika penayang tidak mengaktifkan penentuan jarak, maka batas pembatasan wilayah yang ditentukan oleh pelanggan akan diabaikan dan penemuan normal akan dilakukan, 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 menunjukkan bahwa jarak minimum adalah 0. Hanya menentukan jarak minimum menunjukkan bahwa tidak ada jarak maksimum.

Saat layanan peer ditemukan di dalam pembatasan wilayah, callback onServiceDiscoveredWithinRange akan terpicu, yang memberikan jarak terukur ke peer. Kemudian, Wi-Fi RTT API langsung dapat dipanggil jika diperlukan untuk mengukur jarak di waktu mendatang.