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 kümeleme davranışı cihazın tamamı için geçerlidir ve Wi-Fi-Aware sistem hizmeti tarafından yönetilir. Uygulamaların kümeleme davranışı üzerinde herhangi bir kontrolü yoktur. Uygulamalar, cihazdaki Wi-Fi Aware donanımını yöneten Wi-Fi Aware sistem hizmetiyle iletişim kurmak için Wi-Fi Aware API'leri kullanır.
Wi-Fi Aware API'ler, uygulamaların aşağıdaki işlemleri gerçekleştirmesine izin verir:
Diğer cihazları keşfetme: API'nin, yakındaki diğer cihazları bulmaya yönelik bir mekanizması vardır. İşlem, bir cihaz bir veya daha fazla bulunabilir hizmet 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ıyı keşfettikten 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.
Kablosuz Ağa Duyarlı ağ bağlantıları, daha uzun mesafelerde Bluetooth bağlantılarından daha yüksek işleme hızı 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 yararlı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, PublishConfig.Builder.setInstantCommunicationModeEnabled()
ve SubscribeConfig.Builder.setInstantCommunicationModeEnabled()
yöntemlerini kullanarak yayıncı veya abone keşif oturumu için anında iletişim modunu etkinleştirebilir veya devre dışı bırakabilir. Anında iletişim modu; mesaj alışverişini, hizmet keşfini ve yayıncı veya abone keşif oturumunun parçası olarak ayarlanan 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), Wi-Fi Aware'e bazı geliş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ıtlayıcı (sunucu) herhangi bir eşi kabul edecek şekilde yapılandırılabilir. Yani, başlatanı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ı, oturumları ve abone oturumlarını almak için
WifiAwareManager.getAvailableAwareResources()
yöntemini kullanabilir. Bu sayede uygulama, istenen işlevi yürütmek için yeterli kaynak olup olmadığını belirleyebilir.
İlk kurulum
Uygulamanızı Kablosuz Ağ duyarlılığını ve ağını 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ğıda gösterildiği gibi
PackageManager
API ile Wi-Fi Aware'i destekleyip desteklemediğini kontrol edin:Kotlin
context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)
Java
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
Wi-Fi Aware özelliğinin şu anda kullanılabilir olup olmadığını kontrol edin. Wi-Fi Aware cihazda mevcut olabilir, ancak kullanıcı kablosuz bağlantıyı veya konumu devre dışı bıraktığından şu anda kullanılamıyor olabilir. Donanım ve donanım yazılımı özelliklerine bağlı olarak, Wi-Fi Direct, SoftAP veya tethering kullanılıyorsa bazı cihazlar Wi-Fi Aware'i desteklemeyebilir. Wi-Fi Aware'in şu anda kullanılabilir olup olmadığını kontrol etmek için
isAvailable()
numaralı telefonu arayın.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
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()
numaralı telefonu arayarak bir WifiAwareSession
edinmesi 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.
- İç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 eklenirse sistem, onAttached()
geri çağırmasını 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 bir hizmete abone olmak için oturumu kullanabilir.
Uygulamanız attach()
numarasını yalnızca bir kez çağırmalıdır. Uygulamanız, attach()
yöntemini birden fazla kez çağırırsa uygulama her çağrı için kendi ad alanına sahip farklı bir oturum alır. Bu, karmaşık senaryolarda işe yarayabilir
ancak genellikle kaçınılması gerekir.
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şleşme filtresi gibi diğer yapılandırma özelliklerini belirtir.DiscoverySessionCallback
, etkinlikler gerçekleştiğinde (ör. abonenin bir mesaj aldığında) yürütülecek 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()
geri çağırma yöntemi çağrılır.
Yayından sonra, eşleşen abone uygulamalarını çalıştıran cihazlar yayınlama cihazının kablosuz ağ aralığına taşındığında aboneler bu hizmeti keşfeder. Abone bir yayıncıyı keşfettiğinde yayıncı bildirim almaz. Ancak abone, yayıncıya mesaj gönderirse yayıncı bir bildirim alır. Bu durumda onMessageReceived()
geri çağırma yöntemi çağrılır. Aboneye geri bir mesaj göndermek veya aboneyle bağlantı oluşturmak için bu yöntemdeki PeerHandle
bağımsız değişkenini kullanabilirsiniz.
Hizmeti yayınlamayı durdurmak için DiscoverySession.close()
numaralı telefonu arayın.
Keşif oturumları, üst WifiAwareSession
ile ilişkilendirilir. Üst oturum kapalıysa ilişkili keşif oturumları da kapatılır. Silinen nesneler de kapatılsa da sistem, kapsam dışı oturumların ne zaman kapatılacağını garanti etmez. Bu nedenle, close()
yöntemlerini açık bir şekilde ç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şleşme 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ızda onSubscribeStarted()
geri çağırmasını çağırır. Uygulamanız bir yayıncı keşfettikten sonra yayıncıyla iletişim kurmak için geri çağırmada SubscribeDiscoverySession
bağımsız değişkenini kullanabileceğinizden 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ğ aralığına gelmesini bekler. Bu durumda sistem, onServiceDiscovered()
geri çağırma yöntemini yürütür. Bu geri aramadaki PeerHandle
bağımsız değişkenini kullanarak ileti gönderebilir veya yayıncıyla bağlantı oluşturabilirsiniz.
Bir hizmete aboneliği sonlandırmak için DiscoverySession.close()
numaralı telefonu arayın.
Keşif oturumları, üst WifiAwareSession
ile ilişkilendirilir. Üst oturum kapalıysa ilişkili keşif oturumları da kapatılır. Silinen nesneler de kapatılsa da sistem, kapsam dışı oturumların ne zaman kapatılacağını garanti etmez. Bu nedenle, close()
yöntemlerini açık bir şekilde çağırmanızı öneririz.
İleti gönderme
Başka bir cihaza mesaj göndermek için aşağıdaki nesnelere ihtiyacınız vardır:
DiscoverySession
. Bu nesne,sendMessage()
yöntemini çağırmanıza olanak tanır. Uygulamanız, bir hizmet yayınlayarak veya bir hizmete abone olarakDiscoverySession
alır.Mesajı yönlendirmek için diğer cihazın
PeerHandle
. Uygulamanız, başka bir cihazınPeerHandle
parametresini iki yöntemden biriyle alır:- Uygulamanız bir hizmet yayınlar ve aboneden mesaj alır.
Uygulamanız, abonenin
PeerHandle
bilgisinionMessageReceived()
geri çağırmasından alır. - Uygulamanız bir hizmete abone olduğunda. Daha sonra, eşleşen bir yayıncı bulduğunda uygulamanız
onServiceDiscovered()
geri çağırmasından yayıncınınPeerHandle
değerini alır.
- Uygulamanız bir hizmet yayınlar ve aboneden mesaj alır.
Uygulamanız, abonenin
Mesaj göndermek için sendMessage()
numaralı telefonu arayın. Bu durumda 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. Üst düzey tanımlayıcılar, keşif hizmetinin kendisine yerleştirilmiş uygulama tarafından veya sonraki mesajlarda kullanılabilir. Keşif hizmetine setMatchFilter()
veya setServiceSpecificInfo()
PublishConfig
ya da SubscribeConfig
yöntemiyle bir tanımlayıcı yerleştirebilirsiniz. setMatchFilter()
yöntemi, keşfi etkiler. setServiceSpecificInfo()
yöntemi ise 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şturun
Wi-Fi Aware iki Wi-Fi duyarlı cihaz arasında istemci-sunucu ağını destekler.
İstemci-sunucu bağlantısını ayarlamak için:
Bir hizmette yayınlamak (sunucuda) ve bir hizmete abone olmak (istemcide) için Wi-Fi Aware keşfini kullanın.
Abone yayıncıyı keşfettikten sonra, aboneden yayıncıya bir mesaj gönderin.
Yayıncının 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ğa duyarlı ağ isteğinde bulunmak içinConnectivityManager
'ı kullanın. Keşif oturumunu ve aboneninPeerHandle
değerini belirtin. Bu, abone tarafından iletilen mesajdan alınır: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ğ isteğinde bulunduğunda aboneye bir mesaj göndermelidir.
Abone, yayıncıdan mesajı aldıktan sonra, yayıncıyla aynı yöntemi kullanarak abonede kablosuz duyarlı ağ isteyin.
NetworkSpecifier
oluştururken bağlantı noktası belirtmeyin. Ağ bağlantısı kullanılabilir olduğunda, değiştirildiğinde veya kesildiğ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ğiniz birNetwork
nesnesi kullanılabilir ancakServerSocket
IPv6 adresini ve bağlantı noktasını bilmeniz gerekir. BunlarıonCapabilitiesChanged()
geri çağırmasında 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ıyla işiniz bittiğinde
unregisterNetworkCallback()
numaralı telefonu arayın.
Benzerlere göre ve konuma duyarlı keşif
Kablosuz RTT konumu özelliğine sahip bir cihaz, benzerlerle olan mesafeyi doğrudan ölçebilir ve bu bilgileri Wi-Fi Aware 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.
Wi-Fi Aware keşfi, yalnızca belirli bir coğrafi sınır içindeki hizmetleri keşfedecek şekilde sınırlandırılabilir. Örneğin, 3 metreden daha yakın (3.000 mm olarak belirtilir) ve 10 metreden (10.000 mm olarak belirtilir) uzakta olmayan bir "Aware_File_Share_Service_Name"
hizmeti yayınlayan cihazın keşfedilmesini sağlayan coğrafi sınır oluşturabilirsiniz.
Coğrafi sınır çizmeyi etkinleştirmek için yayıncının ve abonenin işlem yapması gerekir:
Yayıncı, yayınlanan hizmette setRangingEnabled(true) seçeneğini kullanarak aralığı 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.
Abonenin, setMinLengthMm ve setMaxLengthMm kombinasyonlarını kullanarak bir coğrafi sınır belirtmesi gerekir.
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ğu anlamına gelir. Yalnızca minimum mesafenin belirtilmesi, maksimum bir mesafe anlamına gelmez.
Coğrafi sınır içinde bir eş hizmet keşfedildiğinde, eşe olan ölçülen mesafeyi sağlayan onServiceKeşfetedWithinRange geri çağırması tetiklenir. Daha sonra mesafeyi ölçmek için gerektiğinde doğrudan Wi-Fi RTT API çağrılabilir.