ConnectivityManager getNetworkInfo (int) устарел


151

Используется compileSdkVersion 23 , но пытается поддерживать еще 9.

getNetworkInfo(int)осуждались в 23. Предлагалось использование getAllNetworks()и getNetworkInfo(Network)вместо этого. Однако оба они требуют минимум API 21.

Есть ли класс, который мы можем использовать в пакете поддержки, который может помочь в этом?

Я знаю, что решение было предложено раньше , однако проблема с моими минимальными требованиями к API, равными 9, создает проблему.


вы можете проверить версию сборки во время выполнения и использовать соответствующий метод
stinepike

1
Будет ли это по-прежнему выдавать устаревшее предупреждение?
kyleED

Пожалуйста, ознакомьтесь с моим классом ConnectivityObserver, который инкапсулирует методы API ниже и выше Android Nougat.
JJD

Ответы:


172

Ты можешь использовать:

getActiveNetworkInfo ();

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork != null) { 
    // connected to the internet
    if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
        // connected to wifi
    } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
        // connected to mobile data
    }
} else {
    // not connected to the internet
}

Или в случае выключателя

ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork != null) { 
    // connected to the internet
    switch (activeNetwork.getType()) {
        case ConnectivityManager.TYPE_WIFI:
            // connected to wifi
            break;
        case ConnectivityManager.TYPE_MOBILE:
            // connected to mobile data
            break;
        default:
            break;
    }
} else {
    // not connected to the internet
}

1
@ShirishHerwade - Да, широковещательный приемник в этом случае не нужен. getActiveNetworkInfo () может быть помещен в собственный метод при условии включения контекстной ссылки.
Cheese Bread

1
@TheIT - Да, в документе говорится: «Вы всегда должны проверять isConnected () перед инициированием сетевого трафика». Это решение не инициирует трафик, а только обеспечивает решение устаревшего вызова getNetworkInfo ().
Cheese Bread

9
Начиная с Android 9, SDK 28 устарел.
Збарча Кристиан

33
activeNetwork.getType()устарел и ConnectivityManager.TYPE_WIFIне рекомендуется
noobEinstien

7
Замена сейчасcm.getNetworkCapabilities(cm.activeNetwork).hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
tmm1

69

Обновление за февраль 2020 г .:

Принятый ответ снова устарел 28 (Android P), но его метод замены работает только 23 (Android M). Для поддержки старых устройств я написал вспомогательную функцию в.

Как использовать:

int type = getConnectionType(getApplicationContext());

Он возвращает int, вы можете изменить его enumв своем коде:

0: Интернет недоступен (возможно, в режиме полета или в процессе подключения к Wi-Fi).

1: Сотовая связь (мобильные данные, 3G / 4G / LTE, что угодно).

2: Wi-Fi.

3: VPN

Вы можете скопировать Kotlin или Java-версию вспомогательной функции.

Котлин:

@IntRange(from = 0, to = 3)
fun getConnectionType(context: Context): Int {
    var result = 0 // Returns connection type. 0: none; 1: mobile data; 2: wifi
    val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        cm?.run {
            cm.getNetworkCapabilities(cm.activeNetwork)?.run {
                if (hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                    result = 2
                } else if (hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                    result = 1
                } else if (hasTransport(NetworkCapabilities.TRANSPORT_VPN)){
                    result = 3
                }
            }
        }
    } else {
        cm?.run {
            cm.activeNetworkInfo?.run {
                if (type == ConnectivityManager.TYPE_WIFI) {
                    result = 2
                } else if (type == ConnectivityManager.TYPE_MOBILE) {
                    result = 1
                } else if(type == ConnectivityManager.TYPE_VPN) {
                    result = 3
                }
            }
        }
    }
    return result
}

Ява:

@IntRange(from = 0, to = 3)
public static int getConnectionType(Context context) {
    int result = 0; // Returns connection type. 0: none; 1: mobile data; 2: wifi
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (cm != null) {
            NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork());
            if (capabilities != null) {
                if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                    result = 2;
                } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                    result = 1;
                } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
                    result = 3;
                }
            }
        }
    } else {
        if (cm != null) {
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            if (activeNetwork != null) {
                // connected to the internet
                if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                    result = 2;
                } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                    result = 1;
                } else if (activeNetwork.getType() == ConnectivityManager.TYPE_VPN) {
                    result = 3;
                }
            }
        }
    }
    return result;
}

2
Поскольку у вас есть 2 возможных результата, лучше использовать логическое значение вместо того, чтобы возвращать целое число ...
Кристиан

3
@Christian Как объяснено в желтом разделе, эта вспомогательная функция возвращает 3 возможных состояния: No Internet, Cellularи Wi-Fi. Если вам не важен тип подключения, не стесняйтесь изменять код в соответствии с вашим приложением.
user1032613

