Sabrina N
Sabrina N

Reputation: 150

NetworkInfo and WifiConfiguration has been deprecated in SDK 22

I'm using android lollipop in PAX A920 device (SDK Version 22). I get a warning message like this when build:

NetworkInfo in android.net has been deprecated

WifiConfiguration in android.net has been deprecated

I'm confused because I saw an example of sdk 22 in C:\Users\{YOUR_ACCOUNT}\AppData\Local\Android\Sdk\sources\android-22\com\android\connectivitymanagertestto access wifi using that method, but why does it appear deprecated?

What method is the same to replace the deprecated methods?

public boolean isWifiConnected() {
    boolean isWifiConnected = false;
    try {
        NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        if (networkInfo != null) {
            isWifiConnected = networkInfo.getState() == CONNECTED;
        }
        Log.i(TAG, "wifi adapter is connected? " + isWifiConnected);
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return isWifiConnected;
}

public void removeNetwork() {
    List<WifiConfiguration> wifiCfgList = wifiManager.getConfiguredNetworks();
    if (wifiCfgList.size() > 0) {
        for (WifiConfiguration item : wifiCfgList) {
            if (item != null) {
                wifiManager.removeNetwork(item.networkId);
                wifiManager.saveConfiguration();
            }
        }
    }
}

Thanks for point out.

Upvotes: 1

Views: 3398

Answers (1)

Jenea Vranceanu
Jenea Vranceanu

Reputation: 4694

Deprecated classes were repaced with ConnectivityManager system service and NetworkCallbacks: https://developer.android.com/training/monitoring-device-state/connectivity-status-type

Even though the official code example shows how to get NetworkInfo from ConnectivityManager there is a highlighted note:

enter image description here

Here is a sample code of how you could get the current network state and also receive updates as time goes by. This is a partially stripped-down solution that I would use in production. If you connect it with RxJava or RxKotlin you could create an observable that will hold network state and that will be updated when overridden method of NetworkCallback get called.

Note regarding Java: public class-level variables are made public just for brevity. I'd instead create a few getters for these to access the value behind these variables.

Feel free to ask questions.

Java

class NetworkReachabilityService {

    public NetworkType networkType;
    public NetworkState networkState = NetworkState.Unavailable;
    private ConnectivityManager connectivityManager;
    private ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
        @Override
        public void onAvailable(@NonNull Network network) {
            super.onAvailable(network);
            updateAvailability(connectivityManager.getNetworkCapabilities(network));
        }

        @Override
        public void onLosing(@NonNull Network network, int maxMsToLive) {
            super.onLosing(network, maxMsToLive);
            networkState = NetworkState.Losing;
        }

        @Override
        public void onLost(@NonNull Network network) {
            super.onLost(network);
            networkState = NetworkState.Lost;
        }

        @Override
        public void onUnavailable() {
            super.onUnavailable();
            networkState = NetworkState.Unavailable;
        }

        @Override
        public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
            super.onCapabilitiesChanged(network, networkCapabilities);
            updateAvailability(networkCapabilities);
        }
    };

    public NetworkReachabilityService(Context context) {
        connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    }

    private void updateAvailability(NetworkCapabilities networkCapabilities) {
        if (networkCapabilities == null) {
            networkState = NetworkState.Unavailable;
            return;
        }

        if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
            networkType = NetworkType.CELL;
        } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
            networkType = NetworkType.WiFi;
        }

        networkState = NetworkState.Available;
    }

    public void resumeListeningNetworkChanges() {
        pauseListeningNetworkChanges();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            connectivityManager.registerDefaultNetworkCallback(networkCallback);
        } else {
            connectivityManager.registerNetworkCallback(
                    new NetworkRequest.Builder().build(),
                    networkCallback
            );
        }
    }

    public void pauseListeningNetworkChanges() {
        try {
            connectivityManager.unregisterNetworkCallback(networkCallback);
        } catch (IllegalArgumentException exception) {
            // Usually happens only once if: "NetworkCallback was not registered"
        }
    }

    private enum NetworkState {
        Available, Unavailable, Connecting, Losing, Lost
    }

    private enum NetworkType {
        WiFi, CELL, OTHER
    }
}

Kotlin

sealed class NetworkState {
    data class Available(val type: NetworkType) : NetworkState()
    object Unavailable : NetworkState()
    object Connecting : NetworkState()
    object Losing : NetworkState()
    object Lost : NetworkState()
}

sealed class NetworkType {
    object WiFi : NetworkType()
    object CELL : NetworkType()
    object OTHER : NetworkType()
}

class NetworkReachabilityService private constructor(context: Context) {
    
    private val connectivityManager: ConnectivityManager =
        context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    private val networkCallback = object : ConnectivityManager.NetworkCallback() {
        // There are more functions to override!

        override fun onLost(network: Network) {
            super.onLost(network)
            networkState = NetworkState.Lost
        }

        override fun onUnavailable() {
            super.onUnavailable()
            networkState = NetworkState.Unavailable
        }

        override fun onLosing(network: Network, maxMsToLive: Int) {
            super.onLosing(network, maxMsToLive)
            networkState = NetworkState.Losing
        }

        override fun onAvailable(network: Network) {
            super.onAvailable(network)
            updateAvailability(connectivityManager.getNetworkCapabilities(network))
        }

        override fun onCapabilitiesChanged(
            network: Network,
            networkCapabilities: NetworkCapabilities
        ) {
            super.onCapabilitiesChanged(network, networkCapabilities)
            updateAvailability(networkCapabilities)
        }
    }
    
    var networkState: NetworkState = NetworkState.Unavailable
        private set

    private fun updateAvailability(networkCapabilities: NetworkCapabilities?) {
        if (networkCapabilities == null) {
            networkState = NetworkState.Unavailable
            return
        }
        var networkType: NetworkType = NetworkType.OTHER

        if (networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
            networkType = NetworkType.CELL
        }
        if (networkCapabilities.hasTransport(TRANSPORT_WIFI)) {
            networkType = NetworkType.WiFi
        }

        networkState = NetworkState.Available(networkType)
    }

    fun pauseListeningNetworkChanges() {
        try {
            connectivityManager.unregisterNetworkCallback(networkCallback)
        } catch (e: IllegalArgumentException) {
            // Usually happens only once if: "NetworkCallback was not registered"
        }
    }

    fun resumeListeningNetworkChanges() {
        pauseListeningNetworkChanges()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            connectivityManager.registerDefaultNetworkCallback(networkCallback)
        } else {
            connectivityManager.registerNetworkCallback(
                NetworkRequest.Builder().build(),
                networkCallback
            )
        }
    }
}

To start receiving network state updates call resumeListeningNetworkChanges and to stop pauseListeningNetworkChanges respectively.

Update: how to switch between deprecated and new API

Note that even when you use this solution you will anyway have a message that the certain code you use is deprecated! It is completely fine and is not considered as an error as long as you provide an implementation that can switch between new API and old, deprecated API.

Here is an approximate solution. Since the new classes were added in API level 29 we must use Build.VERSION_CODES.Q because it is an integer with the value 29.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {         
   // Use new API here
} else {
   // Use old API here
}

Upvotes: 2

Related Questions