Reputation: 1
` I’m developing an Android app that intended to use Ethernet to discover BACnet devices on the local network, while Wi-Fi is used for general internet connectivity. The device has both Ethernet and Wi-Fi interfaces connected simultaneously.
Issue: When I bind my app’s process to a specific network interface (Ethernet or Wi-Fi), the network binding appears to succeed, as indicated by the logs. However, I am unable to discover BACnet devices over Ethernet after binding, when both Ethernet and Wi-Fi are active. This issue occurs on Android 12 (API level 31). The same code works on older Android versions (like Android 7) where I can successfully discover devices using either interface.
Details: App Behavior:
When only one interface (Ethernet or Wi-Fi) is active, the app successfully discovers devices on that network. When both interfaces (Ethernet and Wi-Fi) are active, I bind to the required interface using bindProcessToNetwork(). The logs show that the process is successfully bound, but the device discovery fails over Ethernet (BACnet devices are discovered but I am unable to fetch objects).
Observed Behavior:
The app logs show that the process is bound to Ethernet (TRANSPORT_ETHERNET), but no BACnet devices are discovered. When I disable Wi-Fi, the devices on Ethernet are successfully discovered. The same code works perfectly on Android 7, where the app can discover devices using either interface, even when both are active.
Environment: Android Version: 12 (API level 31) App Requirement: Wi-Fi is needed for general internet access. Ethernet is used for BACnet device discovery on the local network.
Network Binding Code
private static void bindToBestNetwork() {
Network[] networks = connectivityManager.getAllNetworks();
Network ethernetNetwork = null;
Network wifiNetwork = null;
// Check available networks and prioritize Ethernet
for (Network network : networks) {
NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
if (capabilities != null) {
if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
ethernetNetwork = network;
} else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
wifiNetwork = network;
}
}
}
// Prioritize Ethernet, fall back to Wi-Fi if Ethernet is not available
if (ethernetNetwork != null) {
WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(false);
ConnectivityManager.setProcessDefaultNetwork(ethernetNetwork);
boolean success = connectivityManager.bindProcessToNetwork(ethernetNetwork);
wifiManager.disconnect();
WifiManager.MulticastLock multicastLock = wifiManager.createMulticastLock("bacnetLock");
multicastLock.setReferenceCounted(true);
multicastLock.acquire();
try {
Log.d(TAG,"Binding socket to Ethernet network");
DatagramSocket socket = new DatagramSocket();
ethernetNetwork.bindSocket(socket);
} catch (Exception e) {
Log.d(TAG,"Exception while binding socket to Ethernet network");
e.printStackTrace();
}
if (success) {
Log.d(TAG, "Ethernet network successfully bound");
} else {
Log.d(TAG, "Ethernet network binding failed");
}
} else if (wifiNetwork != null) {
boolean success = connectivityManager.bindProcessToNetwork(wifiNetwork);
if (success) {
Log.d(TAG, "Wi-Fi network successfully bound");
} else {
Log.d(TAG, "Wi-Fi network binding failed");
}
} else {
connectivityManager.bindProcessToNetwork(null);
}
}
// Register a callback for Ethernet network
private static void registerEthernetListener() {
Log.d(TAG, "Registering Ethernet listener");
NetworkRequest ethernetRequest = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
ethernetCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
Log.d(TAG, "Ethernet network Available");
bindToBestNetwork();
}
@Override
public void onLost(Network network) {
Log.d(TAG, "Ethernet network lost");
bindToBestNetwork();
}
};
connectivityManager.requestNetwork(ethernetRequest,ethernetCallback);
}
// Register a callback for Wi-Fi network
private static void registerWifiListener() {
Log.d(TAG, "Registering Wi-Fi listener");
NetworkRequest wifiRequest = new NetworkRequest.Builder()
.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
wifiCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
Log.d(TAG, "Wi-Fi network Available");
bindToBestNetwork();
}
@Override
public void onLost(Network network) {
Log.d(TAG, "Wi-Fi network lost");
bindToBestNetwork();
}
};
connectivityManager.requestNetwork(wifiRequest, wifiCallback);
}
Upvotes: 0
Views: 25
Reputation: 488
Sounds like the BACnet stack that you're using might also (now / for Android 12) need to be told which NIC (Network Interface Card) to use.
Try using (/can you use?) Wireshark to check/confirm what's happening.
Upvotes: 0