1
как насчет комментария в приведенном выше решении «если вы подключены к Wi-Fi и к VPN, тогда ваше текущее состояние может быть TRANSPORT_VPN, поэтому вы можете также проверить его»?
Дэвид

1
@Lukas, вы должны быть осторожны, если вы используете Booleanкласс-оболочку вместо booleanпримитивного. В операторе if вам нужно будет добавить проверку для null. Также что, если завтра будет представлен еще один новый транспортный режим в NetworkCapabilities ... так что использование целого числа для ветвления поможет, а также вы можете перейти к случаям переключения.
Shadow Droid

3
Я устал от этого постоянного цикла осуждения
Сегун Вахаб

68

Что касается октября 2018 года, принятый ответ устарел.

getType(), и сами типы теперь устарели на уровне API 28. Из Javadoc:

Вызывающие должны переключиться на проверку NetworkCapabilities # hasTransport вместо одной из констант NetworkCapabilities # TRANSPORT *.

Чтобы использовать NetworkCapabilities, вам необходимо передать Networkэкземпляр getNetworkCapabilities()методу. Чтобы получить этот экземпляр, вам нужно вызвать, getActiveNetwork()который был добавлен в API Level 23.

Итак, я считаю, что на данный момент правильный способ безопасно проверить, подключены ли вы к Wi-Fi или сотовой сети:

public static boolean isNetworkConnected() {
    final ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

    if (cm != null) {
        if (Build.VERSION.SDK_INT < 23) {
            final NetworkInfo ni = cm.getActiveNetworkInfo();

            if (ni != null) {
                return (ni.isConnected() && (ni.getType() == ConnectivityManager.TYPE_WIFI || ni.getType() == ConnectivityManager.TYPE_MOBILE));
            }
        } else {
            final Network n = cm.getActiveNetwork();

            if (n != null) {
                final NetworkCapabilities nc = cm.getNetworkCapabilities(n);

                return (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) || nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI));
            }
        } 
    }

    return false; 
}

Вы также можете проверить наличие других типов TRANSPORT, которые вы можете найти здесь .

Важное примечание: если вы подключены к Wi-Fi и к VPN, ваше текущее состояние может быть TRANSPORT_VPNтаким, поэтому вы можете также проверить его.

Не забудьте добавить следующее разрешение к вашему файлу AndroidManifest:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Эквивалентен ли hasTransport (NetworkCapabilities.TRANSPORT_WIFI) ni.isConnected () && (ni.getType () == ConnnectivityManager.TYPE_WIFI)? Я имею в виду, что функция hasTransport () также проверяет, подключено ли устройство или пытается подключиться?
Biscuit

Опять же, NetworkInfoобесценивается, вы больше не можете использовать NetWorkInfo, так как это дает альтернативу?
Prescott Chartier,

@PrescottChartier, этот фрагмент кода обращается к NetworkInfo только на устройствах SDK <23
Том

16

Обновленный ответ (19: 07: 2018):

Этот метод поможет вам проверить, доступно ли подключение к Интернету.

public static boolean isNetworkAvailable(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

    if (connectivityManager != null) {
        NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
        return (activeNetwork != null && activeNetwork.isConnectedOrConnecting());
    } else {
        return false;
    }
}

Старый ответ:

Для лучшей практики повторного использования кода импровизируем ответ Cheese Bread.

public static boolean isNetworkAvailable(Context context) {
    int[] networkTypes = {ConnectivityManager.TYPE_MOBILE,
            ConnectivityManager.TYPE_WIFI};
    try {
        ConnectivityManager connectivityManager =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        for (int networkType : networkTypes) {
            NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
            if (activeNetworkInfo != null &&
                    activeNetworkInfo.getType() == networkType)
                return true;
        }
    } catch (Exception e) {
        return false;
    }
    return false;
}

Код можно поместить в класс Util и использовать для проверки, подключен ли телефон к Интернету через Wi-Fi или мобильный Интернет из любой части вашего приложения.


3
Я предлагаю вывести получение активной сети за пределы цикла for.
штолик

20
activeNetwork.isConnectedOrConnecting()устарела
MHSFisher

1
Я меняю activeNetwork.isConnectedOrConnecting () на activeNetwork.isConnected
Мурильо Комино

1
NetworkInfo устарела. Необходимо обновить еще раз!
SMBiggs

14

По состоянию на март 2020 года есть обновление для этого ответа, которое поддерживает API.15 через API.29, вы можете найти его после исходного ответа

Ответ февраль 2019

Чтобы проверить, онлайн ли вы:

boolean isOnline() {
    // Checking internet connectivity
    ConnectivityManager connectivityMgr = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = null;
    if (connectivityMgr != null) {
        activeNetwork = connectivityMgr.getActiveNetworkInfo();
    }
    return activeNetwork != null;
}

