[JAVA] Android 8.0 - Mémo compatible Wi-Fi

Ci-dessous ↓ traduction automatique https://developer.android.com/guide/topics/connectivity/wifi-aware.html#create_a_connection

Aperçu

On some devices running Android 8.0 (API level 26) and higher, Wi-Fi Aware provides the ability to discover and connect directly to each other without any other type of connectivity between them, such as Wi-Fi Access Point or Cellular. Wi-Fi Aware is also known as Neighbor Awareness Networking or NAN.

Sur certains appareils exécutant Android 8.0 (niveau API 26) ou version ultérieure, Wi-Fi Aware, comme les points d'accès Wi-Fi et Cellular, peut se détecter et se connecter directement les uns aux autres sans aucun autre type de connexion. .. Wi-Fi Aware est également connu sous le nom de réseau de sensibilisation des voisins ou NAN.

Wi-Fi Aware networking works by forming clusters with neighboring devices, or by creating a new cluster if the device is the first one in an area. This clustering behavior is device-wide—apps have no control over clustering behavior—and the behavior is managed by the Wi-Fi Aware system service. Apps use the Wi-Fi Aware APIs to talk to the Wi-Fi Aware system service which, in turn, manages the Wi-Fi Aware hardware on the device.

Les réseaux Wi-Fi fonctionnent en formant un cluster avec des appareils voisins, ou en créant un nouveau cluster si l'appareil est le premier dans la zone. Le comportement de ce clustering est à l'échelle de l'appareil, l'application n'a aucun contrôle sur le comportement du clustering, et ce comportement est géré par les services système Wi-Fi Aware. L'application utilise l'API Wi-Fi Aware pour communiquer avec le service système Wi-Fi Aware, qui gère le matériel Wi-Fi Aware sur l'appareil.

The Wi-Fi Aware APIs are available to apps that target Android 8.0 (API level 26), and let apps perform the following operations:

L'API Wi-Fi Aware peut être utilisée dans les applications ciblant Android 8.0 (niveau d'API 26), ce qui permet à l'application d'effectuer les opérations suivantes:

Découvrir d'autres appareils - L'API dispose d'un mécanisme pour trouver d'autres appareils à proximité. Le processus commence lorsqu'un appareil expose un service détectable. Ensuite, lorsque l'appareil s'abonne à un ou plusieurs services et entre dans la plage Wi-Fi de l'éditeur, l'abonné sera informé qu'un éditeur correspondant a été trouvé. Une fois que l'abonné a découvert l'éditeur, l'abonné peut envoyer un message court ou établir une connexion réseau avec le périphérique découvert.

Création d'une connexion réseau - Vous pouvez créer une connexion réseau bidirectionnelle Wi-Fi Aware sans point d'accès une fois que les deux appareils se sont détectés via la découverte Wi-Fi Aware ou d'autres mécanismes tels que Bluetooth ou BLE.

Wi-Fi Aware network connections are more reliable than Wi-Fi P2P connections and support higher throughput rates across longer distances than Bluetooth connections. These types of connections are useful for apps that share data between users, such as photo-sharing apps.

Les connexions réseau Wi-Fi sont plus fiables que les connexions Wi-Fi P2P et prennent en charge un débit plus élevé sur des distances plus longues que les connexions Bluetooth. Ces types de connexions sont utiles pour les applications qui partagent des données entre utilisateurs, telles que les applications de partage de photos.

Configuration compatible Wi-Fi

Définition des autorisations

<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_COARSE_LOCATION" />

Vérifiez la prise en charge Wi-Fi Aware pour votre appareil

context.getPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE);

Enregistrement du récepteur de diffusion pour recevoir une notification de changement de disponibilité Wi-Fi Aware

IntentFilter filter =
    new IntentFilter(WifiAwareManager.WIFI_AWARE_STATE_CHANGED_ACTION);
BroadcastReceiver myReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(final Context context, final Intent intent) {
        if (WifiAwareManager.isAvailable()) {
            //Wi-Que faire lorsque Fi Aware devient disponible
        } else {
            //Wi-Que faire lorsque Fi Aware devient indisponible
        }
    }
};
context.registerReceiver(myReceiver, filter);

Obtenir la session

To start using Wi-Fi Aware, your app must obtain a WifiAwareSession by calling attach(). This method does the following:

Pour démarrer avec Wi-Fi Aware, votre application doit appeler attach () pour obtenir une session WifiAwareSession. Cette méthode effectue les opérations suivantes:

Publier le service

Pour rendre le service détectable, appelez la méthode WiFiAwareSession # publish ().

PublishConfig config = new PublishConfig.Builder()
    .setServiceName(AWARE_FILE_SHARE_SERVICE_NAME)
    .build();

