WiFiFlutter
WiFiFlutter copied to clipboard
Could not get gateway ip after connecting to iot device and setting forceWifiUsage(true);
Android Studio: Giraffe | 2022.3.1 Flutter SDK: 3.10.6 wifi_iot: ^0.3.18+1 network_info_plus: ^4.0.2 Android Phone: Pixel 3a, Android 12 android/app/src/main/AndroidManifes.xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
code snippet:
const ssid = 'IGD-MY-IOT-SSID';
WiFiForIoTPlugin.connect(ssid,
withInternet: false, security: NetworkSecurity.NONE)
.then((value) async {
String currentSsid = await WiFiForIoTPlugin.getSSID() ?? '';
String ip = await WiFiForIoTPlugin.getIP() ?? '';
if (Platform.isAndroid) {
if (value) {
WiFiForIoTPlugin.forceWifiUsage(true);
dprint('success to connect with Andorid');
final gatewayIP = await NetworkInfo().getWifiGatewayIP(); // null
debugPrint('Adnroid, current gateway ip: $gatewayIP');
debugPrint('Android, current_ssid: $currentSsid, current_ip: $ip'); // work as expected
} else {
dprint('failure to connect with Andorid');
throw CustomError('Android Wifi Failure');
}
}
})
I am using wifi_iot
on my Android Phone to connect to my IoT device which act as an wifi-spot without Internet connection.
After connecting successfully, I was able to send an HTTP request to my IoT device with a successful response JSON.
However, the IP address of my IoT device (used for sending http request from my Android Phone to it) is hardcoded in my code.
Therefore, I used network_info_plus 4.0.2
to obtain the gateway IP of my Android Phone (which happens to be the ip address of my iot device) so that I can remove the hardcoded IP address from my code.
I have tested that if I connect to my IoT device through the settings page, network_info_plus 4.0.2
is able to retrieve the gateway IP. However, if I connect to my IoT device using the above code, network_info_plus 4.0.2
will return null for the gateway IP address.
I am aware that this is similar to this issue: https://github.com/flutternetwork/WiFiFlutter/issues/181, I read the instruction there but still can not solve my problem.
By the way, on my iPhone, there is no problem, wifi_iot
and network_info_plus
works seamlessly.
Please let me know if I need to provide further information or if I am missing something. Thank you very much.
After investigating the source code of network_info_plus 4.0.2
and wifi_iot
, I found the following:
- After
wifi_iot.selectNetwork
get called, thenetwork
is not an active network. - The Implementation of
network_info_plus.getGatewayIPAddress
use an active network to retrieve gatewayIP, therefore it returns null.
fun getGatewayIPAddress(): String? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val linkAddresses = connectivityManager?.getLinkProperties(connectivityManager.activeNetwork)
val dhcpServer = linkAddresses?.dhcpServerAddress?.hostAddress
dhcpServer
} else {
@Suppress("DEPRECATION")
val dhcpInfo = wifiManager.dhcpInfo
val gatewayIPInt = dhcpInfo?.gateway
Log.w("my_log_tag", "depercate, gatewayIPInt: $gatewayIPInt");
gatewayIPInt?.let { formatIPAddress(it) }
}
}
- Insdie the implementation of
wifi_iot.selectNetwrok
, if I do the following, I can get get getwayIp I needed:
private boolean selectNetwork(final Network network, final ConnectivityManager manager) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
boolean isBinded = manager.bindProcessToNetwork(network);
Log.w("my_log_tag", String.format("bindProcessToNetwork: %b, network: %s", isBinded, network.toString()));
LinkProperties linkAddresses = manager.getLinkProperties(network);
if (linkAddresses == null) {
Log.w("my_log_tag", "!!! null linkAddress");
return isBinded;
}
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R) {
Log.w("my_log_tag", "!!! SDK version < R");
return isBinded;
}
Inet4Address dhcpServerAddress = linkAddresses.getDhcpServerAddress();
if (dhcpServerAddress == null) {
Log.w("my_log_tag", "!!! null dhcpServerAddress");
return isBinded;
}
String hostAddress = dhcpServerAddress.getHostAddress();
if (hostAddress == null) {
Log.w("my_log_tag", "!!! null hostAddress");
return isBinded;
}
/// code successfully ran through here, the host address is 192.168.xxx.xxx
Log.w("my_log_tag", String.format("get getway hostAddress: %s", hostAddress));
return isBinded;
} else {
return ConnectivityManager.setProcessDefaultNetwork(network);
}
}
Now I know more about why did I got null gatewayIp in my original code snippet.
However, I have limited knowledge about networking and Android, I am not sure what's the proper way to fix it.
It seems to me that in my use case, it is the implementaion of network_info_plus.getGatewayIPAddress
needs to be change as something like this:
fun getGatewayIPAddress(): String? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
val network = connectivityManager?.allNetworks?.first() // but allNetworks is deprecated on API level 31
val linkAddresses = connectivityManager?.getLinkProperties(network);
val dhcpServer = linkAddresses?.dhcpServerAddress?.hostAddress
dhcpServer
} else {
@Suppress("DEPRECATION")
val dhcpInfo = wifiManager.dhcpInfo
val gatewayIPInt = dhcpInfo?.gateway
Log.w("my_log_tag", "depercate, gatewayIPInt: $gatewayIPInt");
gatewayIPInt?.let { formatIPAddress(it) }
}
}
If so, please close this issue or you may give me some further suggestion, thank you.
I was having similar issue with this and I tried using "findAndConnect" and then forceWifi for Android and this then connected properly and allow me to hit the server on that network. I'll need to do dome more digging but his allow me to continue using the plugin. Also not that for iOS I had use "connect" as 'findAndConnect' did not work.
Hi ctwdtw You said:
I am using
wifi_iot
on my Android Phone to connect to my IoT device which act as an wifi-spot without Internet connection. After connecting successfully, I was able to send an HTTP request to my IoT device with a successful response JSON.
I would like to know if, you Android Phone could use internet over mobile data, while you app is sending HTTP requests and receiving responses from you IOT device. Are you connecting to your iot device through standard wifi or wifi-direct?