3
3
import com .facebook .react .bridge .*;
4
4
5
5
import android .net .ConnectivityManager ;
6
+ import android .net .Network ;
7
+ import android .net .NetworkCapabilities ;
6
8
import android .net .NetworkInfo ;
9
+ import android .net .NetworkRequest ;
7
10
import android .net .wifi .WifiInfo ;
8
11
import android .net .wifi .WifiManager ;
9
12
import android .net .wifi .WifiConfiguration ;
13
16
14
17
import java .util .List ;
15
18
19
+
20
+ class FailureCodes {
21
+ static int SYSTEM_ADDED_CONFIG_EXISTS = 1 ;
22
+ static int FAILED_TO_CONNECT = 2 ;
23
+ static int FAILED_TO_ADD_CONFIG = 3 ;
24
+ static int FAILED_TO_BIND_CONFIG = 4 ;
25
+ }
26
+
16
27
public class IOTWifiModule extends ReactContextBaseJavaModule {
17
- WifiManager wifiManager ;
18
- ConnectivityManager connectivityManager ;
19
- ReactApplicationContext context ;
20
-
28
+ private WifiManager wifiManager ;
29
+ private ConnectivityManager connectivityManager ;
30
+ private ReactApplicationContext context ;
31
+
21
32
public IOTWifiModule (ReactApplicationContext reactContext ) {
22
33
super (reactContext );
23
- wifiManager = (WifiManager ) getReactApplicationContext ().getApplicationContext ().getSystemService (Context .WIFI_SERVICE );
24
- connectivityManager = (ConnectivityManager ) getReactApplicationContext ().getApplicationContext ().getSystemService (Context .CONNECTIVITY_SERVICE );
34
+ wifiManager = (WifiManager ) getReactApplicationContext ().getApplicationContext ()
35
+ .getSystemService (Context .WIFI_SERVICE );
36
+ connectivityManager = (ConnectivityManager ) getReactApplicationContext ().getApplicationContext ()
37
+ .getSystemService (Context .CONNECTIVITY_SERVICE );
25
38
context = getReactApplicationContext ();
26
39
}
27
-
40
+
41
+ private String errorFromCode (int errorCode ) {
42
+ return "ErrorCode: " + errorCode ;
43
+ }
44
+
28
45
@ Override
29
46
public String getName () {
30
47
return "IOTWifi" ;
31
48
}
32
-
49
+
33
50
@ ReactMethod
34
- public void isAvaliable ( Callback callback ) {
51
+ public void isApiAvailable ( final Callback callback ) {
35
52
callback .invoke (true );
36
53
}
37
54
38
55
@ ReactMethod
39
- public void connect (String ssid , Callback callback ) {
40
- connectSecure (ssid , "" , false , callback );
56
+ public void connect (String ssid , Boolean bindNetwork , Callback callback ) {
57
+ connectSecure (ssid , "" , false , bindNetwork , callback );
41
58
}
42
59
43
60
@ ReactMethod
44
- public void connectSecure (final String ssid , final String passphrase , final Boolean isWEP , final Callback callback ) {
61
+ public void connectSecure (final String ssid , final String passphrase , final Boolean isWEP ,
62
+ final Boolean bindNetwork , final Callback callback ) {
45
63
new Thread (new Runnable () {
46
64
public void run () {
47
- connectToWifi (ssid , passphrase , isWEP , callback );
65
+ connectToWifi (ssid , passphrase , isWEP , bindNetwork , callback );
48
66
}
49
67
}).start ();
50
68
}
51
69
52
- private void connectToWifi (String ssid , String passphrase , Boolean isWEP , Callback callback ) {
70
+ private void connectToWifi (String ssid , String passphrase , Boolean isWEP , Boolean bindNetwork , Callback callback ) {
53
71
if (Build .VERSION .SDK_INT > 28 ) {
54
- callback .invoke ("Fail " );
72
+ callback .invoke ("Not supported on Android Q " );
55
73
return ;
56
74
}
75
+ if (!removeSSID (ssid )) {
76
+ callback .invoke (errorFromCode (FailureCodes .SYSTEM_ADDED_CONFIG_EXISTS ));
77
+ return ;
78
+ }
79
+
80
+ WifiConfiguration configuration = createWifiConfiguration (ssid , passphrase , isWEP );
81
+ int networkId = wifiManager .addNetwork (configuration );
82
+
83
+ if (networkId != -1 ) {
84
+ // Enable it so that android can connect
85
+ wifiManager .disconnect ();
86
+ boolean success = wifiManager .enableNetwork (networkId , true );
87
+ if (!success ) {
88
+ callback .invoke (errorFromCode (FailureCodes .FAILED_TO_ADD_CONFIG ));
89
+ return ;
90
+ }
91
+ success = wifiManager .reconnect ();
92
+ if (!success ) {
93
+ callback .invoke (errorFromCode (FailureCodes .FAILED_TO_CONNECT ));
94
+ return ;
95
+ }
96
+ boolean connected = pollForValidSSSID (10 , ssid );
97
+ if (!connected ) {
98
+ callback .invoke (errorFromCode (FailureCodes .FAILED_TO_CONNECT ));
99
+ return ;
100
+ }
101
+ if (!bindNetwork ) {
102
+ callback .invoke ();
103
+ return ;
104
+ }
105
+ try {
106
+ bindToNetwork (ssid , callback );
107
+ } catch (Exception e ) {
108
+ Log .d ("IoTWifi" , "Failed to bind to Wifi: " + ssid );
109
+ callback .invoke ();
110
+ }
111
+ } else {
112
+ callback .invoke (errorFromCode (FailureCodes .FAILED_TO_ADD_CONFIG ));
113
+ }
114
+ }
115
+
116
+ private WifiConfiguration createWifiConfiguration (String ssid , String passphrase , Boolean isWEP ) {
57
117
WifiConfiguration configuration = new WifiConfiguration ();
58
118
configuration .SSID = String .format ("\" %s\" " , ssid );
59
119
@@ -71,70 +131,136 @@ private void connectToWifi(String ssid, String passphrase, Boolean isWEP, Callba
71
131
if (!wifiManager .isWifiEnabled ()) {
72
132
wifiManager .setWifiEnabled (true );
73
133
}
134
+ return configuration ;
135
+ }
74
136
75
- removeSSID (ssid );
137
+ private boolean pollForValidSSSID (int maxSeconds , String expectedSSID ) {
138
+ try {
139
+ for (int i = 0 ; i < maxSeconds ; i ++) {
140
+ String ssid = this .getWifiSSID ();
141
+ if (ssid != null && ssid .equalsIgnoreCase (expectedSSID )) {
142
+ return true ;
143
+ }
144
+ Thread .sleep (1000 );
145
+ }
146
+ } catch (InterruptedException e ) {
147
+ return false ;
148
+ }
149
+ return false ;
150
+ }
76
151
77
- // Add configuration to Android wifi manager settings...
78
- int networkId = wifiManager .addNetwork (configuration );
152
+ private void bindToNetwork (final String ssid , final Callback callback ) {
153
+ NetworkRequest .Builder builder = new NetworkRequest .Builder ();
154
+ builder .addTransportType (NetworkCapabilities .TRANSPORT_WIFI );
155
+ connectivityManager .requestNetwork (builder .build (), new ConnectivityManager .NetworkCallback () {
79
156
80
- if (networkId != -1 ) {
81
- // Enable it so that android can connect
82
- wifiManager .disconnect ();
83
- wifiManager .enableNetwork (networkId , true );
84
- boolean success = wifiManager .reconnect ();
85
- if (!success ) {
86
- callback .invoke ("Fail" );
87
- return ;
157
+ private boolean bound = false ;
158
+
159
+ @ Override
160
+ public void onAvailable (Network network ) {
161
+ String offeredSSID = getWifiSSID ();
162
+
163
+ if (!bound && offeredSSID .equals (ssid )) {
164
+ try {
165
+ bindProcessToNetwork (network );
166
+ bound = true ;
167
+ callback .invoke ();
168
+ return ;
169
+ } catch (Exception e ) {
170
+ e .printStackTrace ();
171
+ }
172
+ }
173
+ callback .invoke (errorFromCode (FailureCodes .FAILED_TO_BIND_CONFIG ));
88
174
}
89
- try {
90
- Thread .sleep (3000 );
91
- callback .invoke ();
92
- } catch (InterruptedException e ) {
93
- callback .invoke ("Fail" );
175
+
176
+ @ Override
177
+ public void onLost (Network network ) {
178
+ if (bound ) {
179
+ bindProcessToNetwork (null );
180
+ connectivityManager .unregisterNetworkCallback (this );
181
+ }
94
182
}
183
+ });
184
+ }
185
+
186
+ private void bindProcessToNetwork (final Network network ) {
187
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .M ) {
188
+ connectivityManager .bindProcessToNetwork (network );
95
189
} else {
96
- callback . invoke ( "Failed to add network configuration" );
190
+ ConnectivityManager . setProcessDefaultNetwork ( network );
97
191
}
98
192
}
99
193
100
194
@ ReactMethod
101
- public void removeSSID (String ssid , Callback callback ) {
102
- removeSSID (ssid );
195
+ public void removeSSID (String ssid , Boolean unbind , Callback callback ) {
196
+ if (!removeSSID (ssid )) {
197
+ callback .invoke (errorFromCode (FailureCodes .SYSTEM_ADDED_CONFIG_EXISTS ));
198
+ return ;
199
+ }
200
+ if (unbind ) {
201
+ bindProcessToNetwork (null );
202
+ }
203
+
103
204
callback .invoke ();
104
205
}
105
206
106
- public void removeSSID ( String ssid ) {
107
- // Remove the existing configuration for this netwrok
108
- List < WifiConfiguration > configList = wifiManager . getConfiguredNetworks () ;
109
- String comparableSSID = ( '"' + ssid + '"' ); // Add quotes because wifiConfig.SSID has them
110
- if ( configList != null ) {
111
- for ( WifiConfiguration wifiConfig : configList ) {
112
- if ( wifiConfig . SSID . equals ( comparableSSID )) {
113
- Log . d ( "wifi" , wifiConfig . toString ());
114
- int networkId = wifiConfig . networkId ;
115
- wifiManager . removeNetwork ( networkId );
116
- wifiManager . saveConfiguration () ;
117
- }
118
- }
207
+
208
+ private boolean removeSSID ( String ssid ) {
209
+ boolean success = true ;
210
+ // Remove the existing configuration for this network
211
+ WifiConfiguration existingNetworkConfigForSSID = getExistingNetworkConfig ( ssid );
212
+
213
+ //No Config found
214
+ if ( existingNetworkConfigForSSID == null ) {
215
+ return success ;
216
+ }
217
+ int existingNetworkId = existingNetworkConfigForSSID . networkId ;
218
+ if ( existingNetworkId == - 1 ) {
219
+ return success ;
119
220
}
221
+ success = wifiManager .removeNetwork (existingNetworkId ) && wifiManager .saveConfiguration ();
222
+ //If not our config then success would be false
223
+ return success ;
120
224
}
121
225
122
226
@ ReactMethod
123
227
public void getSSID (Callback callback ) {
228
+ String ssid = this .getWifiSSID ();
229
+ callback .invoke (ssid );
230
+ }
231
+
232
+ private String getWifiSSID () {
124
233
WifiInfo info = wifiManager .getConnectionInfo ();
125
234
String ssid = info .getSSID ();
126
235
127
- if (ssid == null || ssid == "<unknown ssid>" ) {
236
+ if (ssid == null || ssid . equalsIgnoreCase ( "<unknown ssid>" ) ) {
128
237
NetworkInfo nInfo = connectivityManager .getActiveNetworkInfo ();
129
238
if (nInfo != null && nInfo .isConnected ()) {
130
239
ssid = nInfo .getExtraInfo ();
131
240
}
132
241
}
133
242
134
- if (ssid .startsWith ("\" " ) && ssid .endsWith ("\" " )) {
243
+ if (ssid != null && ssid .startsWith ("\" " ) && ssid .endsWith ("\" " )) {
135
244
ssid = ssid .substring (1 , ssid .length () - 1 );
136
245
}
137
246
138
- callback .invoke (ssid );
247
+ return ssid ;
248
+ }
249
+
250
+ private WifiConfiguration getExistingNetworkConfig (String ssid ) {
251
+ WifiConfiguration existingNetworkConfigForSSID = null ;
252
+ List <WifiConfiguration > configList = wifiManager .getConfiguredNetworks ();
253
+ String comparableSSID = ('"' + ssid + '"' ); // Add quotes because wifiConfig.SSID has them
254
+ if (configList != null ) {
255
+ for (WifiConfiguration wifiConfig : configList ) {
256
+ if (wifiConfig .SSID .equals (comparableSSID )) {
257
+ Log .d ("IoTWifi" , "Found Matching Wifi: " + wifiConfig .toString ());
258
+ existingNetworkConfigForSSID = wifiConfig ;
259
+ break ;
260
+
261
+ }
262
+ }
263
+ }
264
+ return existingNetworkConfigForSSID ;
139
265
}
140
266
}
0 commit comments