Panoramica di Wi-Fi Aware

Le funzionalità Wi-Fi Aware consentono i dispositivi con Android 8.0 (livello API 26) e per scoprire e connettersi direttamente l'uno all'altro senza alcun altro tipo di e la connettività tra di loro. Il Wi-Fi Aware è anche noto come Nearby Awareness Networking (NAN).

La rete Wi-Fi Aware funziona formando cluster con dispositivi vicini, oppure creando un nuovo cluster se il dispositivo è il primo in un'area. Questo Il comportamento di clustering si applica all'intero dispositivo ed è gestito dalla rete Wi-Fi Conoscere il servizio di sistema; le app non hanno alcun controllo sul comportamento di clustering. Utilizzo da parte delle app le API Wi-Fi Aware per comunicare con il servizio di sistema Wi-Fi Aware, che gestisce all'hardware Wi-Fi Aware del dispositivo.

Le API Wi-Fi Aware consentono alle app di eseguire le seguenti operazioni:

  • Rilevamento di altri dispositivi: l'API dispone di un meccanismo per trovare altri dispositivi dispositivi nelle vicinanze. La procedura inizia quando un dispositivo pubblica uno di questi o più servizi rilevabili. Quindi, quando un dispositivo si abbona a uno o più ed entra nell'intervallo Wi-Fi dell'editore, l'abbonato riceve una notifica che indica che è stato trovato un publisher corrispondente. Dopo il scopre un editore, l'abbonato può inviare uno Short o stabilire una connessione di rete con il dispositivo rilevato. I dispositivi possono essere contemporaneamente publisher e abbonati.

  • Crea una connessione di rete:dopo il rilevamento di due dispositivi, possono creare un'istanza Connessione di rete bidirezionale Wi-Fi Aware senza punto di accesso.

Le connessioni di rete Wi-Fi Aware supportano velocità di velocità effettiva più elevate per un periodo di tempo più lungo distanze rispetto al Bluetooth e connessioni a Internet. Questi tipi di connessioni sono utili per le app che condividono contenuti quantità di dati tra gli utenti, ad esempio le app di condivisione di foto.

Miglioramenti ad Android 13 (livello API 33)

Sui dispositivi con Android 13 (livello API 33) e versioni successive che supportano le funzionalità istantanee modalità di comunicazione, le app possono utilizzare PublishConfig.Builder.setInstantCommunicationModeEnabled() e SubscribeConfig.Builder.setInstantCommunicationModeEnabled() metodi per attivare o disattivare la modalità di comunicazione istantanea per un publisher o un abbonato durante una sessione di rilevamento. La modalità di comunicazione istantanea velocizza lo scambio di messaggi, Service Discovery ed eventuali percorsi di dati impostati come parte di un publisher o di un abbonato durante una sessione di rilevamento. Per determinare se un dispositivo supporta la comunicazione istantanea utilizza il metodo isInstantCommunicationModeSupported().

Miglioramenti ad Android 12 (livello API 31)

Android 12 (livello API 31) aggiunge alcuni miglioramenti a Wi-Fi Aware:

  • Sui dispositivi con Android 12 (livello API 31) o versioni successive, puoi utilizzare onServiceLost() per ricevere un avviso quando la tua app ha perso un servizio rilevato a causa l'interruzione o lo spostamento del servizio fuori dal raggio d'azione.
  • La configurazione dei percorsi dati Wi-Fi Aware è stata semplificata. Versioni precedenti ha utilizzato la messaggistica L2 per fornire l'indirizzo MAC dell'iniziatore, abbiamo introdotto la latenza. Sui dispositivi con Android 12 e versioni successive, l'utente che risponde (server) può essere configurato in modo da accettare qualsiasi peer, ovvero non necessita per conoscere in anticipo l'indirizzo MAC dell'iniziatore. Questo accelera il percorso dei dati generare e abilitare più collegamenti point-to-point con una sola rete richiesta.
  • Le app con Android 12 o versioni successive possono utilizzare WifiAwareManager.getAvailableAwareResources() per ottenere il numero di percorsi di dati attualmente disponibili, sessioni di pubblicazione e le sessioni di iscrizione. Ciò può aiutare l'app a determinare se sono presenti abbastanza risorse disponibili per eseguire la funzionalità desiderata.

Configurazione iniziale

