1414import android .net .NetworkRequest ;
1515import android .net .wifi .ScanResult ;
1616import android .net .wifi .SoftApConfiguration ;
17- import android .net .wifi .SupplicantState ;
1817import android .net .wifi .WifiConfiguration ;
1918import android .net .wifi .WifiInfo ;
2019import android .net .wifi .WifiManager ;
4948import org .json .JSONArray ;
5049import org .json .JSONException ;
5150import org .json .JSONObject ;
51+ import java .util .Random ;
52+ import android .net .wifi .SupplicantState ;
5253
5354/** WifiIotPlugin */
5455public 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