mAwareSession.publish(config, new DiscoverySessionCallback() {
    @Override
    public void onPublishStarted(PublishDiscoverySession session) {
        //Appelé si la publication réussit.
        //L'appareil exécutant l'application d'abonné correspondante est le Wi-Fi de l'appareil public-Lorsque vous passez à la plage Fi, l'abonné découvre le service. Lorsqu'un abonné découvre un éditeur, l'éditeur ne sera pas averti tant que l'abonné n'aura pas envoyé un message à l'éditeur.
    }
    @Override
    public void onMessageReceived(PeerHandle peerHandle, byte[] message) {
        //L'éditeur reçoit une notification lorsque l'abonné envoie un message à l'éditeur. Lorsque cela se produit, la méthode de rappel onMessageReceived () est exécutée. Vous pouvez utiliser l'argument PeerHandle de cette méthode pour renvoyer un message ou créer une connexion à l'abonné.
    }, null);

To stop publishing the service, call DiscoverySession.close(). Discovery sessions are associated with their parent WifiAwareSession. If the parent session is closed, its associated discovery sessions are also closed. However, the system doesn't guarantee when out-of-scope sessions are closed, so we recommend that you manually call DiscoverySession.close().

Pour arrêter la publication du service, appelez DiscoverySession.close (). La session de découverte est associée à la WifiAwareSession parent. Si la session parente est fermée, sa session de découverte associée est également fermée. Cependant, cela n'est pas garanti lorsqu'une session hors de portée est fermée, il est donc recommandé d'appeler manuellement DiscoverySession.close ().

Abonnement au service

Appelez la méthode WiFiAwareSession # subscribe () pour vous abonner au service.

SubscribeConfig config = new SubscribeConfig.Builder()
    .setServiceName(AWARE_FILE_SHARE_SERVICE_NAME)
    .build();

mAwareSession.subscribe(config, new DiscoverySessionCallback() {
    @Override
    public void onSubscribeStarted(SubscribeDiscoverySession session) {
        //Si l'opération d'abonnement réussit, le système effectue un rappel onSubscribeStarted () dans l'application. Vous devez enregistrer cette référence car vous pouvez utiliser l'argument SubscribeDiscoverySession dans le rappel pour communiquer avec l'éditeur une fois que l'application l'a détecté. Vous pouvez mettre à jour la description à tout moment en appelant updateSubscribe () dans la session de découverte.
    }

    @Override
    public void onServiceDiscovered(PeerHandle peerHandle,
            byte[] serviceSpecificInfo, List<byte[]> matchFilter) {
        //L'éditeur correspondant est Wi-En mode Fi, le système exécute la méthode de rappel onServiceDiscovered (). Vous pouvez utiliser l'argument PeerHandle dans ce rappel pour envoyer un message ou créer une connexion à cet éditeur.
    }
}, null);

Envoyer le message

To send a message to another device, you need the following objects: A DiscoverySession. This object allows you to call sendMessage(). Your app gets a DiscoverySession by either publishing a service or subscribing to a service. The other device's PeerHandle, so you know where to send the message. Your app gets another device's PeerHandle in one of two ways: Your app publishes a service. Then, when it receives a message from a subscriber, your app gets the subscriber's PeerHandle from the onMessageReceived() callback. Your app subscribes to a service. Then, when it discovers a matching publisher, your app gets the publisher's PeerHandle from the onServiceDiscovered() callback. To send a message, call sendMessage(). The following callbacks might then occur:

Pour envoyer un message à un autre appareil, vous avez besoin des objets suivants: Session découverte. Vous pouvez utiliser cet objet pour appeler sendMessage (). Votre application obtient une session de découverte en publiant ou en vous abonnant au service. PeerHandle sur les autres appareils sait où envoyer le message. Votre application obtient PeerHandle sur un autre appareil de l'une des deux manières suivantes: Votre application publie le service. Ensuite, lorsqu'elle reçoit un message de l'abonné, l'application obtient le PeerHandle de l'abonné à partir du rappel onMessageReceived (). Votre application est abonnée au service. Ensuite, lorsqu'il trouve un éditeur correspondant, il obtient le PeerHandle de l'éditeur à partir du rappel onServiceDiscovered (). Appelez sendMessage () pour envoyer un message. Les rappels suivants peuvent se produire:

When the message is successfully received by the peer, the system executes the onMessageSendSucceeded() callback in the sending app. When the peer receives a message, the system executes the onMessageReceived() callback in the receiving app. Note: Messages are generally used for lightweight messaging, as they might not be delivered and are limited to about 255 bytes in length. To determine the exact length limit, call getMaxServiceSpecificInfoLength(). For high speed, bi-directional communication, your app should create a connection instead.

Si le message est bien reçu par le pair, le système effectuera un rappel onMessageSendSucceeded () dans l'application d'envoi. Lorsque l'homologue reçoit le message, l'application réceptrice effectue un rappel onMessageReceived (). Remarque: les messages sont couramment utilisés pour les messages légers. Cela est dû au fait que le message peut ne pas être remis et est limité à environ 255 octets de longueur. Pour déterminer la limite de longueur exacte, appelez getMaxServiceSpecificInfoLength (). Pour une communication bidirectionnelle à haut débit, l'application doit plutôt créer une connexion.

Lien

There are two ways to create a Wi-Fi Aware connection. The first way assumes that you have used Wi-Fi Aware to discover the other device and you have the other device's PeerHandle. The second way assumes that you have discovered the other device's MAC address through some other mechanism, such as Bluetooth or BLE. This is known as out-of-band discovery, or OOB.

Il existe deux façons de créer une connexion Wi-Fi Aware. La première méthode suppose que vous utilisez Wi-Fi Aware pour détecter d'autres appareils et que vous utilisez le PeerHandle de l'autre appareil. La deuxième méthode suppose que vous avez détecté l'adresse MAC d'un autre appareil à l'aide d'autres mécanismes tels que Bluetooth ou BLE. C'est ce qu'on appelle la détection hors bande, ou OOB.

Regardless of which method you choose, there are always two devices in a Wi-Fi Aware connection: an initiator and a responder. If you're using Wi-Fi Aware discovery, then the roles are fixed and don't need to be explicitly specified: the subscriber is the initiator and the publisher is the responder. If you are using out-of-band discovery, then the devices need to negotiate these roles on their own.

Quelle que soit la méthode choisie, il y a toujours deux appareils dans votre connexion Wi-Fi Aware: l'initiateur et le répondeur. Si vous utilisez la détection Wi-Fi Aware, le rôle est fixe et n'a pas besoin d'être explicitement spécifié. L'abonné est l'initiateur et l'éditeur est le répondeur. Si vous utilisez la détection hors bande, votre appareil devra négocier ces rôles tout seul.

To create a connection, complete the following sequence of steps:

  1. Create a network specifier: For Wi-Fi Aware discovery, call either DiscoverySession.createNetworkSpecifierOpen() or DiscoverySession.createNetworkSpecifierPassphrase() from the publisher and subscriber. For OOB discovery, call either WifiAwareSession.createNetworkSpecifierOpen() or WifiAwareSession.createNetworkSpecifierPassphrase() from both devices. The responder isn't required to provide a MAC address or a PeerHandle. If no MAC address or PeerHandle is specified, the device accepts all connection requests.

Pour créer une connexion, procédez comme suit:

  1. Créez un spécificateur de réseau: Pour la découverte Wi-Fi Aware, appelez DiscoverySession.createNetworkSpecifierOpen () ou DiscoverySession.createNetworkSpecifierPassphrase () auprès des éditeurs et des abonnés. Pour la découverte OOB, appelez WifiAwareSession.createNetworkSpecifierOpen () ou WifiAwareSession.createNetworkSpecifierPassphrase () à partir des deux appareils. Le répondeur n'a pas besoin de fournir une adresse MAC ou PeerHandle. Si aucune adresse MAC ou PeerHandle n'est spécifié, l'appareil acceptera toutes les demandes de connexion.
  1. Build a network request, setting the transport mechanism to TRANSPORT_WIFI_AWARE:

Réglez le mécanisme de transport sur TRANSPORT_WIFI_AWARE pour effectuer une requête réseau.

NetworkRequest myNetworkRequest = new NetworkRequest.Builder()
     .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
     .setNetworkSpecifier(networkSpecifier)
     .build();
  1. Call requestNetwork() and provide the following callback methods:

Appelez requestNetwork () et fournissez la méthode de rappel suivante:

mCallback = new ConnectivityManager.NetworkCallback() {
    @Override
    public void onAvailable(Network network) {
        ...
    }
    @Override
    public void onLinkPropertiesChanged(Network network,
            LinkProperties linkProperties) {
        ...
    }
    @Override
    public void onLost(Network network) {
        ...
    }
};
mConnMgr.requestNetwork(networkRequest, mCallback);

The appropriate callback methods are executed when the network connection is available, changed, or lost.

Des méthodes de rappel appropriées sont exécutées lorsqu'une connexion réseau est disponible, modifiée ou perdue.

4 When you're finished with the network connection, call unregisterNetworkCallback(). Note: Building a network request and specifying the required network capabilities aren't specific to the Wi-Fi Aware API. For more information on working with network requests, see ConnectivityManager.

Appelez unregisterNetworkCallback () lorsque la connexion réseau est fermée. Remarque: la création de requêtes réseau et la spécification des fonctionnalités réseau requises ne sont pas spécifiques à l'API Wi-Fi Aware. Pour plus d'informations sur la gestion des demandes réseau, consultez Connectivity Manager.


Créer une application de test basée sur ce qui précède

Côté éditeur qui commence la publication et reçoit les messages des abonnés faisant référence à ce qui précède Essayez l'application et l'implémentation de l'application côté abonné qui s'abonne et envoie des messages à l'éditeur.

Activité de l'éditeur

package com.example.user.wifiawaretest;

import android.app.Activity;
import android.content.pm.PackageManager;
import android.net.wifi.aware.AttachCallback;
import android.net.wifi.aware.DiscoverySessionCallback;
import android.net.wifi.aware.PeerHandle;
import android.net.wifi.aware.PublishConfig;
import android.net.wifi.aware.PublishDiscoverySession;
import android.net.wifi.aware.WifiAwareManager;
import android.net.wifi.aware.WifiAwareSession;
import android.os.Handler;
import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends Activity {

    private WifiAwareSession mAwareSession;
    private Handler mHandler = new Handler();
    public static final String AWARE_SERVICE_NAME = "Aware Service";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)) {
            Toast.makeText(this, "Wi-Fi Aware not supoortted", Toast.LENGTH_SHORT).show();
            return;
        }

        WifiAwareManager was = (WifiAwareManager)getSystemService(WifiAwareManager.class);

        was.attach(new MyAttachCallback(), mHandler);
    }

    class MyAttachCallback extends AttachCallback {
        @Override
        public void onAttachFailed() {
            Toast.makeText(MainActivity.this, "onAttachFailed", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onAttached(WifiAwareSession session) {
            Toast.makeText(MainActivity.this, "onAttach", Toast.LENGTH_SHORT).show();

            MainActivity.this.mAwareSession = session;
            PublishConfig config = new PublishConfig.Builder()
                    .setServiceName(AWARE_SERVICE_NAME)
                    .build();
            MainActivity.this.mAwareSession.publish(config, new DiscoverySessionCallback() {
                @Override
                public void onPublishStarted(PublishDiscoverySession session) {
                    Toast.makeText(MainActivity.this, "onPublishStarted", Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onMessageReceived(PeerHandle peerHandle, byte[] message) {
                    Toast.makeText(MainActivity.this, "onMessageReceived : " + message.toString(), Toast.LENGTH_SHORT).show();
                }
            }, null);
        }
    }
}

Côté abonné

package com.example.user.wifiawaresubscribertest;

import android.app.Activity;
import android.content.pm.PackageManager;
import android.net.wifi.aware.AttachCallback;
import android.net.wifi.aware.DiscoverySessionCallback;
import android.net.wifi.aware.PeerHandle;
import android.net.wifi.aware.PublishConfig;
import android.net.wifi.aware.PublishDiscoverySession;
import android.net.wifi.aware.SubscribeConfig;
import android.net.wifi.aware.SubscribeDiscoverySession;
import android.net.wifi.aware.WifiAwareManager;
import android.net.wifi.aware.WifiAwareSession;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;

import java.util.List;

public class MainActivity extends Activity {

    private WifiAwareSession mAwareSession;
    private Handler mHandler = new Handler();
    public static final String AWARE_SERVICE_NAME = "Aware Service";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI_AWARE)) {
            Toast.makeText(this, "Wi-Fi Aware not supoortted", Toast.LENGTH_SHORT).show();
            return;
        }

        WifiAwareManager was = (WifiAwareManager)getSystemService(WifiAwareManager.class);

        was.attach(new MyAttachCallback(), mHandler);
    }

    class MyAttachCallback extends AttachCallback {
        @Override
        public void onAttachFailed() {
            Toast.makeText(MainActivity.this, "onAttachFailed", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onAttached(WifiAwareSession session) {
            Toast.makeText(MainActivity.this, "onAttach", Toast.LENGTH_SHORT).show();

            MainActivity.this.mAwareSession = session;

            SubscribeConfig config = new SubscribeConfig.Builder()
                    .setServiceName(AWARE_SERVICE_NAME)
                    .build();

            mAwareSession.subscribe(config, new DiscoverySessionCallback() {

                private PeerHandle mPeerHandle = null;
                @Override
                public void onSubscribeStarted(SubscribeDiscoverySession session) {
                    if (mPeerHandle != null) {
                        int messageId = 1;
                        session.sendMessage(mPeerHandle, messageId, "Test Message".getBytes());
                    }
                }

                @Override
                public void onServiceDiscovered(PeerHandle peerHandle,
                                                byte[] serviceSpecificInfo, List<byte[]> matchFilter) {
                    mPeerHandle = peerHandle;
                }
            }, null);

        }
    }
}

Commun (paramètre d'autorisation)

AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.user.wifiawaretest">
    
    <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_COARSE_LOCATION" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Recommended Posts

Android 8.0 - Mémo compatible Wi-Fi
Note