Чтобы получить тип подключения к Интернету до / после Android M

void internetType() {
    // Checking internet connectivity
    ConnectivityManager connectivityMgr = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = null;
    if (connectivityMgr != null) {
        activeNetwork = connectivityMgr.getActiveNetworkInfo();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            NetworkCapabilities nc = connectivityMgr.getNetworkCapabilities(connectivityMgr.getActiveNetwork());
            if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                // connected to mobile data
            } else if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                // connected to wifi
            }
        } else {
            if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                // connected to wifi
            } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                // connected to mobile data
            }
        }
    }
}

Во всех случаях требуется разрешение на доступ к состоянию сети

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Обновление март 2020 г.

Поскольку NetworkInfoон устарел, и теперь с API 29 мы должны использовать ConnectivityManager.NetworkCallbackего изменение состояния сети onAvailable()и onLost()обратные вызовы.

Применение:

  • Вы можете использовать эту библиотеку или напрямую использовать служебный класс ниже, который является частью этой библиотеки.

Характеристики

  • Это LifeCycle сознательно реализует, LifecycleObserverчтобы избежать утечки памяти, выполняя некоторую очистку в onDestroy()методе.
  • Он поддерживает от API 15 (Ice Cream Sandwich) до API 29 (Android Q)
  • Для API до API 21 он использует контекстно-зависимые BoradcastReceiverи NetworkInfo, а ConnectivityManager.NetworkCallbackдля API 21 и выше.
  • Когда включены и Wi-Fi, и сотовая сеть, прослушиватель подключения не прерывается, когда WiFi отключается при переходе к сотовой сети.
  • Когда сотовая сеть включена, прослушиватель подключения не будет прерываться, когда WiFi подключен и является активной сетью (поскольку это предпочтительная сеть).
  • Если вы собираетесь использовать библиотеку, то включать это разрешение не нужно android.permission.ACCESS_NETWORK_STATE; но вы должны включить его, если собираетесь использовать служебный класс.

Возможности

  • Получите текущий статус подключения (онлайн / офлайн).
  • Непрерывная проверка / прослушивание интернет-соединения и запуск обратного вызова, когда устройство переходит в офлайн или онлайн.
  • Узнайте тип активного подключения к Интернету (Wi-Fi или сотовая связь).
  • Получите тип всех доступных сетей (Wi-Fi или сотовая связь). >> Поддерживается только в API 21+
  • Получить количество всех доступных сетей >> Поддерживается только в API 21+
@RequiresApi(api = Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1)
public class ConnectionUtil implements LifecycleObserver {

    private static final String TAG = "LOG_TAG";
    private ConnectivityManager mConnectivityMgr;
    private Context mContext;
    private NetworkStateReceiver mNetworkStateReceiver;

    /*
     * boolean indicates if my device is connected to the internet or not
     * */
    private boolean mIsConnected = false;
    private ConnectionMonitor mConnectionMonitor;


    /**
     * Indicates there is no available network.
     */
    private static final int NO_NETWORK_AVAILABLE = -1;


    /**
     * Indicates this network uses a Cellular transport.
     */
    public static final int TRANSPORT_CELLULAR = 0;


    /**
     * Indicates this network uses a Wi-Fi transport.
     */
    public static final int TRANSPORT_WIFI = 1;


    public interface ConnectionStateListener {
        void onAvailable(boolean isAvailable);
    }


