Wi-Fi Aware'e genel bakış

Wi-Fi Aware özellikleri, Android 8.0 (API düzeyi 26) ve sonraki sürümleri çalıştıran cihazlarda ve başka tür bir iletişim kurmadan birbirleriyle doğrudan bağlantı kurmalarını gerçekten çok iyi. Wi-Fi Aware, Neighbor Awareness Networking (NAN) olarak da bilinir.

Wi-Fi Aware ağ iletişimi, komşu cihazlarla kümeler oluşturarak çalışır veya kümedeki ilk cihaz olması halinde yeni bir küme oluşturarak. Bu gruplandırma davranışı cihazın tamamı için geçerlidir ve Wi-FiAware sistem hizmeti tarafından yönetilir. Uygulamaların gruplandırma davranışı üzerinde hiçbir kontrolü yoktur. Uygulamaların kullanımı Wi-Fi Aware sistem hizmetiyle iletişim kurmak için Wi-Fi Aware API'lerini kullanır. cihazdaki Wi-Fi-Aware donanım üzerinde çalışır.

Wi-Fi Aware API'ler, uygulamaların aşağıdaki işlemleri gerçekleştirmesine izin verir:

  • Diğer cihazları keşfetme: API, yakındaki diğer cihazları bulmak için bir mekanizmaya sahiptir. İşlem, bir cihaz bir veya daha fazla bulunabilir hizmeti yayınladığında başlar. Ardından, cihaz bir veya daha fazla uygulamaya abone olduğunda yayıncının kablosuz ağ aralığına girer ve abone olan eşleşen bir yayıncının bulunduğuna dair bildirim. bir yayıncı keşfettiğinde, aboneden bir kısa video veya bulunan cihazla ağ bağlantısı kurun. Cihazlar aynı anda hem yayıncı hem de abone olabilir.

  • Ağ bağlantısı oluşturma: İki cihaz birbirini keşfettikten sonra erişim noktası olmadan iki yönlü bir Kablosuz Farkında Ağ bağlantısı oluşturabilir.

Wi-Fi Aware ağ bağlantıları, Bluetooth bağlantılarına kıyasla daha uzun mesafelerde daha yüksek aktarım hızlarını destekler. Bu tür bağlantılar, fotoğraf paylaşımı uygulamaları gibi kullanıcılar arasında büyük miktarda veri paylaşan uygulamalar için kullanışlıdır.

Android 13 (API düzeyi 33) geliştirmeleri

Android 13 (API düzeyi 33) ve sonraki sürümleri çalıştıran ve Anında Arama özelliğini destekleyen cihazlarda iletişim modundaysa uygulamalar PublishConfig.Builder.setInstantCommunicationModeEnabled() ve SubscribeConfig.Builder.setInstantCommunicationModeEnabled() yöntemini kullanarak bir yayıncı veya abone için anında iletişim modunu etkinleştir veya devre dışı bırak ele alacağız. Anında iletişim modu, mesaj alışverişini hızlandırır, ve yayıncının ya da abonenin parçası olarak ayarlanmış herhangi bir veri yolu ele alacağız. Bir cihazın anlık iletişimi destekleyip desteklemediğini belirlemek için modunda incelemek için isInstantCommunicationModeSupported() yöntemini kullanın.

Android 12 (API düzeyi 31) geliştirmeleri

Android 12 (API düzeyi 31), kablosuz ağ farkındalığı özelliğine bazı iyileştirmeler ekler:

  • Android 12 (API düzeyi 31) veya sonraki sürümleri çalıştıran cihazlarda onServiceLost() veya başka herhangi bir nedenle uygulamanızın keşfedilen bir hizmeti kaybetmesi durumunda durması veya kapsama alanının dışına çıkması gibi bir durum söz konusu.
  • Wi-Fi Aware veri yollarının kurulumu basitleştirildi. Önceki sürümlerde, başlatıcının MAC adresini sağlamak için L2 mesajlaşma kullanılıyordu. Bu da gecikmeye neden oluyordu. Android 12 ve sonraki sürümleri çalıştıran cihazlarda yanıtlayan (sunucu), herhangi bir eşlemeyi kabul edecek şekilde yapılandırılabilir. Yani başlatıcının MAC adresini önceden bilmesi gerekmez. Bu, veri yolunun başlatılmasını hızlandırır ve yalnızca bir ağ isteğiyle birden fazla noktadan noktaya bağlantı sağlar.
  • Android 12 veya sonraki sürümleri çalıştıran uygulamalar WifiAwareManager.getAvailableAwareResources() yöntemindeki mevcut veri yollarının sayısını, yayınlama oturumlarını, ve abone oturumlarının sayısını artırın. Bu, uygulamanın aynı zamanda istenen işlevleri yerine getirmek için yeterli kaynak olması gerekir.

