Skip to content

Commit 796f784

Browse files
committed
Fixed an issue on Android < Q where if the user already successfully connected to the network before, a new connection request with a wrong password would succeed. (Tested on Android 8.1 OnePlus 5T)
Changed the WIFI behavior when disconnecting from an app-created network on Android < Q to be loosely similar to observed behvaior on Android 11 (OnePlus 7 Pro) where the device will try to reconnect to the previously connected network.
1 parent 4fe564b commit 796f784

File tree

1 file changed

+102
-25
lines changed

1 file changed

+102
-25
lines changed

packages/wifi_iot/android/src/main/java/com/alternadom/wifiiot/WifiIotPlugin.java

Lines changed: 102 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import android.net.NetworkRequest;
1515
import android.net.wifi.ScanResult;
1616
import android.net.wifi.SoftApConfiguration;
17-
import android.net.wifi.SupplicantState;
1817
import android.net.wifi.WifiConfiguration;
1918
import android.net.wifi.WifiInfo;
2019
import android.net.wifi.WifiManager;
@@ -49,6 +48,8 @@
4948
import org.json.JSONArray;
5049
import org.json.JSONException;
5150
import org.json.JSONObject;
51+
import java.util.Random;
52+
import android.net.wifi.SupplicantState;
5253

5354
/** WifiIotPlugin */
5455
public class WifiIotPlugin
@@ -73,6 +74,8 @@ public class WifiIotPlugin
7374
private List<WifiNetworkSuggestion> networkSuggestions;
7475
private List<String> ssidsToBeRemovedOnExit = new ArrayList<String>();
7576
private List<WifiNetworkSuggestion> suggestionsToBeRemovedOnExit = new ArrayList<>();
77+
//last connected network ID from outside the app
78+
private int lastConnectedNetworkId = -1;
7679

