2424
2525import java .io .IOException ;
2626import java .net .Inet4Address ;
27+ import java .net .Inet6Address ;
28+ import java .net .InetAddress ;
29+ import java .net .NetworkInterface ;
30+ import java .net .SocketException ;
2731import java .util .ArrayList ;
32+ import java .util .Enumeration ;
33+ import java .util .HashMap ;
2834import java .util .List ;
35+ import java .util .Map ;
2936import java .util .Objects ;
3037import java .util .concurrent .ConcurrentHashMap ;
3138import java .util .concurrent .CountDownLatch ;
@@ -263,51 +270,134 @@ public void onUnavailable() {
263270 }
264271 }
265272
273+ // Create networkMap to select correct network via NetworkInterface (fallback)
274+ Map <String , Network > networkMap = new HashMap <>();
275+ for (Network network : wifiNetworks ) {
276+ NetworkCapabilities nc = cm .getNetworkCapabilities (network );
277+ LinkProperties lp = cm .getLinkProperties (network );
278+ if (lp != null ) {
279+ for (LinkAddress address : lp .getLinkAddresses ()) {
280+ InetAddress inetAddress = address .getAddress ();
281+ if (inetAddress instanceof Inet4Address || inetAddress instanceof Inet6Address ) {
282+ networkMap .put (inetAddress .getHostAddress (), network );
283+ }
284+ }
285+ }
286+ }
287+
266288 // Check exist at least one newtwork based on selected transport type
267289 if (!wifiNetworks .isEmpty ()) {
268290 boolean networkFound = false ;
269- for (Network network : wifiNetworks ) {
270- LinkProperties linkProperties = cm .getLinkProperties (network );
271- // Ensure linkProperties is not null
272- if (linkProperties == null )
273- continue ;
274-
275- if (android .os .Build .VERSION .SDK_INT >= android .os .Build .VERSION_CODES .R ) {
276- Inet4Address foundServerAddress = linkProperties .getDhcpServerAddress ();
277- if (iotDeviceHost .equals (foundServerAddress .getHostAddress ())) {
278- // found ioT device network
279- currentNetwork .setNetwork (network );
280- cm .bindProcessToNetwork (network );
281- networkFound = true ;
282- awaitingNetwork .countDown (); // Stop waiting
283- break ;
284- }
285- } else {
291+
292+ if (wifiNetworks .size () == 1 ) {
293+ // Single network scenario --> // Use that network in any case
294+ Network network = wifiNetworks .get (0 );
295+ currentNetwork .setNetwork (network );
296+ cm .bindProcessToNetwork (network );
297+ networkFound = true ;
298+ } else {
299+ // Multiple network scenario
300+ for (Network network : wifiNetworks ) {
301+ LinkProperties linkProperties = cm .getLinkProperties (network );
302+ // Ensure linkProperties is not null
303+ if (linkProperties == null )
304+ continue ;
305+
286306 List <LinkAddress > linkAddressList = linkProperties .getLinkAddresses ();
287- if (linkAddressList != null && !linkAddressList .isEmpty ()) {
288- for (LinkAddress address : linkAddressList ) {
289- int lastDotIndex = iotDeviceHost .lastIndexOf ('.' );
290- String iotSubnetAddress = iotDeviceHost ;
291- if (lastDotIndex >=0 )
292- iotSubnetAddress = iotDeviceHost .substring (0 , lastDotIndex );
293- if (address .getAddress ().getHostAddress ().startsWith (iotSubnetAddress )) {
307+ if (android .os .Build .VERSION .SDK_INT >= android .os .Build .VERSION_CODES .R ) {
308+ // Android version >= 11
309+ Inet4Address foundServerAddress = linkProperties .getDhcpServerAddress ();
310+ if (foundServerAddress != null ) {
311+ String foundAddress = foundServerAddress .getHostAddress ();
312+ if (foundAddress != null && foundAddress .contains (iotDeviceHost )) {
294313 // found ioT device network
295314 currentNetwork .setNetwork (network );
296315 cm .bindProcessToNetwork (network );
297316 networkFound = true ;
298- awaitingNetwork .countDown (); // Stop waiting
299317 break ;
300318 }
319+ } else if (linkAddressList != null && !linkAddressList .isEmpty ()) {
320+ // Fallback to linkAddresses if DHCP server address is null
321+ for (LinkAddress address : linkAddressList ) {
322+ int lastDotIndex = iotDeviceHost .lastIndexOf ('.' );
323+ String iotSubnetAddress = iotDeviceHost ;
324+ if (lastDotIndex >= 0 )
325+ iotSubnetAddress = iotDeviceHost .substring (0 , lastDotIndex );
326+ if (address .getAddress ().getHostAddress ().startsWith (iotSubnetAddress )) {
327+ // Found IoT device network
328+ currentNetwork .setNetwork (network );
329+ cm .bindProcessToNetwork (network );
330+ networkFound = true ;
331+ break ;
332+ }
333+ }
334+ }
335+ } else {
336+ // Android version < 11
337+ if (linkAddressList != null && !linkAddressList .isEmpty ()) {
338+ for (LinkAddress address : linkAddressList ) {
339+ int lastDotIndex = iotDeviceHost .lastIndexOf ('.' );
340+ String iotSubnetAddress = iotDeviceHost ;
341+ if (lastDotIndex >=0 )
342+ iotSubnetAddress = iotDeviceHost .substring (0 , lastDotIndex );
343+ if (address .getAddress ().getHostAddress ().startsWith (iotSubnetAddress )) {
344+ // found ioT device network
345+ currentNetwork .setNetwork (network );
346+ cm .bindProcessToNetwork (network );
347+ networkFound = true ;
348+ break ;
349+ }
350+ }
301351 }
302352 }
303353 }
304354 }
305- if (!networkFound ) {
306- awaitingNetwork .countDown (); // Stop waiting if no network was found
355+
356+ // Fallback 1 -> if no matching network is found try selecting via NetworkInterface
357+ if (!networkFound && wifiNetworks .size () > 1 ) {
358+ try {
359+ Enumeration <NetworkInterface > networkInterfaces = NetworkInterface .getNetworkInterfaces ();
360+ while (networkInterfaces .hasMoreElements ()) {
361+ NetworkInterface networkInterface = networkInterfaces .nextElement ();
362+ if (!networkInterface .isUp () || networkInterface .isLoopback ()) continue ;
363+
364+ Enumeration <InetAddress > inetAddresses = networkInterface .getInetAddresses ();
365+ while (inetAddresses .hasMoreElements ()) {
366+ InetAddress inetAddress = inetAddresses .nextElement ();
367+ if (inetAddress instanceof Inet4Address ) {
368+ if (inetAddress != null && iotDeviceHost .equals (inetAddress .getHostAddress ())) {
369+ // Cerca la rete corrispondente nell'HashMap
370+ Network matchedNetwork = networkMap .get (inetAddress .getHostAddress ());
371+ if (matchedNetwork != null ) {
372+ // Found IoT device network
373+ currentNetwork .setNetwork (matchedNetwork );
374+ cm .bindProcessToNetwork (matchedNetwork );
375+ networkFound = true ;
376+ break ;
377+ }
378+ }
379+ }
380+ }
381+ }
382+ } catch (SocketException e ) {
383+ // Fallback 2 -> if no matching network is found try select last wifiNetwork in the list
384+ if (!networkFound && wifiNetworks .size () > 1 ) {
385+ Network fallbackNetwork = wifiNetworks .get (wifiNetworks .size () - 1 ); // Get last network from the list
386+ currentNetwork .setNetwork (fallbackNetwork );
387+ cm .bindProcessToNetwork (fallbackNetwork );
388+ }
389+ }
390+ }
391+
392+ // Fallback 2 -> if no matching network is found try select last wifiNetwork in the list
393+ if (!networkFound && wifiNetworks .size () > 1 ) {
394+ Network fallbackNetwork = wifiNetworks .get (wifiNetworks .size () - 1 ); // Get last network from the list
395+ currentNetwork .setNetwork (fallbackNetwork );
396+ cm .bindProcessToNetwork (fallbackNetwork );
307397 }
308- } else {
309- awaitingNetwork .countDown (); // Stop waiting
310398 }
399+
400+ awaitingNetwork .countDown (); // Stop waiting
311401 } else {
312402 awaitingNetwork .countDown (); // Stop waiting
313403 }
@@ -327,8 +417,6 @@ public void run() {
327417 awaitingNetwork .await ();
328418 }
329419
330- // REQUEST NETWORK
331-
332420 /**
333421 * Returns a network given its interface name:
334422 * "wifi" -> WIFI
0 commit comments