İlk kurulum

Uygulamanızı, Wi-Fi Aware keşif ve ağ özelliklerini kullanacak şekilde ayarlamak için şu işlemi gerçekleştirin: şu adımları uygulayın:

  1. Uygulamanızın manifest dosyasında aşağıdaki izinleri isteyin:

    <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" />
  2. Cihazın, aşağıdaki gibi PackageManager API ile kablosuz ağ farkındalığını destekleyip desteklemediğini kontrol edin:

    Kotlin

    context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)

    Java

    context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
  3. Wi-Fi Aware özelliğinin şu anda kullanılabilir olup olmadığını kontrol edin. Wi-Fi Aware şu cihazlarda olabilir: ancak kullanıcı devre dışı bıraktığından şu anda kullanılamıyor olabilir Kablosuz veya Konum. Donanım ve donanım yazılımı özelliklerine bağlı olarak bazı cihazlar Wi-Fi Direct, SoftAP veya tethering özelliği açıksa Wi-Fi Aware'i desteklemeyebilir pek de iyi olmadığını unutmayın. Wi-Fi Aware'in şu anda kullanılabilir olup olmadığını kontrol etmek için şu numarayı arayın: isAvailable()

    Wi-Fi Aware özelliğinin kullanılabilirliği herhangi bir zamanda değişebilir. Uygulamanız, kullanılabilirlik durumu değiştiğinde gönderilen ACTION_WIFI_AWARE_STATE_CHANGED almak için bir BroadcastReceiver kaydetmelidir. Uygulamanız yayın intent'ini aldığında mevcut tüm oturumları reddetmeli (Wi-Fi Aware hizmetinin kesintiye uğradığı varsayılır), ardından mevcut kullanılabilirlik durumunu kontrol edip davranışını buna göre ayarlamalıdır. Örnek:

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

Daha fazla bilgi için Yayınlar başlıklı makaleyi inceleyin.

Oturum edinme

Wi-Fi Aware'i kullanmaya başlamak için uygulamanızın attach() çağrısı yaparak bir WifiAwareSession alması gerekir. Bu yöntem şunları yapar:

  • Wi-Fi Aware donanımını açar.
  • Kablosuz Ağa Duyarlı bir kümeye katılır veya bir küme oluşturur.
  • Farklı bir ad alanına sahip bir kablosuz ağa duyarlı oturum oluşturur içinde oluşturulan tüm keşif oturumları için bir kapsayıcıdır.

Uygulama başarıyla eklenirse, sistem onAttached() geri arama. Bu geri çağırma, bir WifiAwareSession nesnesi sağlar kullanın. Bir uygulama, bir hizmet yayınlama veya bir hizmete abone olun.

Uygulamanız Yalnızca bir kez attach(). Eğer uygulamanız attach() numarasını çağırıyor Bu işlem her çağrı için farklı bir oturum alır. Bu oturumların her biri kendi ad alanını kullanır. Bu, karmaşık senaryolarda işe yarayabilir ancak kaçınılması gerekir.

çağrısı yapın.

Hizmet yayınlama

Bir hizmeti bulunabilir hale getirmek için aşağıdaki parametreleri alan publish() yöntemini çağırın:

  • PublishConfig, hizmet ve diğer yapılandırma özelliklerini (örneğin, eşleştirme filtresi) kullanabilirsiniz.
  • DiscoverySessionCallback, abone bir mesaj aldığında olduğu gibi etkinlikler gerçekleştiğinde uygulanacak işlemleri belirtir.

Aşağıda bununla ilgili bir örnek verilmiştir:

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

Yayın başarılı olursa onPublishStarted(). çağrılır.