    public ConnectionUtil(Context context) {
        mContext = context;
        mConnectivityMgr = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        ((AppCompatActivity) mContext).getLifecycle().addObserver(this);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mConnectionMonitor = new ConnectionMonitor();
            NetworkRequest networkRequest = new NetworkRequest.Builder()
                    .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
                    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                    .build();
            mConnectivityMgr.registerNetworkCallback(networkRequest, mConnectionMonitor);
        }

    }


    /**
     * Returns true if connected to the internet, and false otherwise
     *
     * <p>
     * NetworkInfo is deprecated in API 29
     * https://developer.android.com/reference/android/net/NetworkInfo
     * <p>
     * getActiveNetworkInfo() is deprecated in API 29
     * https://developer.android.com/reference/android/net/ConnectivityManager#getActiveNetworkInfo()
     * <p>
     * getNetworkInfo(int) is deprecated as of API 23
     * https://developer.android.com/reference/android/net/ConnectivityManager#getNetworkInfo(int)
     */
    public boolean isOnline() {

        mIsConnected = false;

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
            // Checking internet connectivity
            NetworkInfo activeNetwork = null;
            if (mConnectivityMgr != null) {
                activeNetwork = mConnectivityMgr.getActiveNetworkInfo(); // Deprecated in API 29
            }
            mIsConnected = activeNetwork != null;

        } else {
            Network[] allNetworks = mConnectivityMgr.getAllNetworks(); // added in API 21 (Lollipop)

            for (Network network : allNetworks) {
                NetworkCapabilities networkCapabilities = mConnectivityMgr.getNetworkCapabilities(network);
                if (networkCapabilities != null) {
                    if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
                            || networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
                            || networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET))
                        mIsConnected = true;
                }
            }
        }

        return mIsConnected;

    }


    /**
     * Returns
     * <p> <p>
     * <p><p> NO_NETWORK_AVAILABLE >>> when you're offline
     * <p><p> TRANSPORT_CELLULAR >> When Cellular is the active network
     * <p><p> TRANSPORT_WIFI >> When Wi-Fi is the Active network
     * <p>
     */
    public int getActiveNetwork() {

        NetworkInfo activeNetwork = mConnectivityMgr.getActiveNetworkInfo(); // Deprecated in API 29
        if (activeNetwork != null)

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                NetworkCapabilities capabilities = mConnectivityMgr.getNetworkCapabilities(mConnectivityMgr.getActiveNetwork());
                if (capabilities != null)
                    if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                        // connected to mobile data
                        return TRANSPORT_CELLULAR;

                    } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                        // connected to wifi
                        return TRANSPORT_WIFI;
                    }

            } else {
                if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) { // Deprecated in API 28
                    // connected to mobile data
                    return TRANSPORT_CELLULAR;

                } else if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) { // Deprecated in API 28
                    // connected to wifi
                    return TRANSPORT_WIFI;
                }
            }
        return NO_NETWORK_AVAILABLE;
    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public int getAvailableNetworksCount() {

        int count = 0;

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            Network[] allNetworks = mConnectivityMgr.getAllNetworks(); // added in API 21 (Lollipop)
            for (Network network : allNetworks) {
                NetworkCapabilities networkCapabilities = mConnectivityMgr.getNetworkCapabilities(network);
                if (networkCapabilities != null)
                    if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
                            || networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
                        count++;
            }

        }

        return count;
    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public List<Integer> getAvailableNetworks() {

        List<Integer> activeNetworks = new ArrayList<>();

        Network[] allNetworks; // added in API 21 (Lollipop)
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            allNetworks = mConnectivityMgr.getAllNetworks();
            for (Network network : allNetworks) {
                NetworkCapabilities networkCapabilities = mConnectivityMgr.getNetworkCapabilities(network);
                if (networkCapabilities != null) {
                    if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
                        activeNetworks.add(TRANSPORT_WIFI);

                    if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
                        activeNetworks.add(TRANSPORT_CELLULAR);

                }
            }
        }

        return activeNetworks;
    }


    public void onInternetStateListener(ConnectionStateListener listener) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            mNetworkStateReceiver = new NetworkStateReceiver(listener);
            IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
            mContext.registerReceiver(mNetworkStateReceiver, intentFilter);

        } else {
            mConnectionMonitor.setOnConnectionStateListener(listener);
        }
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public void onDestroy() {
        Log.d(TAG, "onDestroy");
        ((AppCompatActivity) mContext).getLifecycle().removeObserver(this);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            if (mConnectionMonitor != null)
                mConnectivityMgr.unregisterNetworkCallback(mConnectionMonitor);
        } else {
            if (mNetworkStateReceiver != null)
                mContext.unregisterReceiver(mNetworkStateReceiver);
        }

    }


    public class NetworkStateReceiver extends BroadcastReceiver {

        ConnectionStateListener mListener;

        public NetworkStateReceiver(ConnectionStateListener listener) {
            mListener = listener;
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getExtras() != null) {

                NetworkInfo activeNetworkInfo = mConnectivityMgr.getActiveNetworkInfo(); // deprecated in API 29

                /*
                 * activeNetworkInfo.getState() deprecated in API 28
                 * NetworkInfo.State.CONNECTED deprecated in API 29
                 * */
                if (!mIsConnected && activeNetworkInfo != null && activeNetworkInfo.getState() == NetworkInfo.State.CONNECTED) {
                    Log.d(TAG, "onReceive: " + "Connected To: " + activeNetworkInfo.getTypeName());
                    mIsConnected = true;
                    mListener.onAvailable(true);

                } else if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, Boolean.FALSE)) {
                    if (!isOnline()) {
                        mListener.onAvailable(false);
                        mIsConnected = false;
                    }

                }

            }
        }
    }


    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public class ConnectionMonitor extends ConnectivityManager.NetworkCallback {

        private ConnectionStateListener mConnectionStateListener;

        void setOnConnectionStateListener(ConnectionStateListener connectionStateListener) {
            mConnectionStateListener = connectionStateListener;
        }

        @Override
        public void onAvailable(@NonNull Network network) {

            if (mIsConnected)
                return;

            Log.d(TAG, "onAvailable: ");

            if (mConnectionStateListener != null) {
                mConnectionStateListener.onAvailable(true);
                mIsConnected = true;
            }

        }

        @Override
        public void onLost(@NonNull Network network) {

            if (getAvailableNetworksCount() == 0) {
                mConnectionStateListener.onAvailable(false);
                mIsConnected = false;
            }

        }

    }

}

