Search code examples
javaandroidwifideprecated

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.


Solution

  • 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
    }