web-dev-qa-db-fra.com

Est-il possible d'ajouter une configuration réseau sur Android Q?

Contexte

J'ai remarqué que dans la classe WifiManager il y a une fonction appelée ( addNetwork , qui pourrait être utile si je veux restaurer ou enregistrer des informations sur les réseaux (nom du réseau AKA SSID, ainsi que le mot de passe et le type), afin que je puisse également me connecter à il.

Le problème

Je ne trouve pas beaucoup d'informations sur la façon de faire une telle chose. J'ai vu divers exemples sur StackOverflow, et si je cible Android API 28 (ou ci-dessous), je réussis en effet à lui faire ajouter un réseau et même à s'y connecter.

Cependant, lors du ciblage Android 29 (Android Q), il ne parvient pas à ajouter le réseau.

Ce que j'ai trouvé

Puisque j'essaye Pixel 2 avec Android Q beta 4, je pense que c'est peut-être parce que addNetwork est déconseillé, donc les docs le disent même, et que si je cible Android Q, cela ne fonctionnera pas, et en effet cela ne fonctionne pas:

Remarque sur la compatibilité: pour les applications ciblant Build.VERSION_CODES.Q ou une version ultérieure, cette API renvoie toujours -1.

La façon dont il semble que cela devrait fonctionner jusqu'à Android Q (à l'exclusion), consiste à préparer WifiConfiguration et à l'ajouter. Plus tard, je peux également me connecter si je le souhaite. On = Android Q, il semble qu'il ait été remplacé par WifiNetworkSuggestion , mais il ne semble pas comme il s’agit d’ajouter un réseau:

L'objet Suggestion de réseau est utilisé pour fournir un réseau Wi-Fi à prendre en compte lors de la connexion automatique aux réseaux. Les applications ne peuvent pas créer directement cet objet, elles doivent utiliser WifiNetworkSuggestion.Builder # build () pour obtenir une instance de cet objet.

Les applications peuvent fournir une liste de ces réseaux à la plate-forme à l'aide de WifiManager # addNetworkSuggestions (List).

Voici mon code actuel, pour pré-Android-Q

@WorkerThread
fun addNetwork(context: Context, networkName: String, networkPassword: String? = null, keyMgmt: Int = WifiConfiguration.KeyMgmt.NONE) {
    val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
    val conf = WifiConfiguration()
    conf.SSID = "\"$networkName\""
    conf.preSharedKey = if (networkPassword.isNullOrEmpty()) "" else "\"$networkPassword\""
    conf.allowedKeyManagement.set(keyMgmt)
    when (keyMgmt) {
        WifiConfiguration.KeyMgmt.WPA_PSK -> {
            //WPA/WPA2
        }
        WifiConfiguration.KeyMgmt.IEEE8021X -> {
        }
        WifiConfiguration.KeyMgmt.WPA_EAP -> {
        }
        WifiConfiguration.KeyMgmt.NONE -> {
            if (networkPassword.isNullOrEmpty()) {
                //open network
                conf.wepKeys[0] = "\"\""
            } else {
                //wep
                conf.wepKeys[0] = "\"" + networkPassword + "\""
                conf.wepTxKeyIndex = 0
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40)
            }
        }
    }
    if (networkPassword.isNullOrEmpty()) {
        //open network
        conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE)
    } else {
    }
    wifiManager.isWifiEnabled = true
    while (!wifiManager.pingSupplicant()) {
        Log.d("AppLog", "waiting to be able to add network")
    }
    val networkId = wifiManager.addNetwork(conf)
    if (networkId == -1)
        Log.d("AppLog", "failed to add network")
    else {
        wifiManager.enableNetwork(networkId, false)
        Log.d("AppLog", "success to add network")
    }
}

Semble qu'il ne nécessite que ces autorisations:

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

Mais dans tous les cas, cela fonctionne tant que vous ne ciblez pas Android Q (API 29) et au-dessus. Lorsque vous le ciblez, j'obtiens en effet toujours "-1", ce qui signifie qu'il échoue.