@Rasel, пожалуйста, проверьте обновленный ответ, надеюсь, это поможет
Zain

Если пользователь подключен к Wi-Fi и мобильным данным одновременно и теряет соединение, один из них onLostполучит вызов. onLostне означает, что устройство потеряло подключение к Интернету, но сеть потеряла соединение.
Гохан Арик,

@Gokhan Arik .. Хорошая уловка, я работаю над ее решением
Zain

1
Проверьте это обсуждение gist.github.com/PasanBhanu/730a32a9eeb180ec2950c172d54bb06a
Арик

@GokhanArik, спасибо за помощь .. Я только что обновил свой ответ и расширил использование API, пожалуйста, дайте мне знать, если вы заметите какие-либо ошибки
Zain

13

Принятый ответ устарел в версии 28, поэтому вот решение, которое я использую в своем проекте.

Возвращает тип подключения. false: нет подключения к Интернету; правда: мобильные данные || вай фай

public static boolean isNetworkConnected(Context context) { 
    boolean result = false; 
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (cm != null) {
            NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork());
            if (capabilities != null) {
                if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                    result = true;
                } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                    result = true;
                }
            }
        }
    } else {
        if (cm != null) {
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            if (activeNetwork != null) {
                // connected to the internet
                if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                    result = true;
                } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                    result = true;
                }
            }
        }
    }
    return result;
}

2
activeNetwork.getType () также устарел. Вы можете использовать activeNetwork.isConnected ();
Аман Верма

4

Хорошо бы проверить, подключена ли ваша сеть к Интернету:

@Suppress("DEPRECATION")
fun isNetworkAvailable(context: Context): Boolean {
    try {
        val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        return if (Build.VERSION.SDK_INT > 22) {
            val an = cm.activeNetwork ?: return false
            val capabilities = cm.getNetworkCapabilities(an) ?: return false
            capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
        } else {
            val a = cm.activeNetworkInfo ?: return false
            a.isConnected && (a.type == ConnectivityManager.TYPE_WIFI || a.type == ConnectivityManager.TYPE_MOBILE)
        }
    } catch (e: Exception) {
        e.printStackTrace()
    }
    return false
}

Вы также можете проверить NetworkCapabilities.NET_CAPABILITY_VALIDATED.
JJD

4

Многие ответы по-прежнему используют getNetworkType ниже 23, что является устаревшим; используйте приведенный ниже код, чтобы проверить, есть ли у устройства подключение к Интернету.

public static boolean isNetworkConnected(Context context) {

    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

    if (cm != null) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork());
            return capabilities != null && (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR));
        } else {
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            return activeNetwork != null && activeNetwork.isConnected();
        }
    }

    return false;
}

..

И не забудьте добавить эту строку в Manifest

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

3

Версия Котлина:

fun isInternetOn(context: Context): Boolean {
   val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as? ConnectivityManager
   val activeNetwork = cm?.activeNetworkInfo
   return activeNetwork != null && activeNetwork.isConnected
}

3

Как предложил Cheese Bread , используйте getActiveNetworkInfo ()

getActiveNetworkInfo

Добавлено в API уровня 1

NetworkInfo getActiveNetworkInfo ()

Возвращает сведения о текущей активной сети передачи данных по умолчанию. При подключении эта сеть является маршрутом по умолчанию для исходящих подключений. Вы всегда должны проверять isConnected () перед инициированием сетевого трафика. Это может вернуть null, если нет сети по умолчанию. Этот метод требует, чтобы вызывающий объект имел разрешение ACCESS_NETWORK_STATE. Возвращает NetworkInfo объект NetworkInfo для текущей сети по умолчанию или null, если сеть по умолчанию в настоящее время не активна.

Ссылка: Android Studio

 public final boolean isInternetOn() {

    // get Connectivity Manager object to check connection
    ConnectivityManager connec =
            (ConnectivityManager)getSystemService(getBaseContext().CONNECTIVITY_SERVICE);

    // Check for network connections
    if ( connec.getActiveNetworkInfo().getState() == android.net.NetworkInfo.State.CONNECTED ||
            connec.getActiveNetworkInfo().getState() == android.net.NetworkInfo.State.CONNECTING ) {

        // if connected with internet

        Toast.makeText(this, connec.getActiveNetworkInfo().getTypeName(), Toast.LENGTH_LONG).show();
        return true;

    } else if (
            connec.getActiveNetworkInfo().getState() == android.net.NetworkInfo.State.DISCONNECTED ||
                    connec.getActiveNetworkInfo().getState() == android.net.NetworkInfo.State.DISCONNECTED  ) {

        Toast.makeText(this, " Not Connected ", Toast.LENGTH_LONG).show();
        return false;
    }
    return false;
}

