web-dev-qa-db-fra.com

Android Q, connectez-vous par programmation à différents AP WiFi pour Internet

Comme dans Android Q, plusieurs API WiFi sont limitées. J'essaie d'utiliser des API alternatives pour me connecter à différents AP Wifi pour Internet.

Voici mon code:

    WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder();
    builder.setSsid("wifi-ap-ssid");
    builder.setWpa2Passphrase("wifi-ap-password");

    WifiNetworkSpecifier wifiNetworkSpecifier = builder.build();

    NetworkRequest.Builder networkRequestBuilder1 = new NetworkRequest.Builder();
    networkRequestBuilder1.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
    networkRequestBuilder1.setNetworkSpecifier(wifiNetworkSpecifier);

    NetworkRequest nr = networkRequestBuilder1.build();
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    cm.requestNetwork(nr, callback);

Cela me permet de me connecter mais Internet est désactivé. Cela fonctionne comme défini dans Android docs.

Autre moyen que j'ai essayé est ci-dessous:

    WifiNetworkSuggestion.Builder wifiNetworkSuggestionBuilder1 = new WifiNetworkSuggestion.Builder();
    wifiNetworkSuggestionBuilder1.setSsid("wifi-ap-ssid");
    wifiNetworkSuggestionBuilder1.setWpa2Passphrase("wifi-ap-password");
    WifiNetworkSuggestion wifiNetworkSuggestion = wifiNetworkSuggestionBuilder1.build();
    List<WifiNetworkSuggestion> list = new ArrayList<>();
    list.add(wifiNetworkSuggestion);
    wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
    wifiManager.removeNetworkSuggestions(new ArrayList<WifiNetworkSuggestion>());
    wifiManager.addNetworkSuggestions(list);

autorisation déclarée dans le manifeste:

<uses-permission Android:name="Android.permission.CHANGE_WIFI_STATE"/>

Son utilisation n'a rien changé au comportement.

Veuillez indiquer la séquence d'API pour vous connecter avec succès à différents AP Wifi avec capacité Internet.

10
Vinodh

L'API WifiNetworkSuggestion est utilisée pour suggérer à l'utilisateur de rejoindre un AP (le système publiera une notification pour que l'utilisateur rejoigne)

Utilisez WifiNetworkSpecifier pour envoyer vos demandes. Utilisez l'objet réseau fourni dans onAvailable ().

WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder();
builder.setSsid("wifi-ap-ssid");
builder.setWpa2Passphrase("wifi-ap-password");

WifiNetworkSpecifier wifiNetworkSpecifier = builder.build();

NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
networkRequestBuilder1.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
networkRequestBuilder1.setNetworkSpecifier(wifiNetworkSpecifier);

NetworkRequest networkRequest = networkRequestBuilder.build();
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.requestNetwork(networkRequest, networkCallback);
networkCallback = new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(@NonNull Network network) {
                //Use this network object to Send request. 
                //eg - Using OkHttp library to create a service request
                 //Service is an OkHttp interface where we define docs. Please read OkHttp docs
                 Service service = null;

                 OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
                okHttpBuilder.socketFactory(network.getSocketFactory());

                service = new Retrofit.Builder()                                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                        .addConverterFactory(GsonConverterFactory.create(gson))
                         .client(okHttpBuilder.build())
                         .build()
                         .create(Service.class);


               Observable<Object> observable = null;
               try {
                  if (service != null) {
                     observable = service.yourRestCall();
                  }
                  Subscriber<Object> sub = new Subscriber< Object >() {
                     @Override
                     public void onError(Throwable e) {
                        //Do on error
                     }

                     @Override
                     public void onNext(Object logs) {
                        //Do on next
                     }
                  };
                 if(observable != null) {
                     observable.subscribeOn(Schedulers.io())
                                          .observeOn(AndroidSchedulers.mainThread()).subscribe(sub);
                 }

                super.onAvailable(network);
            }
        };

Une fois que vous avez fini d'utiliser le point d'accès Wifi,

connectivityManager.unregisterNetworkCallback(networkCallback);

Depuis le tracker Issue de Google par l'ingénieur de Google:

Le flux d'API de suggestions de réseau nécessite que l'utilisateur approuve l'application (la plateforme publie une notification pour demander l'approbation de l'utilisateur). Une fois l'application approuvée, la plateforme prendra en compte tous les réseaux de l'application lors de futures tentatives de connexion automatique. Mais, cette API ne vous donne aucune garantie sur le moment où l'appareil se connectera à votre AP pour l'approvisionnement. Ainsi, WifiNetworkSuggestion n'est pas la bonne surface API pour le cas d'utilisation fourni (connectivité instantanée peer to peer).

L'utilisation de WifiNetworkSpecifier établit une connexion locale au point d'accès wifi comme mentionné ci-dessus. Le réseau par défaut sera toujours cellulaire dans ce cas (nous ne perturbons pas la connectivité Internet des autres applications). L'application qui fait la demande doit utiliser les API multi-réseaux pour acheminer leur trafic via la connexion établie. Le | Réseau | l'objet fourni dans le rappel onAvailable () pour la demande est le handle que l'application doit utiliser pour ouvrir des sockets sur ce réseau local (Regardez https://developer.Android.com/reference/Android/net/Network .html # bindSocket (Java.net.DatagramSocket) et d'autres API de ce type disponibles dans la surface de l'objet | Network |.

J'espère que cela t'aides.

3
Anand Khinvasara

Essayez d'appeler bindProcessToNetwork () dans le rappel onAvailable () pour retrouver la connectivité réseau, cela fonctionne bien pour moi.

Connectez-vous au réseau:

    WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder();
    builder.setSsid("wifi-ap-ssid");
    builder.setWpa2Passphrase("wifi-ap-password");

    WifiNetworkSpecifier wifiNetworkSpecifier = builder.build();

    NetworkRequest.Builder networkRequestBuilder1 = new NetworkRequest.Builder();
    networkRequestBuilder1.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
    networkRequestBuilder1.setNetworkSpecifier(wifiNetworkSpecifier);

    NetworkRequest nr = networkRequestBuilder1.build();
    ConnectivityManager cm = (ConnectivityManager)
            context.getSystemService(Context.CONNECTIVITY_SERVICE);
    ConnectivityManager.NetworkCallback networkCallback = new 
        ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(Network network) {
            super.onAvailable(network);
            Log.d(TAG, "onAvailable:" + network);
            cm.bindProcessToNetwork(network);
        }
    });
    cm.requestNetwork(nr, networkCallback);

