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.
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.
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:
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 )
Comment Android Q doit-il être géré exactement? N'y a-t-il vraiment plus d'API pour ajouter un réseau?
Si WifiNetworkSuggestion
ne consiste pas à ajouter un réseau, à quoi sert-il exactement?
É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
?
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?
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:
6. Lorsque vous appuyez sur "Oui", le système se connecte automatiquement via votre application et Internet fonctionne normalement. Voir ce qui suit:
Veuillez noter ce qui suit:
wifiManager.removeNetworkSuggestions(listOf(it))
et l'ajoutez à nouveau . Et même si vous désinstallez et réinstallez votre applicationMalheureusement, 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.
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).
(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).