теперь вызовите метод, для безопасного использования попробуйте поймать

try {
    if (isInternetOn()) { /* connected actions */ }
    else { /* not connected actions */ }
} catch (Exception e){
  Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
}

И не забудьте добавить:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

спасибо, это полезно. когда мы проверяем статус сети, и если Wi-Fi и данные отключены - в этот раз происходит сбой приложения, но попробуйте решить проблему ..
Руча Бхатт Джоши

Однако это не сработает, если я хочу проверить, присутствует ли определенный тип сети, перечислить все существующие сети, то естьgetNetworkInfo(ConnectivityManager.TYPE_ETHERNET).isAvailable
m0skit0

3
getState () устарел!
Диего Венансио

Несколько устаревших инструкций!
SMBiggs

3

проверьте, доступен ли интернет

@RequiresPermission(allOf = [
    Manifest.permission.ACCESS_NETWORK_STATE, 
    Manifest.permission.INTERNET
])
fun isInternetAvailable(context: Context): Boolean {
    val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
    val activeNetworkInfo = connectivityManager!!.activeNetworkInfo
    return activeNetworkInfo != null && activeNetworkInfo.isConnected
}

3

Это может помочь кому-то Kotlin

fun isNetworkConnected(context: Context) : Boolean {
        val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val capabilities =  connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
        capabilities.also {
            if (it != null){
                if (it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI))
                    return true
                else if (it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)){
                    return true
                }
            }
        }
        return false
    }

Улучшите этот код и верните истинное значение интернета, чтобы получить либо Wi-Fi, либо пакет данных. Благодарность !!
Наджиб Ахмед Путхавала

2

Чтобы быть в безопасности, я бы посоветовал также использовать метод

NetworkInfo.isConnected ()

Весь метод может выглядеть следующим образом:

/**
 * Checking whether network is connected
 * @param context Context to get {@link ConnectivityManager}
 * @return true if Network is connected, else false
 */
public static boolean isConnected(Context context){
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    if (activeNetwork != null && activeNetwork.isConnected()) {
        int networkType = activeNetwork.getType();
        return networkType == ConnectivityManager.TYPE_WIFI || networkType == ConnectivityManager.TYPE_MOBILE;
    } else {
        return false;
    }
}

9
activeNetwork.getType()устарел и ConnectivityManager.TYPE_WIFI не рекомендуется
noobEinstien

2

Вот как я проверяю, использует ли текущая сеть сотовую связь или нет в последних версиях Android:

val isCellular: Boolean get() {
    val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        cm.getNetworkCapabilities(cm.activeNetwork).hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
    } else {
        cm.activeNetworkInfo?.type == ConnectivityManager.TYPE_MOBILE
    }
}

2

(Почти) Все ответы устарели в Android P, поэтому вот C#решение ( которое легко понять для разработчиков Java )

public bool IsOnline(Context context)
{
    var cm = (ConnectivityManager)context.GetSystemService(Context.ConnectivityService);

    if (cm == null) return false;

    if (Build.VERSION.SdkInt < BuildVersionCodes.M)
    {
        var ni = cm.ActiveNetworkInfo;

        if (ni == null) return false;

        return ni.IsConnected && (ni.Type == ConnectivityType.Wifi || ni.Type == ConnectivityType.Mobile);
    }

    return cm.GetNetworkCapabilities(cm.ActiveNetwork).HasTransport(Android.Net.TransportType.Wifi)
        || cm.GetNetworkCapabilities(cm.ActiveNetwork).HasTransport(Android.Net.TransportType.Cellular);
}   

Ключ здесь Android.Net.TransportType


Aaaannnndddd все в этом УСТАРЕЛО!
Прескотт Шартье,

@PrescottChartier в какой версии?
Мехди Дехгани,

2

Возможно, нам потребуется более одного раза проверить подключение к Интернету. Так что нам будет проще, если мы напишем блок кода в методе расширения Context. Ниже приведены мои вспомогательные расширения для Contextи Fragment.

Проверка подключения к Интернету

fun Context.hasInternet(): Boolean {
    val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    return if (Build.VERSION.SDK_INT < 23) {
        val activeNetworkInfo = connectivityManager.activeNetworkInfo
        activeNetworkInfo != null && activeNetworkInfo.isConnected
    } else {
        val nc = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
        if (nc == null) {
            false
        } else {
            nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                    nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
        }
    }
}

