I am searching for a way to let an Android 5.0 tablet connect to an intranet which does not have internet connection for security reasons.
Problem is the captive portal protection that Google build in android since 4.4/5.0. A call is done to android connectivitycheck to check for internet connection, when this call fails the wifi network is marked as not working and avoided. Pretty lame.
Others have run into the same issue and some suggest using a new API introduced in android 5, see: Android 5.0 Lollipop and 4.4 KitKat ignores my WiFi network, enableNetwork() is useless
The documentation on this is very vague:
NetworkRequest.Builder.setNetworkSpecifier(String networkSpecifier)
"The interpretation of this String is bearer specific and bearers that use it should document their particulars. For example, Bluetooth may use some sort of device id while WiFi could used ssid and/or bssid. Cellular may use carrier spn"
I tried this and it does not work. Main problem is that once I use setNetworkSpecifier()
no network is found. I tried using the bssid
(mac) and the ssid
of the AP.
It looks like the filter is working but its not clear how it should work.
If I leave out the setNetworkSpecifier()
call 1 network is found, but it is not possible to determine which. At least it shows my code works.
So what should I put in here if ssid and bssid does not work?
Here is my code.
private void connect(String ssid, Context context) {
Log.i(TAG, "try connect to! " + ssid);
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest nr = new NetworkRequest.Builder().addTransportType(NetworkCapabilities.TRANSPORT_WIFI).
removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED).
removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET
setNetworkSpecifier(ssid). //<--- here is the problem
build();
ConnectivityManager.NetworkCallback callback
= new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Log.i(TAG, "onAvailable " + network.toString() + " " + network.getClass().getName());
}
}
@Override
public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Log.i(TAG, "onCapabilitiesChanged " + networkCapabilities.getLinkDownstreamBandwidthKbps());
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Log.i(TAG, "onLinkPropertiesChanged " + linkProperties.getInterfaceName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
Log.i(TAG, "requestNetwork ");
// cm.requestNetwork(nr, callback);
cm.registerNetworkCallback(nr, callback);
}
}
I debugged the following code running on a Samsung S5 (SM-G900V), API 23 (6.0.1) in Android Studio.
void inspectNetworks() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ConnectivityManager connectivity = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
Network[] ns = connectivity.getAllNetworks();
for (Network n : ns) {
NetworkCapabilities c = connectivity.getNetworkCapabilities(n);
Log.i(TAG, "inspectNetworks: network="+n+" capabilities="+c); // <- breakpoint
}
}
}
I found that Wi-Fi networks didn't have any networkSpecifier
at all:
Maybe networkSpecifier
s for WIFI
-transport networks will be implemented in the future... For the record, I found that networkSpecifier
was set to 1
on this particular phone for both existing CELLULAR
-transport networks.
As for now, it seems like being as specific as possible with calls to addCapability
is the best option when requesting a Wi-Fi network.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With