Per configurare l'app per l'utilizzo del rilevamento e della rete Wi-Fi Aware, esegui la seguenti passaggi:

  1. Richiedi le seguenti autorizzazioni nel file manifest dell'app:

    <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. Controlla se il dispositivo supporta Wi-Fi Aware con la PackageManager come mostrato di seguito:

    Kotlin

    context.packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)
    

    Java

    context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);
    
  3. Controlla se è attualmente disponibile il Wi-Fi Aware. La connessione Wi-Fi potrebbe essere attiva su il dispositivo, ma potrebbe non essere attualmente disponibile perché l'utente ha disattivato Wi-Fi o Posizione. A seconda delle funzionalità hardware e firmware, alcuni dispositivi potrebbe non supportare la funzionalità Wi-Fi Aware se è attivo Wi-Fi Direct, SoftAP o tethering per gli utilizzi odierni. Per verificare se la funzionalità Wi-Fi Aware è attualmente disponibile, chiama isAvailable().

    La disponibilità di Wi-Fi Aware può variare in qualsiasi momento. La tua app dovrebbe registra un BroadcastReceiver per ricevere ACTION_WIFI_AWARE_STATE_CHANGED, che viene inviato ogni volta che la disponibilità cambia. Quando la tua app riceve per intent di trasmissione, dovrebbe ignorare tutte le sessioni esistenti (supponendo che Il servizio Wi-Fi Aware è stato interrotto), quindi controlla la lo stato di disponibilità attuale e regolarne il comportamento di conseguenza. Ad esempio:

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

Per ulteriori informazioni, vedi Trasmissioni.

Ottieni una sessione

Per iniziare a usare Wi-Fi Aware, la tua app deve ottenere un WifiAwareSession chiamando attach(). Questo metodo svolge le seguenti operazioni:

  • Attiva l'hardware Wi-Fi Aware.
  • Si unisce o forma un cluster Wi-Fi Aware.
  • Crea una sessione Wi-Fi Aware con uno spazio dei nomi univoco che funge da per tutte le sessioni di rilevamento create al suo interno.

Se l'app si collega correttamente, il sistema esegue Chiamata di onAttached(). Questo callback fornisce un oggetto WifiAwareSession che la tua app dovrebbe usare per tutte le altre operazioni della sessione. Un'app può utilizzare sessione per pubblicare un servizio o sottoscrivere un abbonamento a un servizio.

L'app deve chiamare attach() solo una volta. Se la tua app chiama attach() più volte, l'app riceve una sessione diversa per ogni chiamata, ciascuna con il proprio spazio dei nomi. Questa opzione potrebbe essere utile in scenari complessi, ma dovrebbe in genere evitate.

Pubblica un servizio

Per rendere rilevabile un servizio, chiama il publish(), che accetta i seguenti parametri:

  • PublishConfig specifica il nome del e altre proprietà di configurazione, come il filtro di corrispondenza.
  • DiscoverySessionCallback specifica azioni da eseguire quando si verificano eventi, ad esempio quando l'abbonato riceve un messaggio.

Ecco un esempio:

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

Se la pubblicazione va a buon fine, onPublishStarted() viene chiamato il metodo di callback.

Dopo la pubblicazione, quando i dispositivi che eseguono app per abbonati corrispondenti passano alla Raggio d'azione Wi-Fi del dispositivo di pubblicazione, gli abbonati scoprono il servizio. Quando un abbonato scopre un editore, l'editore non riceve notifica; se invece il sottoscrittore invia un messaggio all'editore il publisher riceve una notifica. In questo caso, onMessageReceived() viene chiamato il metodo di callback. Puoi utilizzare lo PeerHandle di questo metodo a inviare un messaggio al sottoscrittore o crea una connessione.

Per interrompere la pubblicazione del servizio, chiama DiscoverySession.close(). Le sessioni di rilevamento sono associate al genitore WifiAwareSession. Se la sessione principale è vengono chiuse anche le relative sessioni di rilevamento. Dopo l'eliminazione anch'essi sono chiusi, il sistema non garantisce che sessioni sono chiuse, quindi ti consigliamo di chiamare esplicitamente close() di machine learning.

Abbonarsi a un servizio

Per abbonarti a un servizio, chiama il subscribe() metodo, che accetta i seguenti parametri:

  • SubscribeConfig specifica il nome del servizio a cui eseguire la sottoscrizione e altre proprietà di configurazione, come filtro.
  • DiscoverySessionCallback specifica azioni da eseguire quando si verificano eventi, come il rilevamento di un publisher.

Ecco un esempio:

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

Se l'operazione di sottoscrizione ha esito positivo, il sistema chiama la onSubscribeStarted() richiamarti nell'app. Poiché puoi utilizzare SubscribeDiscoverySession nel per comunicare con un publisher quando la tua app ne ha rilevato uno, salvare questo riferimento. Puoi aggiornare la sessione di iscrizione in qualsiasi momento: chiamata updateSubscribe() durante la sessione di rilevamento.

A questo punto, il tuo abbonamento attende l'arrivo degli editori corrispondenti Portata Wi-Fi. In questi casi, il sistema esegue onServiceDiscovered() di callback di Google. Puoi usare PeerHandle di questo callback per inviare un messaggio o crea una connessione con quel publisher.

Per interrompere l'iscrizione a un servizio, chiama DiscoverySession.close(). Le sessioni di rilevamento sono associate al genitore WifiAwareSession. Se la sessione principale è vengono chiuse anche le relative sessioni di rilevamento. Dopo l'eliminazione anch'essi sono chiusi, il sistema non garantisce che sessioni sono chiuse, quindi ti consigliamo di chiamare esplicitamente close() di machine learning.

