Working on an android application in which I need to connect WiFi device programatically which does not have internet. Here is a code:
private void connectToWiFi(final String ssid, String password) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
final ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
request.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); // Internet not required
ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
String networkSSID = getNetworkSsid();
if (networkSSID.equals(ssid)) {
connectivityManager.bindProcessToNetwork(network);
}
}
@Override
public void onUnavailable() {
super.onUnavailable();
}
@Override
public void onLost(@NonNull Network network) {
super.onLost(network);
}
};
connectivityManager.registerNetworkCallback(request.build(), networkCallback);
WifiConfiguration config = new WifiConfiguration();
config.SSID = String.format("\"%s\"", ssid);
int netId = -1;
List<WifiConfiguration> apList = wifiManager.getConfiguredNetworks();
for (WifiConfiguration i : apList) {
if (i.SSID != null && i.SSID.equals("\"" + ssid + "\"")) {
netId = i.networkId;
}
}
// Add network in Saves network list if it is not available in list
if (netId == -1) {
if (TextUtils.isEmpty(password)) {
Log.d(TAG, "====== Connect to open network");
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
} else {
Log.d(TAG, "====== Connect to secure network");
config.preSharedKey = String.format("\"%s\"", password);
}
netId = wifiManager.addNetwork(config);
}
Log.d(TAG, "Connect to Network : " + netId);
wifiManager.enableNetwork(netId, true);
} else {
// For Android 10 and above
// WifiNetworkSpecifier code
}
}
Permissions used :
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<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_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Above code works fine for the networks that offer internet connection. But it fails in most of the cases for the networks without internet connection.
When attempting to connect to a WiFi configuration which does not have internet access, we need to bind our app's process to that network, or configure our HTTP client to use that network's socket factory, otherwise the system will disconnect from this WiFi network.
As per this guideline , bindProcessToNetwork is already applied. But system is disconnecting from the network regardless of the use of bindToProcess() / routing traffic over the socket factory. It is not allowing to remain connected with the WiFi which don't have internet. It is really surprising, Android has never thought for IoT device use cases before restricting to network connection.
When attempting to connect to a WiFi network added by my app or system settings app or any other app, the system logs reveal:
UID xxxxx does not have permission to update configuration
Same error is not occurring when app tries to connect device which has internet even if that network is added by some other app.
So the app is allowed to connect to the previous configuration, albeit with 'insufficient permissions', and traffic is momentarily routed over this network. But after a few seconds, the network is disconnected, and the system attempts to re-associate with some other internet-enabled network.
Testing on Moto G5 Plus, Android 8.1.0, but I believe this is a platform bug, not device specific. And mostly this bug is introduced from Android 7 or something because it was working previously.
I have also reported issue here. Also provided sample app in this issue.
Is there any solution available for this issue ? Is there any option of paid support from Android ?
Thanks in advance.
conf.status = WifiConfiguration.Status.ENABLED;
. Try setting this. Not sure about it, this is why as a comment. – Peabody