Yayınlamadan sonra, eşleşen abone uygulamalarını çalıştıran cihazlar yayın cihazının kablosuz aralığına girdiğinde aboneler hizmeti keşfeder. Bir abone yayıncıyı keşfettiğinde yayıncı bildirim almaz. Ancak abone yayıncıya mesaj gönderirse yayıncı bildirim alır. Böyle bir durumda, onMessageReceived(). çağrılır. Aboneye mesaj göndermek veya aboneyle bağlantı oluşturmak için bu yöntemdeki PeerHandle bağımsız değişkenini kullanabilirsiniz.

Hizmetin yayınlanmasını durdurmak için DiscoverySession.close() numaralı telefonu arayın. Keşif oturumları, üst öğeleriyle WifiAwareSession ilişkilendirilir. Üst oturum bu platformla ilişkili keşif oturumları da kapatılır. Silinirken kapalı olduğuna göre sistem, kapsam dışında kalmanın oturumlar kapatıldığı için, bu işlemi açıkça close() çağrısı yapmanızı öneririz. yöntemlerine göz atın.

Bir hizmete abone olma

Bir hizmete abone olmak için aşağıdaki parametreleri alan subscribe() yöntemini çağırın:

  • SubscribeConfig, abone olma hizmeti ve diğer yapılandırma özelliklerine (örneğin, filtresini uygulayabilirsiniz.
  • DiscoverySessionCallback, yayıncı bulunması gibi etkinlikler gerçekleştiğinde yürütülecek işlemler.

Aşağıda bununla ilgili bir örnek verilmiştir:

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

Abone olma işlemi başarılı olursa sistem, uygulamanızdaki onSubscribeStarted() geri çağırma işlevini çağırır. Uygulamanız bir yayıncı keşfettikten sonra yayıncıyla iletişim kurmak için geri çağırma işlevindeki SubscribeDiscoverySession bağımsız değişkenini kullanabileceğiniz için bu referansı kaydetmeniz gerekir. Abone olma oturumunu istediğiniz zaman arama updateSubscribe(). ele alacağız.

Bu noktada aboneliğiniz, eşleşen yayıncıların gelmesini bekler Kablosuz menzili. Bu durumda sistem, onServiceDiscovered() geri çağırma yöntemini yürütür. PeerHandle kullanabilirsiniz argümanını mesaj göndermek için kullanın veya Bu yayıncıyla bağlantı oluşturun.

Bir hizmete aboneliğinizi sonlandırmak için şu numarayı arayın: DiscoverySession.close() Keşif oturumları, üst öğeleriyle WifiAwareSession ilişkilendirilir. Üst oturum bu platformla ilişkili keşif oturumları da kapatılır. Silinirken kapalı olduğu için sistem, uygulamanın kapsam dışında olduğunu oturumlar kapatılmıştır. Bu nedenle, açıkça close() çağrısı yapmanızı öneririz. yöntemlerine göz atın.

Mesaj gönder

Başka bir cihaza mesaj göndermek için aşağıdaki nesnelere ihtiyacınız vardır:

Mesaj göndermek için sendMessage() numaralı telefonu arayın. Ardından aşağıdaki geri çağırmalar gerçekleşebilir:

  • Mesaj eş taraf tarafından başarıyla alındığında sistem, gönderen uygulamasında onMessageSendSucceeded() geri çağırma işlevini çağırır.
  • Eş, mesaj aldığında sistem, alıcı uygulamasında onMessageReceived() geri çağırma işlevini çağırır.

PeerHandle, eşlerle iletişim kurmak için gerekli olsa da eşlerin kalıcı tanımlayıcısı olarak bu değere güvenmemeniz gerekir. Daha üst düzey tanımlayıcılar keşif hizmetinin kendisinde yerleşik uygulama tarafından veya mesajları takip eder. PublishConfig veya SubscribeConfig yöntemiyle setMatchFilter() veya setServiceSpecificInfo() yöntemini kullanarak keşif hizmetine bir tanımlayıcı yerleştirebilirsiniz. setMatchFilter() yöntemi keşfi etkilerken setServiceSpecificInfo() yöntemi keşfi etkilemez.

Bir iletiye tanımlayıcı yerleştirmek, ileti bayt dizisinin bir tanımlayıcı ekleyin (örneğin, ilk birkaç bayt olarak).

Bağlantı oluşturma

Wi-Fi Aware iki Wi-Fi duyarlı cihaz arasında istemci-sunucu ağını destekler.

İstemci-sunucu bağlantısını ayarlamak için:

  1. Bir hizmet yayınlamak için Wi-Fi Aware keşif özelliğini kullanın ( sunucu) ve bir hizmete abone olun ( müşteri).

  2. Abone, yayıncıyı keşfettikten sonra aboneden yayıncıya bir ileti gönderebilirsiniz.

  3. Yayıncı cihazında bir ServerSocket başlatın ve bağlantı noktasını ayarlayın veya alın:

    Kotlin

    val ss = ServerSocket(0)
    val port = ss.localPort

    Java

    ServerSocket ss = new ServerSocket(0);
    int port = ss.getLocalPort();
  4. ConnectivityManager kullanarak bir WifiAwareNetworkSpecifier, Keşif oturumunu ve Abonenin PeerHandle. (abone tarafından iletilen mesajdan edindiğiniz):

    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);
  5. Yayıncı bir ağ istediğinde aboneye mesaj göndermelidir.

  6. Abone, yayıncıdan mesaj aldıktan sonra yayıncıdakiyle aynı yöntemi kullanarak abonede kablosuz ağ farkındalığı ağı isteyin. NetworkSpecifier oluştururken bağlantı noktası belirtmeyin. İlgili içeriği oluşturmak için kullanılan uygun geri çağırma yöntemleri çağrılır: kullanılabilir, değiştirilmiş veya kaybolabilir.

  7. Abonede onAvailable() yöntemi çağrıldıktan sonra, Network nesnesi şununla kullanılabilir: Bunu iletişim kurmak için Socket yayıncıda ServerSocket ile iletişim kurmanız gerekiyor, ancak ServerSocket kullanıcısının IPv6 adresi ve bağlantı noktası. Aşağıdakileri onCapabilitiesChanged() geri çağırma işlevinde sağlanan NetworkCapabilities nesnesinden alırsınız:

    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);
  8. Ağ bağlantısıyla işiniz bittiğinde şunu arayın: unregisterNetworkCallback().