J'ai également trouvé un problème sur le suivi des problèmes ( ici et j'ai écrit à ce sujet ici ), parler de quelqu'un qui a besoin de l'API, mais je ne suis pas sûr qu'il s'agisse d'ajouter un réseau.

En regardant WifiNetworkSuggestion, je ne vois pas qu'il a autant de choses à définir que WifiConfiguration via son constructeur, c'est donc une autre raison pour laquelle je soupçonne qu'il ne s'agit pas d'ajouter un réseau.

Mais j'ai quand même essayé. Voici le code que j'ai essayé, par exemple, pour ajouter un réseau normal WPA:

@WorkerThread
fun addNetworkAndroidQ(context: Context, networkName: String, networkPassword: String? = null) {
    val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
    val list = ArrayList<WifiNetworkSuggestion>()
    val builder = WifiNetworkSuggestion.Builder().setSsid(networkName)
    if (!networkPassword.isNullOrEmpty())
        builder.setWpa2Passphrase(networkPassword)
    list.add(builder.build())
    val result = wifiManager.addNetworkSuggestions(list)
    if (result == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS)
        Log.d("AppLog", "success")
    else Log.d("AppLog", "failed")
}

Lors de l'exécution (je lui ai donné les détails de mon réseau Wifi, après avoir fait oublier le système d'exploitation), il dit que cela a réussi, mais rien ne s'est produit sur les paramètres Wifi du système d'exploitation. Le réseau n'existe pas avec le mot de passe que j'ai ajouté. Donc je ne comprends vraiment pas ce que ça a fait ...

Après quelques longues secondes, j'ai remarqué une notification me demandant si je peux me connecter aux réseaux suggérés par l'application:

enter image description here

Mais quand j'ai choisi d'accepter, cela n'a rien fait, comme avant.

J'ai essayé de créer un autre POC, pensant que je l'avais peut-être mal fait, mais il n'a même pas affiché la notification. Puisque je pense que tout ce comportement est un bug, je l'ai signalé ici .

Non seulement cela, mais j'ai découvert que si en effet il est censé ajouter un réseau d'une manière ou d'une autre, il a encore de sérieuses restrictions, telles que le nombre maximal de réseaux ajoutés ( ici ) et supprimé lors de la désinstallation de l'application ( ici )

Questions

  1. Comment Android Q doit-il être géré exactement? N'y a-t-il vraiment plus d'API pour ajouter un réseau?

  2. Si WifiNetworkSuggestion ne consiste pas à ajouter un réseau, à quoi sert-il exactement?

  3. Étant donné que je ne connais pas suffisamment les détails de l'ajout d'un réseau, mon code est-il correct sur toutes les façons possibles d'ajouter un réseau? Je pose cette question car quelqu'un a écrit ici que les gens devraient activer le Wifi et s'assurer que pingSupplicant renvoie vrai. Est-ce vrai? Ou serait-ce suffisant d'appeler simplement addNetwork?

  4. S'il est désormais impossible d'ajouter un réseau à l'aide de l'API normale, existe-t-il peut-être une solution en utilisant un périphérique enraciné à la place? Peut-être une commande adb?

10
android developer

Je suis resté avec le même problème, mais d'une manière ou d'une autre, j'ai atteint un état reproductible pour connecter un réseau souhaité et je veux partager mes résultats, cela peut aider.

En résumé: Vous devez désactiver toutes les connexions automatiques avant d'appliquer la logique WifiNetworkSuggestion

Pour plus de détails, veuillez lire ce qui suit:

J'ai utilisé le code suivant (similaire à ce que vous utilisez):