Déconnectez-vous du réseau lié:

cm.unregisterNetworkCallback(networkCallback);
2
Neil.Ling

Comme indiqué ici , Android 10 l'a fait intentionnellement pour que le WifiNetworkSpecifier empêche la connectivité Internet réelle. Il est destiné aux connexions peer-to-peer.

L'API WifiNetworkSuggestion, cependant, fournit une connectivité Internet et se comporte de manière similaire à l'API WifiNetworkSpecifier. Tant que l'appareil n'est actuellement connecté à aucun réseau Wifi , l'API WifiNetworkSuggestion se connectera automatiquement au réseau spécifié. La première fois qu'un appareil l'utilise, une notification apparaîtra vous demandant si l'application peut suggérer des réseaux. L'utilisateur doit accepter cette notification pour que l'API WifiNetworkSuggestion fonctionne.

J'ai trouvé que le code fourni par Android dans la documentation WifiNetworkSuggestion avait quelques erreurs de compilation. Voici le code que j'ai trouvé fonctionner:

final WifiNetworkSuggestion suggestion1 = new WifiNetworkSuggestion.Builder()
.setSsid("SSID here")
.setWpa2Passphrase("password here")
.setIsAppInteractionRequired(true) // Optional (Needs location permission)
.build();

// Optional extra suggesstion, you can delete this or add more
final WifiNetworkSuggestion suggestion2 = new WifiNetworkSuggestion.Builder()
.setSsid("SSID here 2")
.setWpa2Passphrase("password here 2")
.setIsAppInteractionRequired(true) // Optional (Needs location permission)
.build();

final List<WifiNetworkSuggestion> suggestionsList = new ArrayList<WifiNetworkSuggestion>();
suggestionsList.add(suggestion1);
suggestionsList.add(suggestion2); // Optional extra suggestion
final WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
final int status = wifiManager.addNetworkSuggestions(suggestionsList);

if (status != WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
     // Error handling
}

final IntentFilter intentFilter = new IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);

final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
    @Override public void onReceive(Context context, Intent intent) {
        if (!intent.getAction().equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
              return;
        }
        // Post connection
    }
};
getApplicationContext().registerReceiver(broadcastReceiver, intentFilter);
0
Russell C.