Benzerlere göre ve konuma duyarlı keşif

Kablosuz RTT konumuna sahip bir cihaz özellikler, benzerlerle mesafeyi doğrudan ölçebilir ve bu bilgiyi kullanarak Wi-Fi Aware hizmet keşfini kısıtlar.

Wi-Fi RTT API, MAC adresini veya PeerHandle'ı kullanarak bir Wi-Fi Aware eşle doğrudan menzil belirlemenize olanak tanır.

Wi-Fi Aware keşfi, yalnızca belirli bir ele alacağız. Örneğin, dünyanın dört bir yanındaki kişilerin keşfedilmesine olanak tanıyan bir "Aware_File_Share_Service_Name" hizmeti yayınlayan cihazın 3 metreden yakın (3.000 mm olarak belirtilir) ve 10 metreden uzak olmamak üzere (10.000 mm olarak belirtilir).

Coğrafi sınırlamayı etkinleştirmek için hem yayıncının hem de abonenin işlem yapması gerekir:

  • Yayıncı, setRangingEnabled(true) kullanarak yayınlanan hizmette menzil belirlemeyi etkinleştirmelidir.

    Yayıncı, menzil belirlemeyi etkinleştirmezse abone tarafından belirtilen tüm coğrafi çit kısıtlamaları yok sayılır ve mesafe dikkate alınmadan normal keşif gerçekleştirilir.

  • Abone, setMinMesafeMm ve setMaxLengthMm.

    Her iki değer için de belirtilmemiş mesafe, sınır olmadığını gösterir. Yalnızca belirtiliyor maksimum mesafe, minimum mesafenin 0 olduğu anlamına gelir. Yalnızca minimum mesafenin belirtilmesi, maksimum mesafenin olmadığı anlamına gelir.

Coğrafi sınır içinde bir eş hizmet keşfedildiğinde onServiceKeşfetedWithinRange geri çağırma tetiklenir. Bu, eşle ölçülen mesafeyi sağlar. İlgili içeriği oluşturmak için kullanılan Daha sonra, mesafe ölçümü için gerektiğinde doğrudan Wi-Fi RTT API çağrılabilir devam edebilir.