Wi-Fi Aware özellikleri, Android 8.0 (API düzeyi 26) ve sonraki sürümleri çalıştıran cihazların, aralarında başka hiçbir bağlantı olmadan birbirlerini keşfedip doğrudan bağlantı kurmalarını sağlar. Wi-Fi Aware, Komşu Algılama Ağ İletişimi (NAN) olarak da bilinir.
Wi-Fi Aware ağ iletişimi, komşu cihazlarla kümeler oluşturarak veya cihaz bir alandaki ilk cihazsa yeni bir küme oluşturarak çalışır. 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, cihazdaki kablosuz ağ bağlantısı farkında donanımını yöneten kablosuz ağ bağlantısı farkında sistem hizmetiyle iletişim kurmak için kablosuz ağ bağlantısı farkında API'lerini kullanır.
Wi-Fi Aware API'leri, uygulamaların aşağıdaki işlemleri gerçekleştirmesine olanak tanır:
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, bir cihaz bir veya daha fazla hizmete abone olduğunda ve yayıncının kablosuz ağ aralığına girdiğinde abone, eşleşen bir yayıncının bulunduğuna dair bir bildirim alır. Abone, bir yayıncı bulduktan sonra kısa bir mesaj gönderebilir veya bulunan cihazla ağ bağlantısı kurabilir. Cihazlar aynı anda hem yayıncı hem de abone olabilir.
Ağ bağlantısı oluşturma: İki cihaz birbirini keşfettikten sonra bir erişim noktası olmadan iki yönlü bir Wi-Fi Aware 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 iletişim modunu destekleyen cihazlarda uygulamalar, yayıncı veya abone keşif oturumu için anında iletişim modunu etkinleştirmek veya devre dışı bırakmak üzere PublishConfig.Builder.setInstantCommunicationModeEnabled()
ve SubscribeConfig.Builder.setInstantCommunicationModeEnabled()
yöntemlerini kullanabilir. Anında iletişim modu, mesaj alışverişini, hizmet keşfini ve yayıncı veya abone keşif oturumu kapsamında ayarlanan tüm veri yollarını hızlandırır. Bir cihazın anında iletişim modunu destekleyip desteklemediğini belirlemek 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, uygulamanız, hizmetin durması veya kapsama alanı dışına çıkması nedeniyle keşfedilen bir hizmeti kaybettiğinde uyarı almak için
onServiceLost()
geri çağırmasını kullanabilirsiniz. - Wi-Fi Aware veri yollarının kurulumu örneklendi. Ö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 açılmasını hızlandırır ve yalnızca tek bir ağ isteğiyle birden çok noktadan noktaya bağlantının etkinleştirilmesini sağlar.
- Android 12 veya sonraki sürümleri çalıştıran uygulamalar, mevcut veri yollarının sayısını almak, oturum yayınlamak ve oturumlara abone olmak için
WifiAwareManager.getAvailableAwareResources()
yöntemini kullanabilir. Bu, uygulamanın istenen işlevi yürütmek için yeterli kaynak olup olmadığını belirlemesine yardımcı olabilir.
İlk kurulum
Uygulamanızı, kablosuz ağ bilinirliği keşfini ve ağ oluşturmayı kullanacak şekilde ayarlamak için aşağıdaki adımları uygulayın:
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" />
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);
Wi-Fi Aware'in şu anda kullanılıp kullanılamadığını kontrol edin. Kablosuz Ağ Farkındalığı cihazda mevcut olabilir ancak kullanıcı kablosuz ağı veya konumu devre dışı bıraktığı için şu anda kullanılamayabilir. Donanım ve donanım yazılımı özelliklerine bağlı olarak bazı cihazlar, kablosuz doğrudan bağlantı, SoftAP veya tethering kullanılıyorsa kablosuz bağlantı bilinir özelliğini desteklemeyebilir. Wi-Fi Aware'ın şu anda kullanılıp kullanılamadığını kontrol etmek için
isAvailable()
numaralı telefonu arayın.Kablosuz Ağ Farkındalığı'nın 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 birBroadcastReceiver
kaydetmelidir. Uygulamanız yayın amacını aldığında mevcut tüm oturumları silmeli (Kablosuz Aware hizmetinin kesintiye uğradığını varsayın), ardından mevcut kullanılabilirlik durumunu kontrol etmeli ve davranışını uygun şekilde düzenlemelidir. Ö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 konusuna bakın.
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:
- Kablosuz Ağ Farkındalığı donanımını açar.
- Kablosuz Ağa Duyarlı bir kümeye katılır veya bir küme oluşturur.
- İçinde oluşturulan tüm keşif oturumları için container görevi gören benzersiz bir ad alanına sahip kablosuz ağa duyarlı oturum oluşturur.
Uygulama başarıyla bağlanırsa sistem onAttached()
geri çağırma işlevini yürütür.
Bu geri çağırma, uygulamanızın sonraki tüm oturum işlemleri için kullanması gereken bir WifiAwareSession
nesnesi sağlar. Uygulamalar, hizmet yayınlamak veya hizmete abone olmak için oturumu kullanabilir.
Uygulamanız attach()
'ü yalnızca bir kez çağırmalıdır. Uygulamanız attach()
işlevini birden çok kez çağırırsa her çağrı için kendi ad alanını içeren farklı bir oturum alır. Bu, karmaşık senaryolarda yararlı olabilir ancak genellikle kullanılmamalıdır.
Hizmet yayınlama
Bir hizmeti bulunabilir hale getirmek için aşağıdaki parametreleri alan publish()
yöntemini çağırın:
PublishConfig
, hizmetin adını ve eşleme filtresi gibi diğer yapılandırma özelliklerini belirtir.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ınlama işlemi başarılı olursa onPublishStarted()
geri çağırma yöntemi ç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. Bu durumda onMessageReceived()
geri çağırma yöntemi ç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 kapatılırsa ilişkili keşif oturumları da kapatılır. Atılan nesneler de kapatılır ancak sistem, kapsam dışındaki oturumların ne zaman kapatılacağını garanti etmez. Bu nedenle, close()
yöntemlerini açıkça çağırmanızı öneririz.
Bir hizmete abone olma
Bir hizmete abone olmak için aşağıdaki parametreleri alan subscribe()
yöntemini çağırın:
-
SubscribeConfig
, abone olunacak hizmetin adını ve eşleme filtresi gibi diğer yapılandırma özelliklerini belirtir. DiscoverySessionCallback
, etkinlikler gerçekleştiğinde (ör. bir yayıncının bulunması) yürütülecek işlemleri belirtir.
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. Keşif oturumunda updateSubscribe()
numaralı telefonu arayarak abonelik oturumunu istediğiniz zaman güncelleyebilirsiniz.
Bu noktada aboneliğiniz, eşleşen yayıncıların kablosuz ağ kapsamına girmesini bekler. Bu durumda sistem, onServiceDiscovered()
geri çağırma yöntemini yürütür. Bu geri çağırmadaki PeerHandle
bağımsız değişkenini kullanarak söz konusu yayıncıya mesaj gönderebilir veya bağlantı oluşturabilirsiniz.
Bir hizmete aboneliği durdurmak için DiscoverySession.close()
numaralı telefonu arayın.
Keşif oturumları, üst öğeleriyle WifiAwareSession
ilişkilendirilir. Üst oturum kapatılırsa ilişkili keşif oturumları da kapatılır. Atılan nesneler de kapatılır ancak sistem, kapsam dışındaki oturumların ne zaman kapatılacağını garanti etmez. Bu nedenle, close()
yöntemlerini açıkça çağırmanızı öneririz.
Mesaj gönder
Başka bir cihaza mesaj göndermek için aşağıdaki nesnelere ihtiyacınız vardır:
DiscoverySession
. Bu nesne,sendMessage()
işlevini çağırmanıza olanak tanır. Uygulamanız, bir hizmet yayınlayarak veya bir hizmete abone olarakDiscoverySession
alır.İletiyi yönlendirmek için diğer cihazın
PeerHandle
. Uygulamanız, başka bir cihazınPeerHandle
bilgisini iki yoldan alır:- Uygulamanız bir hizmet yayınlar ve bir aboneden mesaj alır.
Uygulamanız,
onMessageReceived()
geri çağırma işlevinden aboneninPeerHandle
değerini alır. - Uygulamanız bir hizmete abone olur. Ardından, eşleşen bir yayıncı bulduğunda uygulamanız
onServiceDiscovered()
geri çağırma işlevinden yayıncınınPeerHandle
değerini alır.
- Uygulamanız bir hizmet yayınlar ve bir aboneden mesaj alır.
Uygulamanız,
Mesaj göndermek için sendMessage()
numaralı telefonu arayın. Ardından aşağıdaki geri çağırmalar gerçekleşebilir:
- Mesaj eş tarafından başarıyla alındığında sistem, gönderme uygulamasında
onMessageSendSucceeded()
geri çağırmasını çağırır. - Eş bir mesaj aldığında sistem, alma uygulamasında
onMessageReceived()
geri çağırmasını çağırır.
PeerHandle
, meslektaşlarla iletişim kurmak için gerekli olsa da kalıcı bir benzer tanımlayıcısı olarak buna güvenmemelisiniz. Uygulama, daha üst düzey tanımlayıcıları kullanabilir. Bu tanımlayıcılar, keşif hizmetinin kendisine veya sonraki mesajlara yerleştirilebilir. 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, mesaj bayt dizisinin bir tanımlayıcı içerecek şekilde (örneğin, ilk birkaç bayt olarak) değiştirilmesi anlamına gelir.
Bağlantı oluşturma
Wi-Fi Aware iki Wi-Fi Aware cihaz arasında istemci-sunucu ağını destekler.
İstemci-sunucu bağlantısını ayarlamak için:
Hizmet yayınlamak (sunucu üzerinde) ve hizmete abone olmak (istemci üzerinde) için kablosuz bağlantıyı kullanarak keşif yapın.
Abone yayıncıyı keşfettikten sonra, aboneden yayıncıya bir mesaj gönderin.
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();
WifiAwareNetworkSpecifier
kullanarak yayıncıda kablosuz ağ farkındalığı ağı istemek içinConnectivityManager
'u kullanın. Bu sırada, abone tarafından iletilen mesajdan elde ettiğiniz keşif oturumunu ve aboneninPeerHandle
değerini belirtin: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);
Yayıncı bir ağ istediğinde aboneye mesaj göndermelidir.
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. Ağ bağlantısı kullanılabilir, değiştiğinde veya kaybedildiğinde uygun geri çağırma yöntemleri çağrılır.Abonede
onAvailable()
yöntemi çağrıldıktan sonra, yayıncıdakiServerSocket
ile iletişim kurmak için birSocket
nesnesi açabileceğinizNetwork
nesnesi kullanılabilir ancakServerSocket
IPv6 adresini ve bağlantı noktasını bilmeniz gerekir. AşağıdakilerionCapabilitiesChanged()
geri çağırma işlevinde sağlananNetworkCapabilities
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);
Ağ bağlantısını tamamladığınızda
unregisterNetworkCallback()
düğmesine basın.
Eşler arası menzil ve konuma duyarlı keşif
Kablosuz RTT konum özelliklerine sahip bir cihaz, eşler arasındaki mesafeyi doğrudan ölçebilir ve bu bilgileri kablosuz ağ bilinir hizmet keşfini kısıtlamak için kullanabilir.
Wi-Fi RTT API, MAC adresini veya PeerHandle'ı kullanarak bir Wi-Fi Aware eşine doğrudan geçiş yapılmasına olanak tanır.
Kablosuz Ağ Farkında Keşif yalnızca belirli bir coğrafi çit içindeki hizmetleri keşfedecek şekilde kısıtlanabilir. Örneğin, 3 metreden (3.000 mm olarak belirtilir) daha yakın ve 10 metreden (10.000 mm olarak belirtilir) daha uzak olmayan bir mesafede "Aware_File_Share_Service_Name"
hizmeti yayınlayan bir cihazın bulunmasına olanak tanıyan bir coğrafi çit oluşturabilirsiniz.
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ı, aralığı etkinleştirmezse abone tarafından belirtilen coğrafi sınır kısıtlamaları yok sayılır ve mesafe dikkate alınmadan normal keşif gerçekleştirilir.
Abone, setMinDistanceMm ve setMaxDistanceMm'nin bir kombinasyonunu kullanarak bir coğrafi çit belirtmelidir.
Her iki değer için de belirtilmemiş bir mesafe, sınır olmadığı anlamına gelir. Yalnızca maksimum mesafenin belirtilmesi, minimum mesafenin 0 olduğunu gösterir. Yalnızca minimum mesafenin belirtilmesi, maksimum bir mesafe anlamına gelmez.
Bir eş hizmet, coğrafi çit içinde keşfedildiğinde, eşe olan ölçülen mesafeyi sağlayan onServiceDiscoveredWithinRange geri çağırma işlevi tetiklenir. Daha sonra mesafeyi ölçmek için gerektiğinde doğrudan Wi-Fi RTT API çağrılabilir.