Другие расширения

fun Context.hasInternet(notifyNoInternet: Boolean = true, trueFunc: (internet: Boolean) -> Unit) {
    if (hasInternet()) {
        trueFunc(true)
    } else if (notifyNoInternet) {
        Toast.makeText(this, "No Internet Connection!", Toast.LENGTH_SHORT).show()
    }
}

fun Context.hasInternet(
    trueFunc: (internet: Boolean) -> Unit,
    falseFunc: (internet: Boolean) -> Unit
) {
    if (hasInternet()) {
        trueFunc(true)
    } else {
        falseFunc(true)
    }
}

fun Fragment.hasInternet(): Boolean = context!!.hasInternet()

fun Fragment.hasInternet(notifyNoInternet: Boolean = true, trueFunc: (internet: Boolean) -> Unit) =
    context!!.hasInternet(notifyNoInternet, trueFunc)

fun Fragment.hasInternet(
    trueFunc: (internet: Boolean) -> Unit, falseFunc: (internet: Boolean) -> Unit
) = context!!.hasInternet(trueFunc, falseFunc)

2

ConnectivityManager.getActiveNetwork () не найден в Android ниже M (API 28). networkInfo.getState () устарел выше Android L.

Итак, окончательный ответ:

public static boolean isConnectingToInternet(Context mContext) {
    if (mContext == null) return false;

    ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivityManager != null) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            final Network network = connectivityManager.getActiveNetwork();
            if (network != null) {
                final NetworkCapabilities nc = connectivityManager.getNetworkCapabilities(network);

                return (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
                        nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI));
            }
        } else {
            NetworkInfo[] networkInfos = connectivityManager.getAllNetworkInfo();
            for (NetworkInfo tempNetworkInfo : networkInfos) {
                if (tempNetworkInfo.isConnected()) {
                    return true;
                }
            }
        }
    }
    return false;
}

1
Вы говорите, что getActiveNetwork () не находится в Android ниже M, но ваш код использует его на Lollipop !?
3c71

1

Поскольку опубликованные ответы позволяют вам запрашивать только активную сеть, вот как получить NetworkInfoдля любой сети, а не только для активной (например, сети Wi-Fi) (извините, код Kotlin впереди)

(getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).run {
    allNetworks.find { getNetworkInfo(it).type == ConnectivityManager.TYPE_WIFI }?.let { network -> getNetworkInfo(network) }
//    getNetworkInfo(ConnectivityManager.TYPE_WIFI).isAvailable // This is the deprecated API pre-21
}

Для этого требуется API 21 или выше и разрешение android.permission.ACCESS_NETWORK_STATE


1
currentNetwork.getType () и ConnectivityManager.TYPE_WIFI устарели в API 28.
Абушавиш,

@Abushawish Какое решение рекомендуется для API 28?
tmm1

Замена сейчасcm.getNetworkCapabilities(cm.activeNetwork).hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
tmm1

1

NetManager , который можно использовать для проверки интернет-соединения на Android с помощью Kotlin

Если вы используете minSdkVersion> = 23

class NetManager @Inject constructor(var applicationContext: Context) {
    val isConnectedToInternet: Boolean?
        get() = with(
            applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE)
                    as ConnectivityManager
        ) {
            isConnectedToInternet()
        }
}

fun ConnectivityManager.isConnectedToInternet() = isConnected(getNetworkCapabilities(activeNetwork))

fun isConnected(networkCapabilities: NetworkCapabilities?): Boolean {
    return when (networkCapabilities) {
        null -> false
        else -> with(networkCapabilities) { hasTransport(TRANSPORT_CELLULAR) || hasTransport(TRANSPORT_WIFI) }
    }
}

Если вы используете minSdkVersion <23

class NetManager @Inject constructor(var applicationContext: Context) {
    val isConnectedToInternet: Boolean?
        get() = with(
            applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE)
                    as ConnectivityManager
        ) {
            isConnectedToInternet()
        }
}

fun ConnectivityManager.isConnectedToInternet(): Boolean = if (Build.VERSION.SDK_INT < 23) {
    isConnected(activeNetworkInfo)
} else {
    isConnected(getNetworkCapabilities(activeNetwork))
}


fun isConnected(network: NetworkInfo?): Boolean {
    return when (network) {
        null -> false
        else -> with(network) { isConnected && (type == TYPE_WIFI || type == TYPE_MOBILE) }
    }
}

fun isConnected(networkCapabilities: NetworkCapabilities?): Boolean {
    return when (networkCapabilities) {
        null -> false
        else -> with(networkCapabilities) { hasTransport(TRANSPORT_CELLULAR) || hasTransport(TRANSPORT_WIFI) }
    }
}

1

https://www.agnosticdev.com/content/how-detect-network-connectivity-android

