15

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);
    }
}
Community
  • 1
  • 1
bluevoid
  • 1,274
  • 13
  • 29

2 Answers2

5

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:

in Android Studio Debug view, mNetworkSpecifier = null

Maybe networkSpecifiers 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.

EricRobertBrewer
  • 1,750
  • 1
  • 22
  • 25
-1

First up cheating is always an option and just requiring people to change their settings in the phone in order to work with the network. The cheat goes like this. Wifi->Advanced->Unchecked.

However, I'm sure that is not the answer you are looking for. So I did a little research for you and found what was needed. You need to call a command ignoreNetwork(). To learn more about this command it is under ACTION_CAPTIVE_PORTAL_SIGN_IN on the following source link.

source: http://developer.android.com/reference/android/net/ConnectivityManager.html#ACTION_CAPTIVE_PORTAL_SIGN_IN

http://developer.android.com/reference/android/net/CaptivePortal.html#ignoreNetwork()

kayleighsdaddy
  • 670
  • 5
  • 15