Inviare un messaggio

Per inviare un messaggio a un altro dispositivo, sono necessari i seguenti oggetti:

Per inviare un messaggio, chiama sendMessage(). La potrebbero verificarsi i seguenti callback:

  • Quando il messaggio viene ricevuto correttamente dal peer, il sistema chiama la onMessageSendSucceeded() callback nell'app invio.
  • Quando il peer riceve un messaggio, il sistema chiama onMessageReceived() nell'app di ricezione.
di Gemini Advanced.

Sebbene il PeerHandle sia necessario per comunicare con i compagni, non dovresti come identificatore permanente dei peer. Gli identificatori di livello superiore possono essere utilizzate dall'applicazione, incorporate nel servizio di rilevamento stesso o nelle messaggi successivi. Puoi incorporare un identificatore nel servizio di rilevamento con il setMatchFilter() o setServiceSpecificInfo() di PublishConfig o SubscribeConfig. La Il metodo setMatchFilter() influisce sul rilevamento, mentre il metodo Il metodo setServiceSpecificInfo() non influisce sul rilevamento.

L'incorporamento di un identificatore in un messaggio implica la modifica dell'array di byte del messaggio in includono un identificatore (ad esempio, come prima coppia di byte).

Creare una connessione

Wi-Fi Aware supporta il networking client-server tra due dispositivi Wi-Fi Aware.

Per configurare la connessione client-server:

  1. Utilizza il rilevamento Wi-Fi Aware per pubblicare un servizio (sulla server) e sottoscrivere un servizio (sulla cliente).

  2. Una volta che l'abbonato scopre l'editore, Inviare un messaggio dal sottoscrittore all'editore.

  3. Avviare una ServerSocket sul publisher dispositivo e impostare o ottenere la porta:

    Kotlin

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

    Java

    ServerSocket ss = new ServerSocket(0);
    int port = ss.getLocalPort();
    
  4. Utilizza ConnectivityManager per richiedere una rete Wi-Fi Aware del publisher utilizzando un WifiAwareNetworkSpecifier, che specifica la sessione di rilevamento PeerHandle dell'abbonato, ottenute dal messaggio trasmesso dal sottoscrittore:

    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. Una volta che il publisher richiede una rete, invia un messaggio al sottoscrittore.

  6. Quando l'abbonato riceve il messaggio dall'editore, richiedi un Wi-Fi Rete Aware per l'abbonato utilizzando lo stesso metodo dell'editore. Cosa fare non specificare una porta quando si crea NetworkSpecifier La vengono chiamati metodi di callback appropriati quando la connessione di rete disponibile, modificato o smarrito.

  7. Una volta che il metodo onAvailable() viene chiamato al sottoscrittore, viene L'oggetto Network è disponibile con che puoi aprire in una Socket per comunicare con il ServerSocket del publisher, ma devi conoscere Indirizzo e porta IPv6 di ServerSocket. Puoi trovare queste informazioni Oggetto NetworkCapabilities fornito nel 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);
    
  8. Al termine della connessione di rete, chiama unregisterNetworkCallback()

    .

Varietà di colleghi e scoperta sensibile alla posizione

Un dispositivo dotato della posizione RTT Wi-Fi possono misurare direttamente la distanza rispetto ai colleghi e usare queste informazioni per limitare il rilevamento del servizio Wi-Fi Aware.

L'API Wi-Fi RTT consente il raggio diretto a un peer Wi-Fi Aware utilizzando i suoi l'indirizzo MAC o il relativo PeerHandle.

Il rilevamento di Wi-Fi Aware può essere limitato in modo da rilevare solo i servizi all'interno di un un particolare recinto virtuale. Ad esempio, puoi configurare un recinto virtuale che permetta il rilevamento di un dispositivo che pubblica un servizio "Aware_File_Share_Service_Name" che non è meno di 3 metri (specificati come 3000 mm) e non più di 10 metri (specificati come 10.000 mm).

Per attivare il geofencing, sia il publisher sia l'abbonato devono:

  • L'editore deve abilitare il raggio d'azione sul servizio pubblicato utilizzando setRangingEnabled(true).

    Se il publisher non abilita il raggio d'azione, i vincoli del recinto virtuale specificate dall'abbonato vengono ignorati e viene eseguita la normale scoperta, ignorando la distanza.

  • Il sottoscrittore deve specificare un recinto virtuale utilizzando una combinazione di setMinDistanceMm e setMaxDistanceMm.

    Per entrambi i valori, una distanza non specificata non implica alcun limite. Specificando solo la distanza massima implica una distanza minima pari a 0. Specificando solo la distanza minima non implica un valore massimo.

Quando un servizio peer viene rilevato all'interno di un recinto virtuale, onServiceDiscoveredWithinRange viene attivato, che fornisce la distanza misurata dal peer. La L'API Direct Wi-Fi RTT può quindi essere chiamata se necessario per misurare la distanza a in un secondo momento.