пожалуйста, следуйте этому руководству, оно должно помочь всем, кто ищет ответы.

обратите внимание, что networkInfo устарела, поэтому замените его isNetworkReacheable () на ответ @vidha ниже, передав getApplicationContext () в качестве параметра

  public static boolean isNetworkReacheable(Context context) {
    boolean result = false;
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (cm != null) {
            NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork());
            if (capabilities != null) {
                if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                    result = true;
                } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                    result = true;
                }
            }
        }
    } else {
        if (cm != null) {
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            if (activeNetwork != null) {
                // connected to the internet
                if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
                    result = true;
                } else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
                    result = true;
                }
            }
        }
    }
    return result;
}

1

Это будет работать и в Android 10. Он вернет true, если подключен к Интернету, иначе вернет false.

private fun isOnline(): Boolean {
        val connectivityManager =
                getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        val capabilities =
                connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
        if (capabilities != null) {
            when {
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> {
                    Log.i("Internet", "NetworkCapabilities.TRANSPORT_CELLULAR")
                    return true
                }
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
                    Log.i("Internet", "NetworkCapabilities.TRANSPORT_WIFI")
                    return true
                }
                capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> {
                    Log.i("Internet", "NetworkCapabilities.TRANSPORT_ETHERNET")
                    return true
                }
            }
        }
        return false
    }

0
public boolean isConnectedToWifi(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivityManager == null) {
        return false;
    }

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        Network network = connectivityManager.getActiveNetwork();
        NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
        if (capabilities == null) {
            return false;
        }
        return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
    } else {
        NetworkInfo networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
        if (networkInfo == null) {
            return false;
        }
        return networkInfo.isConnected();
    }
}

0

У меня это работает в Котлине. Многие API устарели в классе Network Manager, поэтому ниже ответ охватывает всю поддержку API.

fun isNetworkAvailable(context: Context): Boolean {
    var result = false
    (context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).apply {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                result = isCapableNetwork(this,this.activeNetwork)
            } else {
                val networkInfos = this.allNetworks
                for (tempNetworkInfo in networkInfos) {
                    if(isCapableNetwork(this,tempNetworkInfo))
                        result =  true
                }
            }
        }

    return result
}

fun isCapableNetwork(cm: ConnectivityManager,network: Network?): Boolean{
     cm.getNetworkCapabilities(network)?.also {
        if (it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
            return true
        } else if (it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
            return true
        }
    }
    return false
}

Вы также добавите ниже

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

0

Приведенный ниже код работает со всеми API. (Котлин)

Однако getActiveNetworkInfo () устарела только в API 29 и работает со всеми API, поэтому мы можем использовать его во всех Api ниже 29.

fun isInternetAvailable(context: Context): Boolean {
            var result = false
            val connectivityManager =
                context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                val networkCapabilities = connectivityManager.activeNetwork ?: return false
                val actNw =
                    connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
                result = when {
                    actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                    actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                    actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
                    else -> false
                }
            } else {
                connectivityManager.run {
                    connectivityManager.activeNetworkInfo?.run {
                        result = when (type) {
                            ConnectivityManager.TYPE_WIFI -> true
                            ConnectivityManager.TYPE_MOBILE -> true
                            ConnectivityManager.TYPE_ETHERNET -> true
                            else -> false
                        }

                    }
                }
            }

            return result
        }

0

Что-то вроде этого:

public boolean hasConnection(final Context context){
    ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNW = cm.getActiveNetworkInfo();
    if (activeNW != null && activeNW.isConnected())
    {
        return true;
    }
    return false;
}

И в основном теле программы:

if(hasConnection(this)) {
    Toast.makeText(this, "Active networks OK ", Toast.LENGTH_LONG).show();
    getAccountData(token, tel);
}
else  Toast.makeText(this, "No active networks... ", Toast.LENGTH_LONG).show();

0

проверка статуса сети с помощью target sdk 29 :

 @IntRange(from = 0, to = 3)
fun getConnectionType(context: Context): Int {
    var result = 0 // Returns connection type. 0: none; 1: mobile data; 2: wifi
    val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

        val capabilities =
            cm.getNetworkCapabilities(cm.activeNetwork)
        if (capabilities != null) {
            if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                result = 2
            } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                result = 1
            } else if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
                result = 3
            }

        }
    } else {

        val activeNetwork = cm.activeNetworkInfo
        if (activeNetwork != null) {
            // connected to the internet
            if (activeNetwork.type === ConnectivityManager.TYPE_WIFI) {
                result = 2
            } else if (activeNetwork.type === ConnectivityManager.TYPE_MOBILE) {
                result = 1
            } else if (activeNetwork.type === ConnectivityManager.TYPE_VPN) {
                result = 3
            }
        }
    }
    return result
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.