7780
// Permission request management
7881
private boolean requestingPermission = false;
@@ -98,20 +101,12 @@ private void initWithActivity(Activity activity) {
98101

99102
// cleanup
100103
private void cleanup() {
101-
if (!ssidsToBeRemovedOnExit.isEmpty()) {
102-
List<WifiConfiguration> wifiConfigList = moWiFi.getConfiguredNetworks();
103-
for (String ssid : ssidsToBeRemovedOnExit) {
104-
for (WifiConfiguration wifiConfig : wifiConfigList) {
105-
if (wifiConfig.SSID.equals(ssid)) {
106-
moWiFi.removeNetwork(wifiConfig.networkId);
107-
}
108-
}
109-
}
110-
}
104+
removeAddedNetworks();
111105
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && !suggestionsToBeRemovedOnExit.isEmpty()) {
112106
moWiFi.removeNetworkSuggestions(suggestionsToBeRemovedOnExit);
113107
}
114108
// setting all members to null to avoid memory leaks
109+
lastConnectedNetworkId = -1;
115110
channel = null;
116111
eventChannel = null;
117112
moActivity = null;
@@ -120,6 +115,20 @@ private void cleanup() {
120115
moWiFiAPManager = null;
121116
}
122117

118+
private void removeAddedNetworks() {
119+
if (!ssidsToBeRemovedOnExit.isEmpty()) {
120+
List<WifiConfiguration> wifiConfigList = moWiFi.getConfiguredNetworks();
121+
for (String ssid : ssidsToBeRemovedOnExit) {
122+
for (WifiConfiguration wifiConfig : wifiConfigList) {
123+
if (wifiConfig.SSID.equals(ssid)) {
124+
moWiFi.removeNetwork(wifiConfig.networkId);
125+
}
126+
}
127+
}
128+
}
129+
ssidsToBeRemovedOnExit.clear();
130+
}
131+
123132
/** Plugin registration. This is used for registering with v1 Android embedding. */
124133
public static void registerWith(Registrar registrar) {
125134
final MethodChannel channel = new MethodChannel(registrar.messenger(), "wifi_iot");
@@ -968,7 +977,7 @@ private void registerWifiNetwork(final MethodCall poCall, final Result poResult)
968977
android.net.wifi.WifiConfiguration conf =
969978
generateConfiguration(ssid, bssid, password, security, isHidden);
970979

971-
int updateNetwork = registerWifiNetworkDeprecated(conf);
980+
int updateNetwork = registerWifiNetworkDeprecated(conf, false);
972981

973982
if (updateNetwork == -1) {
974983
poResult.error("Error", "Error updating network configuration", "");
@@ -1107,6 +1116,10 @@ private void disconnect(Result poResult) {
11071116
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
11081117
//noinspection deprecation
11091118
disconnected = moWiFi.disconnect();
1119+
if(lastConnectedNetworkId != -1) {
1120+
//android 8.1 won't automatically reconnect to the previous network if it shares the same SSID
1121+
moWiFi.enableNetwork(lastConnectedNetworkId, true);
1122+
}
11101123
} else {
11111124
if (networkCallback != null) {
11121125
final ConnectivityManager connectivityManager =
@@ -1186,14 +1199,24 @@ private void removeWifiNetwork(MethodCall poCall, Result poResult) {
11861199
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
11871200
List<android.net.wifi.WifiConfiguration> mWifiConfigList = moWiFi.getConfiguredNetworks();
11881201
for (android.net.wifi.WifiConfiguration wifiConfig : mWifiConfigList) {
1189-
String comparableSSID = ('"' + prefix_ssid); //Add quotes because wifiConfig.SSID has them
1190-
if (wifiConfig.SSID.startsWith(comparableSSID)) {
1191-
moWiFi.removeNetwork(wifiConfig.networkId);
1192-
moWiFi.saveConfiguration();
1193-
removed = true;
1194-
break;
1202+
String comparableSSID = ('"' + prefix_ssid + '"'); //Add quotes because wifiConfig.SSID has them
1203+
if (wifiConfig.SSID.equals(comparableSSID)) {
1204+
Boolean isRemoved = moWiFi.removeNetwork(wifiConfig.networkId);
1205+
if(isRemoved) {
1206+
moWiFi.saveConfiguration();
1207+
removed = true;
1208+
//if the last connected network was our app's network, reset the last connected network
1209+
if(wifiConfig.networkId == lastConnectedNetworkId) {
1210+
lastConnectedNetworkId = -1;
1211+
}
1212+
}
1213+
//multiple networks with the same SSID could be removed
11951214
}
11961215
}
1216+
if(lastConnectedNetworkId != -1) {
1217+
//android 8.1 won't automatically reconnect to the previous network if it shares the same SSID
1218+
moWiFi.enableNetwork(lastConnectedNetworkId, true);
1219+
}
11971220
}
11981221

11991222
// remove network suggestion
@@ -1399,7 +1422,7 @@ public void onUnavailable() {
13991422
}
14001423

14011424
@SuppressWarnings("deprecation")
1402-
private int registerWifiNetworkDeprecated(android.net.wifi.WifiConfiguration conf) {
1425+
private int registerWifiNetworkDeprecated(android.net.wifi.WifiConfiguration conf, Boolean joinOnce) {
14031426
int updateNetwork = -1;
14041427
int registeredNetwork = -1;
14051428

@@ -1414,14 +1437,51 @@ private int registerWifiNetworkDeprecated(android.net.wifi.WifiConfiguration con
14141437
|| wifiConfig.BSSID.equals(conf.BSSID))) {
14151438
conf.networkId = wifiConfig.networkId;
14161439
registeredNetwork = wifiConfig.networkId;
1417-
updateNetwork = moWiFi.updateNetwork(conf);
1440+
//only try to update the configuration if joinOnce is false
1441+
//otherwise use the new add/update method
1442+
if(joinOnce == false) {
1443+
updateNetwork = moWiFi.updateNetwork(conf);
1444+
//required for pre API 26
1445+
moWiFi.saveConfiguration();
1446+
}
1447+
//Android 6.0 and higher no longer allows you to update a network that wasn't created
1448+
//from our app, nor delete it, nor add a network with the same SSID
1449+
//See https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html#behavior-network
1450+
if(updateNetwork == -1) {
1451+
//we add some random number to the conf SSID, add that network, then change the SSID
1452+
// back to circumvent the issue
1453+
String ssid = conf.SSID;
1454+
Random random = new Random(System.currentTimeMillis());
1455+
//loop in the rare case that the generated ssid already exists
1456+
for (int i = 0; i < 20; i++) {
1457+
int randomInteger = random.nextInt(10000);
1458+
//create a valid SSID with max length of 32
1459+
String ssidRandomized = ssid+randomInteger;
1460+
int ssidRandomizedExtraLength = ssidRandomized.length()-32;
1461+
if(ssidRandomizedExtraLength > 0) {
1462+
ssidRandomized = ssid.substring(0,ssid.length()-ssidRandomizedExtraLength)+randomInteger;
1463+
}
1464+
conf.SSID = "\"" + ssidRandomized + "\"";
1465+
updateNetwork = moWiFi.addNetwork(conf); // Add my wifi with another name
1466+
conf.SSID = ssid;
1467+
conf.networkId = updateNetwork;
1468+
updateNetwork = moWiFi.updateNetwork(conf); // After my wifi is added with another name, I change it to the desired name
1469+
moWiFi.saveConfiguration();
1470+
if(updateNetwork != -1) {
1471+
break;
1472+
}
1473+
}
1474+
}
1475+
//no need to continue looping
1476+
break;
14181477
}
14191478
}
14201479
}
14211480

14221481
/// If network not already in configured networks add new network
14231482
if (updateNetwork == -1) {
14241483
updateNetwork = moWiFi.addNetwork(conf);
1484+
conf.networkId = updateNetwork;
14251485
moWiFi.saveConfiguration();
14261486
}
14271487

@@ -1491,7 +1551,7 @@ private Boolean connectToDeprecated(
14911551
android.net.wifi.WifiConfiguration conf =
14921552
generateConfiguration(ssid, bssid, password, security, isHidden);
14931553

1494-
int updateNetwork = registerWifiNetworkDeprecated(conf);
1554+
int updateNetwork = registerWifiNetworkDeprecated(conf, joinOnce);
14951555

14961556
if (updateNetwork == -1) {
14971557
return false;
@@ -1500,6 +1560,9 @@ private Boolean connectToDeprecated(
15001560
if (joinOnce != null && joinOnce.booleanValue()) {
15011561
ssidsToBeRemovedOnExit.add(conf.SSID);
15021562
}
1563+
if(lastConnectedNetworkId == -1) {
1564+
lastConnectedNetworkId = moWiFi.getConnectionInfo().getNetworkId();
1565+
}
15031566

15041567
boolean disconnect = moWiFi.disconnect();
15051568
if (!disconnect) {
@@ -1510,24 +1573,38 @@ private Boolean connectToDeprecated(
15101573
if (!enabled) return false;
15111574

15121575
boolean connected = false;
1576+
int networkId = -1;
15131577
for (int i = 0; i < 20; i++) {
15141578
WifiInfo currentNet = moWiFi.getConnectionInfo();
1515-
int networkId = currentNet.getNetworkId();
1579+
networkId = currentNet.getNetworkId();
15161580
SupplicantState netState = currentNet.getSupplicantState();
15171581

15181582
// Wait for connection to reach state completed
15191583
// to discard false positives like auth error
15201584
if (networkId != -1 && netState == SupplicantState.COMPLETED) {
15211585
connected = networkId == updateNetwork;
1522-
break;
1586+
if(connected == true) {
1587+
break;
1588+
} else {
1589+
disconnect = moWiFi.disconnect();
1590+
if (!disconnect) {
1591+
break;
1592+
}
1593+
1594+
enabled = moWiFi.enableNetwork(updateNetwork, true);
1595+
break;
1596+
}
15231597
}
15241598
try {
1525-
Thread.sleep(500);
1599+
Thread.sleep(1000);
15261600
} catch (InterruptedException ignored) {
15271601
break;
15281602
}
15291603
}
1530-
1604+
if(!connected && lastConnectedNetworkId != -1) {
1605+
//android 8.1 won't automatically reconnect to the previous network if it shares the same SSID
1606+
moWiFi.enableNetwork(lastConnectedNetworkId, true);
1607+
}
15311608
return connected;
15321609
}
15331610
}

0 commit comments

Comments
 (0)