private fun connectUsingNetworkSuggestion(ssid: String, password: String) {
    val wifiNetworkSuggestion = WifiNetworkSuggestion.Builder()
        .setSsid(ssid)
        .setWpa2Passphrase(password)
        .build()

    // Optional (Wait for post connection broadcast to one of your suggestions)
    val intentFilter =
        IntentFilter(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION);

    val broadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            if (!intent.action.equals(WifiManager.ACTION_WIFI_NETWORK_SUGGESTION_POST_CONNECTION)) {
                return
            }
            showToast("Connection Suggestion Succeeded")
            // do post connect processing here
        }
    }
    registerReceiver(broadcastReceiver, intentFilter)

    lastSuggestedNetwork?.let {
        val status = wifiManager.removeNetworkSuggestions(listOf(it))
        Log.i("WifiNetworkSuggestion", "Removing Network suggestions status is $status")
    }
    val suggestionsList = listOf(wifiNetworkSuggestion)
    var status = wifiManager.addNetworkSuggestions(suggestionsList)
    Log.i("WifiNetworkSuggestion", "Adding Network suggestions status is $status")
    if (status == WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_ADD_DUPLICATE) {
        showToast("Suggestion Update Needed")
        status = wifiManager.removeNetworkSuggestions(suggestionsList)
        Log.i("WifiNetworkSuggestion", "Removing Network suggestions status is $status")
        status = wifiManager.addNetworkSuggestions(suggestionsList)
    }
    if (status == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS) {
        lastSuggestedNetwork = wifiNetworkSuggestion
        lastSuggestedNetworkSSID = ssid
        showToast("Suggestion Added")
    }
}

Voici donc les étapes:

  1. Installer une nouvelle version/Ou supprimer toutes les suggestions que vous avez ajoutées avant
  2. Assurez-vous d'avoir oublié tous les réseaux environnants pour que votre appareil ne se connecte pas automatiquement
  3. Ajouter une liste de suggestions de réseaux wifi
  4. Accédez aux paramètres Wifi pour analyser les réseaux ou attendez la prochaine analyse
  5. Une invite de notification apparaîtra:

Notification Prompt 6. Lorsque vous appuyez sur "Oui", le système se connecte automatiquement via votre application et Internet fonctionne normalement. Voir ce qui suit:

Connected to Suggested Network

Veuillez noter ce qui suit:

  1. Si vous déconnectez le réseau des paramètres Wifi (c.-à-d. Appuyez sur l'icône de déconnexion du bac dans l'image suivante) votre réseau sera bloqué pendant 24 heures de la connexion automatique même si vous avez supprimé le réseau suggéré à l'aide de wifiManager.removeNetworkSuggestions(listOf(it)) et l'ajoutez à nouveau . Et même si vous désinstallez et réinstallez votre application

Connected Wifi details

Malheureusement, c'est une limitation ajoutée par Android Système comme décrit ici :

Si l'utilisateur utilise le sélecteur Wi-Fi pour se déconnecter explicitement de l'une des suggestions de réseau lorsqu'il y est connecté, ce réseau est mis sur liste noire pendant 24 heures. Pendant la période de liste noire, ce réseau ne sera pas pris en compte pour la connexion automatique, même si l'application supprime et rajoute la suggestion de réseau correspondant au réseau.

  1. Si vous désinstallez l'application alors que vous êtes connecté au WiFi suggéré, le système fermera automatiquement la connexion.
  2. Si vous avez plusieurs suggestions, vous pouvez les prioriser en utilisant WifiNetworkSuggestion.Builder().setPriority(<Priority Integer>) comme mentionné ici :

Spécifiez la priorité de ce réseau parmi les autres suggestions de réseau fournies par la même application (les priorités n'ont aucun impact sur les suggestions de différentes applications). Plus le nombre est élevé, plus la priorité est élevée (c'est-à-dire la valeur 0 = priorité la plus basse).

  1. Si vous avez appuyé sur "Non" dans l'invite de notification, vous pouvez le changer de (Settings > Apps & notifications > Special App access > Wi-Fi Control > App name) Comme décrit ici :

Un utilisateur refusant la notification de suggestion de réseau supprime l'autorisation CHANGE_WIFI_STATE de l'application. L'utilisateur peut accorder cette approbation ultérieurement en accédant au menu de contrôle Wi-Fi (Paramètres> Applications et notifications> Accès spécial aux applications> Contrôle Wi-Fi> Nom de l'application).

0
Mohammad Sayed