As most of you would know, AndroidThings supports both Ethernet interface and WLAN interface. This means you can connect Pi to an Ethernet and also to a WiFi network simultaneously. In such a scenario Pi will have two IP addresses, one because of Ethernet connection while the other because of WiFi connection.
Below screenshot shows the same.
Generally, in these scenarios, Pi will make one of the interfaces as active interface and choose the same for all the network communications. For example, Pi can make Ethernet interface as active and can only communicate with devices in that network.
This was important for us because we wanted to try working on a GoPro camera based project withthe below requirements.
- Connect GoPro camera to Pi through WiFi and download the video recordings.
- Upload the above video recordings to Google Drive via Ethernet interface.
This was not possible out of the box because system would have chosen an active interface (Ethernet most of the times) and will not let us communicate over the other interface (WiFi in this case).
In order to check the feasibility of the project, we created a test setup.
We built TCP server running in Network 1. Raspberry Pi’s WiFi interface was made to connect to Network 1.
Another network called Network 2 was connected to Raspberry Pi through the Ethernet interface.
Wrote an App with a TCP Client Socket and tried to communicate with TCP Server running on Network 1.
In our case, Ethernet interface was the active interface and hence our client socket did not connect to TCP server.
We tried making use of socket.bind() by passing WLAN interface and then also we were not able to connect with TCP server.
//bind did not work for us.
Socket clientSocket = new Socket();
clientSocket.bind(wlanInterface.getInetAddresses().nextElement());
clientSocket.connect (new InetSocketAddress( ip,port));
Finally, after all the exploration we came across ConnectivityManager which provides a way for processes to choose their communication interface.
We have to bind the process to a required interface. In our case, we used ConnectivityManager to bind to WLAN before creating our client socket.
connectivitymanager.bindProcessToNetwork(wlannetwork);
Socket clientSocket = new Socket();
clientSocket.connect (new InetSocketAddress(ip, port));
public static Network findWlanNetwork(Context context){
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
Network etherNetwork = null;
for (Network network : connectivityManager.getAllNetworks()) {
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
return network;
}
}
return null;
}
This seems to be providing our required test result. We are able to communicate with the TCP server running at Network 1, while our Ethernet interface is still active in Network 2.
Thus we concluded that by defining a separate process and using ConnectivityManager we can achieve the communication through both WiFi and Ethernet interfaces.
Related reads:
1) Customizing-dialog-in-Android