Android 기기가 인터넷에 연결되어 있는지 감지


138

장치가 인터넷에 연결되어 있는지 확인해야합니다. 나는 다음과 같은 많은 답변을 발견했다.

private boolean isNetworkAvailable() {
    ConnectivityManager connectivityManager 
         = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null;
}

(에서 촬영 안드로이드에서 사용할 수있는 인터넷 연결이 있는지 여부를 감지합니다 .)

그러나 인터넷에 액세스 할 수없는 무선 네트워크에 연결된 경우이 방법이 맞지 않습니다 ...이 방법은 true를 반환합니다 ... 장치가 인터넷에 연결되어 있고 연결되어 있지 않은지 알 수있는 방법이 있습니까 무엇인가?


[this] [1]도 함께 갈 수 있습니다. 도움이 될 것입니다! [1] : stackoverflow.com/questions/4238921/…
akshay


isNetworkConnected기능 블록은 모든 사용되지 않는 코드가 포함되어 있습니다 Build.VERSION.SDK_INT >= Build.VERSION_CODES.M. 문제 및 해결 방법에 대한 자세한 내용은 stackoverflow.com/questions/53532406/…
Basti Vagabond

답변:


182

네 말이 맞아 제공 한 코드는 네트워크 연결이 있는지 확인합니다. 인터넷에 연결되어 있는지 확인하는 가장 좋은 방법은 http를 통해 알려진 서버에 연결을 시도하는 것입니다.

public static boolean hasActiveInternetConnection(Context context) {
    if (isNetworkAvailable(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) (new URL("http://www.google.com").openConnection());
            urlc.setRequestProperty("User-Agent", "Test");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500); 
            urlc.connect();
            return (urlc.getResponseCode() == 200);
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error checking internet connection", e);
        }
    } else {
        Log.d(LOG_TAG, "No network available!");
    }
    return false;
}

물론 http://www.google.com연결하려는 다른 서버 나 가동 시간이 좋은 서버로 대체 할 수 있습니다 .

Tony Cho도 아래 주석 에서 지적했듯이 메인 스레드 에서이 코드를 실행하지 않아야합니다. 그렇지 않으면 NetworkOnMainThread 예외가 발생합니다 (Android 3.0 이상). 대신 AsyncTask 또는 Runnable을 사용하십시오.

google.com을 사용하려면 Jeshurun의 수정 사항을 확인해야합니다. 에 그의 대답 그는 내 코드를 수정하고 좀 더 효율적인했다. 에 연결하면

HttpURLConnection urlc = (HttpURLConnection) 
            (new URL("http://clients3.google.com/generate_204")
            .openConnection());

그런 다음 204에 대한 응답 코드를 확인하십시오.

return (urlc.getResponseCode() == 204 && urlc.getContentLength() == 0);

그런 다음 전체 Google 홈페이지를 먼저 가져올 필요가 없습니다.


9
@varunbhardwaj는 다른 웹 사이트 (예 : 중국에 앱을 배포 할 때 baidu.com )를 가져 오거나 첫 번째 사이트가 연결이 없는지 확인하지 못하면 두 번째 사이트를 시도 할 수 있습니다.
THelper

2
나는 당신의 대답을 +1하고 내 앱에서 그것을 사용하는 것을 알고 있지만, 일부 웹 사이트에 의존성이 큰 경우가 있으며 내 질문은 여전히 ​​답이 남아 있습니다. 어쨌든 훌륭한 해결 방법 고맙습니다.
varun bhardwaj

2
@blackcrow 귀하 / 사용자가 기꺼이 기다리는 시간에 따라 다릅니다. 개인적으로 나는 1000ms가 하한, 평균 약 6000ms, 길이 15000ms라고 생각합니다. 그러나 검사가 백그라운드에서 실행 중이고 사용자가 기다리고 있지 않으면 훨씬 더 긴 시간 초과를 사용할 수 있습니다.
THelper

1
@varunbhardwaj 웹 서비스에서 적을 수있는 URI가 있어야합니다. 앱을 시작할 때 가장 먼저 요청하는 것은 다양한 구성 정보가 포함 된 부트 스트랩 파일이며, 서버 측에서 다양한 매개 변수를 변경할 수 있습니다. 그런 것을 사용할 수 있습니다.
Steve

11
백그라운드 스레드에서도 다운되어야합니다 (확인에 ConnectivityManager필요하지는 않음). 그렇지 않으면 Android 4.x + 기기에서 NetworkOnMainThread예외 가 발생합니다.
Anthony Chuinard

90

연결된 WiFi 네트워크에 인터넷 액세스가 있는지 확인하기 위해 Android에서 이미 사용하는 알려진 핵을 사용하도록 THelper의 답변을 약간 수정했습니다. 이것은 전체 Google 홈페이지를 잡는 것보다 훨씬 효율적입니다. 자세한 내용은 여기여기 를 참조 하십시오 .

public static boolean hasInternetAccess(Context context) {
    if (isNetworkAvailable(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) 
                (new URL("http://clients3.google.com/generate_204")
                .openConnection());
            urlc.setRequestProperty("User-Agent", "Android");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500); 
            urlc.connect();
            return (urlc.getResponseCode() == 204 &&
                        urlc.getContentLength() == 0);
        } catch (IOException e) {
            Log.e(TAG, "Error checking internet connection", e);
        }
    } else {
        Log.d(TAG, "No network available!");
    }
    return false;
}

1
안녕하세요, 현재 앱에서이 방법을 사용해도 괜찮습니까?
Slava Fomin II

현재 앱에서 구현하는 것이 효율적입니까?
therealprashant

5
위 답변의 방법보다 훨씬 효율적입니다. Google 홈페이지를 잡는 것은 특히 비효율적입니다.
Jeshurun

1
정답으로 확인 된 답변은 답변이 향상되므로 업데이트해야합니다. 잘 했어요, 고마워요
Hugo

3
당신은 사용 할 수 있습니다 g.cn/generate_204 대신 clients3.google.com/generate_204 뿐만 아니라 당신이 중국에서 연결을 테스트하려면
브리즈

18
public boolean isInternetWorking() {
    boolean success = false;
    try {
        URL url = new URL("https://google.com");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setConnectTimeout(10000);
        connection.connect();
        success = connection.getResponseCode() == 200;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return success;
}

인터넷을 실제로 사용할 수 있으면 true를 반환

이 두 가지 권한이 있는지 확인하십시오

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

http가 새로운 안드로이드 보안으로 인해 작동하지 않으면 이제 일반 텍스트 통신을 허용하지 않습니다. 지금은 그냥지나 치면됩니다.

android : usesCleartextTraffic = "true"


이것은 가장 완전하고 완전한 답변입니다 : 그것은 핑을 수행하는 가장 짧은 방법입니다 (ping은 전체 웹 사이트에 액세스하지 못함), 어떤 연결을 가지고 있든 독립적으로 실행되며 프로세스에서 실행되므로 안드로이드 버전과 잘 어울립니다. .
MacD

원하는게 뭐야 ? 여기 내가 현재 프로젝트 checkInternet
Bilal Shahid

그가 의미하는 것은이 호출이 UI를 차단하고 스레드 에서이 호출을해야합니까 ??
Amit Hooda

2
이것은 나를 위해 작동하지 않습니다 ... 원인 : android.os.NetworkOnMainThreadException android.os.StrictMode $ AndroidBlockGuardPolicy.onNetwork (StrictMode.java:1273) java.net.InetAddress.lookupHostByName (InetAddress.java:431) 에
Maryadi Poipo

@HyosokaPoipo 당신은 메인 스레드에서 이것을 호출해서는 안됩니다. 별도의 스레드 또는 AsyncTask를 사용하십시오.
Pramesh Bajracharya

14

Lollipop 이상을 대상으로하는 경우 새로운 NetworkCapabilities 클래스를 사용할 수 있습니다.

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

    final Network network = connectivityManager.getActiveNetwork();
    final NetworkCapabilities capabilities = connectivityManager
            .getNetworkCapabilities(network);

    return capabilities != null
            && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
}

1
connectivityManager.getActiveNetwork();Lollipop이 아닌 Marshmallow 인 API lvl23이 필요합니다.
Saenic

capability.hasCapability (NetworkCapabilities.NET_CAPABILITY_INTERNET)도 확인해야합니까?
Alex

Alex capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)는 나를 위해 속임수를 쓰는 것처럼 보였다!
rstojano

6

반드시 전체 HTTP 연결을 만들 필요는 없습니다. 알려진 호스트에 대한 TCP 연결을 열려고 시도하면 인터넷에 연결되어있는 것입니다.

public boolean hostAvailable(String host, int port) {
  try (Socket socket = new Socket()) {
    socket.connect(new InetSocketAddress(host, port), 2000);
    return true;
  } catch (IOException e) {
    // Either we have a timeout or unreachable host or failed DNS lookup
    System.out.println(e);
    return false;
  }
}

그런 다음 확인하십시오.

boolean online = hostAvailable("www.google.com", 80);

포트 80은 사용하기에 안전한 포트입니까?
ralphgabb

HTTP 서버를 호스팅하는 한 포트 80에서 TCP 연결을 수락해야합니다.
Xiv

예를 들어 AsyncTask 내부에서 사용하거나 MainActivity의 onCreate 메소드에서 호출해야합니까?
AlexioVay

@ 네트워크와 관련된 것은 메인 / UI 스레드에서 실행해서는 안됩니다. 따라서, 이것은AsyncTask
winklerrr

6

허용 된 답변을 기반으로 리스너 로이 클래스를 작성하여 기본 스레드에서 사용할 수 있습니다.

First : 백그라운드에서 인터넷 연결을 확인한 InterntCheck 클래스는 결과와 함께 리스너 메소드를 호출합니다.

public class InternetCheck extends AsyncTask<Void, Void, Void> {


    private Activity activity;
    private InternetCheckListener listener;

    public InternetCheck(Activity x){

        activity= x;

    }

    @Override
    protected Void doInBackground(Void... params) {


        boolean b = hasInternetAccess();
        listener.onComplete(b);

        return null;
    }


    public void isInternetConnectionAvailable(InternetCheckListener x){
        listener=x;
        execute();
    }

    private boolean isNetworkAvailable() {
        ConnectivityManager connectivityManager = (ConnectivityManager) activity.getSystemService(CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null;
    }
    private boolean hasInternetAccess() {
        if (isNetworkAvailable()) {
            try {
                HttpURLConnection urlc = (HttpURLConnection) (new URL("http://clients3.google.com/generate_204").openConnection());
                urlc.setRequestProperty("User-Agent", "Android");
                urlc.setRequestProperty("Connection", "close");
                urlc.setConnectTimeout(1500);
                urlc.connect();
                return (urlc.getResponseCode() == 204 &&
                        urlc.getContentLength() == 0);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            Log.d("TAG", "No network available!");
        }
        return false;
    }

    public interface InternetCheckListener{
        void onComplete(boolean connected);
    }

}

둘째 : 메인 스레드에서 클래스의 인스턴스를 인스턴스화하고 응답을 기다립니다 (Android 용 Firebase API로 작업 한 경우 익숙해야합니다!).

new InternetCheck(activity).isInternetConnectionAvailable(new InternetCheck.InternetCheckListener() {

        @Override
        public void onComplete(boolean connected) {
           //proceed!
        }
    });

이제 onComplete 메소드 내부에서 장치가 인터넷에 연결되어 있는지 여부를 알 수 있습니다.


3

이거 한번 해봐

public class ConnectionDetector {
    private Context _context;

    public ConnectionDetector(Context context) {
        this._context = context;
    }

    public boolean isConnectingToInternet() {
        if (networkConnectivity()) {
            try {
                HttpURLConnection urlc = (HttpURLConnection) (new URL(
                        "http://www.google.com").openConnection());
                urlc.setRequestProperty("User-Agent", "Test");
                urlc.setRequestProperty("Connection", "close");
                urlc.setConnectTimeout(3000);
                urlc.setReadTimeout(4000);
                urlc.connect();
                // networkcode2 = urlc.getResponseCode();
                return (urlc.getResponseCode() == 200);
            } catch (IOException e) {
                return (false);
            }
        } else
            return false;

    }

    private boolean networkConnectivity() {
        ConnectivityManager cm = (ConnectivityManager) _context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = cm.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            return true;
        }
        return false;
    }
}

매니페스트 파일에 다음 권한을 추가해야합니다.

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

그런 다음 전화하십시오.

if((new ConnectionDetector(MyService.this)).isConnectingToInternet()){
    Log.d("internet status","Internet Access");
}else{
    Log.d("internet status","no Internet Access");
}

이 게시물을 확인하십시오 stackoverflow.com/questions/36233507/…
Milan Gajera

이 게이는 캐치 사용을 시도하므로 오류가 표시되지 않습니다. 먼저 인터넷 권한을 추가 한 다음 시도하십시오. 잘 작동
Attaullah

활동에서이 메소드를 어떻게 호출했는지 알려 드리겠습니다.
Milan Gajera

내가 당신을 게시하려고하고 난 내 블로그에 오류를 게시했습니다 오류가 발생했습니다
밀라노 Gajera


1

ConnectivityManagerAndroid 용 API를 사용하여이 작업을 수행 할 수 있습니다 . 인터넷에 연결되어 있는지 여부 및 연결된 인터넷 연결 유형을 확인할 수 있습니다. 기본적으로 미터 식 또는 미터식이 아닙니다.

인터넷 연결을 확인합니다.

ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();

설명서 링크 : https://developer.android.com/training/monitoring-device-state/connectivity-status-type


모바일 데이터가 부족한지 어떻게 확인합니까? 모바일 데이터가 연결되어 있고 계정에 데이터 잔액이 남아 있지 않은 경우에도 true를 반환합니다.
user2672052

0
private static NetworkUtil mInstance;
private volatile boolean mIsOnline;

private NetworkUtil() {
    ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
    exec.scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            boolean reachable = false;
            try {
                Process process = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
                int returnVal = process.waitFor();
                reachable = (returnVal==0);
            } catch (Exception e) {
                e.printStackTrace();
            }
            mIsOnline = reachable;
        }
    }, 0, 5, TimeUnit.SECONDS);
}

public static NetworkUtil getInstance() {
    if (mInstance == null) {
        synchronized (NetworkUtil.class) {
            if (mInstance == null) {
                mInstance = new NetworkUtil();
            }
        }
    }
    return mInstance;
}

public boolean isOnline() {
    return mIsOnline;
}

위의 코드가 도움이되기를 바랍니다. 또한 ur 응용 프로그램에서 인터넷 권한이 있는지 확인하십시오.


0

으로부터 그렇게 할 수있는 최신 방법 문서는 을 사용하는 ConnectivityManager활성 네트워크를 조회하고 인터넷 연결이 있는지 확인.

public boolean hasInternetConnectivity() {
    ConnectivityManager cm =
        (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return (activeNetwork != null &&
                      activeNetwork.isConnectedOrConnecting());
}

AndroidManifest.xml 파일에 다음 두 가지 권한을 추가하십시오.

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

1
작동하지 않음 : (@ Buda Gavril에 따르면 인터넷에 액세스 할 수없는 무선 네트워크에 연결되어있는 경우이 방법은 여전히 ​​true를 반환합니다. Xiaomi 4, Android 6.0.1에서 테스트
DysaniazzZ

0

연결 관리자에서 Wi-Fi 유형을 확인하십시오.

   //check network connection
    ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    boolean hasNetworkConnection = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    System.out.println("Connection ? : " + hasNetworkConnection);
    //check wifi
    boolean hasWifiConnection = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
    System.out.println("Wifi ? : " + hasWifiConnection);

Android 설명서에서는 'TYPE_WIFI'를 'WIFI 데이터 연결로 설명합니다. 장치는 둘 이상을 지원할 수 있습니다. '


0

활성 네트워크가 인터넷에 연결되어 있는지 확인하는 좋은 솔루션 :

public boolean isNetworkAvailable(Context context) {
    ConnectivityManager connectivityManager
            = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivityManager != null) {
        Network network = connectivityManager.getActiveNetwork();
        NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);
        return networkCapabilities != null && networkCapabilities
                .hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    }
    return false;
}

0

ConnectivityManager를 사용할 수 있습니다.

val cm = getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            val activeNetwork: NetworkInfo? = cm.activeNetworkInfo
            val dialogBuilder = AlertDialog.Builder(this)

            if (activeNetwork!=null) // Some network is available
            {
                if (activeNetwork.isConnected) { // Network is connected to internet

    }else{ // Network is NOT connected to internet

    }

이것이것을 확인하십시오


0

마지막 API 레벨로 업데이트 된 다음 클래스를 사용하십시오 . 29.

// License: MIT
// http://opensource.org/licenses/MIT
package net.i2p.android.router.util;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Build;
import android.telephony.TelephonyManager;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.concurrent.CancellationException;



/**
 * Check device's network connectivity and speed.
 *
 * @author emil http://stackoverflow.com/users/220710/emil
 * @author str4d
 * @author rodrigo https://stackoverflow.com/users/5520417/rodrigo
 */
public class ConnectivityAndInternetAccessCheck {

    private static ArrayList < String > hosts = new ArrayList < String > () {
        {
            add("google.com");
            add("facebook.com");
            add("apple.com");
            add("amazon.com");
            add("twitter.com");
            add("linkedin.com");
            add("microsoft.com");
        }
    };
    /**
     * Get the network info.
     *
     * @param context the Context.
     * @return the active NetworkInfo.
     */
    private static NetworkInfo getNetworkInfo(Context context) {
        NetworkInfo networkInfo = null;
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm != null) {
            networkInfo = cm.getActiveNetworkInfo();
        }
        return networkInfo;
    }

    /**
     * Gets the info of all networks
     * @param context The context
     * @return an array of @code{{@link NetworkInfo}}
     */
    private static NetworkInfo[] getAllNetworkInfo(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        return cm.getAllNetworkInfo();
    }

    /**
     * Gives the connectivity manager
     * @param context The context
     * @return the @code{{@link ConnectivityManager}}
     */
    private static ConnectivityManager getConnectivityManager(Context context) {
        return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    }

    /**
     * Check if there is any connectivity at all.
     *
     * @param context the Context.
     * @return true if we are connected to a network, false otherwise.
     */
    public static boolean isConnected(Context context) {
        boolean isConnected = false;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ConnectivityManager connectivityManager = ConnectivityAndInternetAccessCheck.getConnectivityManager(context);
            Network[] networks = connectivityManager.getAllNetworks();
            networksloop: for (Network network: networks) {
                if (network == null) {
                    isConnected = false;
                } else {
                    NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);
                    if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)){
                        isConnected = true;
                        break networksloop;
                    }
                    else {
                        isConnected = false;
                    }
                }
            }

        } else {
            NetworkInfo[] networkInfos = ConnectivityAndInternetAccessCheck.getAllNetworkInfo(context);
            networkinfosloop: for (NetworkInfo info: networkInfos) {
                // Works on emulator and devices.
                // Note the use of isAvailable() - without this, isConnected() can
                // return true when Wifi is disabled.
                // http://stackoverflow.com/a/2937915
                isConnected = info != null && info.isAvailable() && info.isConnected();
                if (isConnected) {
                    break networkinfosloop;
                }
            }

        }
        return isConnected;
    }

    /**
     * Check if there is any connectivity to a Wifi network.
     *
     * @param context the Context.
     * @return true if we are connected to a Wifi network, false otherwise.
     */
    public static boolean isConnectedWifi(Context context) {
        boolean isConnectedWifi = false;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ConnectivityManager connectivityManager = ConnectivityAndInternetAccessCheck.getConnectivityManager(context);
            Network[] networks = connectivityManager.getAllNetworks();
            networksloop: for (Network network: networks) {
                if (network == null) {
                    isConnectedWifi = false;
                } else {
                    NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);
                    if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)){
                        if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                            isConnectedWifi = true;
                            break networksloop;
                        } else {
                            isConnectedWifi = false;
                        }
                    }
                }

            }


        } else {
            NetworkInfo[] networkInfos = ConnectivityAndInternetAccessCheck.getAllNetworkInfo(context);
            networkinfosloop: for (NetworkInfo n: networkInfos) {
                isConnectedWifi = n != null && n.isAvailable() && n.isConnected() && n.getType() == ConnectivityManager.TYPE_WIFI;
                if (isConnectedWifi) {
                    break networkinfosloop;
                }

            }
        }
        return isConnectedWifi;
    }

    /**
     * Check if there is any connectivity to a mobile network.
     *
     * @param context the Context.
     * @return true if we are connected to a mobile network, false otherwise.
     */
    public static boolean isConnectedMobile(Context context) {
        boolean isConnectedMobile = false;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ConnectivityManager connectivityManager = ConnectivityAndInternetAccessCheck.getConnectivityManager(context);
            Network[] allNetworks = connectivityManager.getAllNetworks();
            networksloop: for (Network network: allNetworks) {
                if (network == null) {
                    isConnectedMobile = false;
                } else {
                    NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);
                    if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)){
                        if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                            isConnectedMobile = true;
                            break networksloop;
                        } else {
                            isConnectedMobile = false;
                        }
                    }
                }

            }

        } else {
            NetworkInfo[] networkInfos = ConnectivityAndInternetAccessCheck.getAllNetworkInfo(context);
            networkinfosloop: for (NetworkInfo networkInfo: networkInfos) {
                isConnectedMobile = networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected() && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE;
                if (isConnectedMobile) {
                    break networkinfosloop;
                }
            }
        }
        return isConnectedMobile;
    }

    /**
     * Check if there is fast connectivity.
     *
     * @param context the Context.
     * @return true if we have "fast" connectivity, false otherwise.
     */
    public static boolean isConnectedFast(Context context) {
        boolean isConnectedFast = false;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            NetworkInfo[] networkInfos = ConnectivityAndInternetAccessCheck.getAllNetworkInfo(context);
            networkInfosloop:
            for (NetworkInfo networkInfo: networkInfos) {
                isConnectedFast = networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected() && isConnectionFast(networkInfo.getType(), networkInfo.getSubtype());
                if (isConnectedFast) {
                    break networkInfosloop;
                }
            }
        } else {
            throw new UnsupportedOperationException();
        }
        return isConnectedFast;
    }

    /**
     * Check if the connection is fast.
     *
     * @param type the network type.
     * @param subType the network subtype.
     * @return true if the provided type/subtype combination is classified as fast.
     */
    private static boolean isConnectionFast(int type, int subType) {
        if (type == ConnectivityManager.TYPE_WIFI) {
            return true;
        } else if (type == ConnectivityManager.TYPE_MOBILE) {
            switch (subType) {
                case TelephonyManager.NETWORK_TYPE_1xRTT:
                    return false; // ~ 50-100 kbps
                case TelephonyManager.NETWORK_TYPE_CDMA:
                    return false; // ~ 14-64 kbps
                case TelephonyManager.NETWORK_TYPE_EDGE:
                    return false; // ~ 50-100 kbps
                case TelephonyManager.NETWORK_TYPE_EVDO_0:
                    return true; // ~ 400-1000 kbps
                case TelephonyManager.NETWORK_TYPE_EVDO_A:
                    return true; // ~ 600-1400 kbps
                case TelephonyManager.NETWORK_TYPE_GPRS:
                    return false; // ~ 100 kbps
                case TelephonyManager.NETWORK_TYPE_HSDPA:
                    return true; // ~ 2-14 Mbps
                case TelephonyManager.NETWORK_TYPE_HSPA:
                    return true; // ~ 700-1700 kbps
                case TelephonyManager.NETWORK_TYPE_HSUPA:
                    return true; // ~ 1-23 Mbps
                case TelephonyManager.NETWORK_TYPE_UMTS:
                    return true; // ~ 400-7000 kbps
                /*
                 * Above API level 7, make sure to set android:targetSdkVersion
                 * to appropriate level to use these
                 */
                case TelephonyManager.NETWORK_TYPE_EHRPD: // API level 11
                    return true; // ~ 1-2 Mbps
                case TelephonyManager.NETWORK_TYPE_EVDO_B: // API level 9
                    return true; // ~ 5 Mbps
                case TelephonyManager.NETWORK_TYPE_HSPAP: // API level 13
                    return true; // ~ 10-20 Mbps
                case TelephonyManager.NETWORK_TYPE_IDEN: // API level 8
                    return false; // ~25 kbps
                case TelephonyManager.NETWORK_TYPE_LTE: // API level 11
                    return true; // ~ 10+ Mbps
                // Unknown
                case TelephonyManager.NETWORK_TYPE_UNKNOWN:
                default:
                    return false;
            }
        } else {
            return false;
        }
    }

    public ArrayList < String > getHosts() {
        return hosts;
    }

    public void setHosts(ArrayList < String > hosts) {
        this.hosts = hosts;
    }
    //TODO Debug on devices
    /**
     * Checks that Internet is available by pinging DNS servers.
     */
    private static class InternetConnectionCheckAsync extends AsyncTask < Void, Void, Boolean > {

        private Context context;

        /**
         * Creates an instance of this class
         * @param context The context
         */
        public InternetConnectionCheckAsync(Context context) {
            this.setContext(context);
        }

        /**
         * Cancels the activity if the device is not connected to a network.
         */
        @Override
        protected void onPreExecute() {
            if (!ConnectivityAndInternetAccessCheck.isConnected(getContext())) {
                cancel(true);
            }
        }

        /**
         * Tells whether there is Internet access
         * @param voids The list of arguments
         * @return True if Internet can be accessed
         */
        @Override
        protected Boolean doInBackground(Void...voids) {
            return isConnectedToInternet(getContext());
        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
        }

        /**
         * The context
         */
        public Context getContext() {
            return context;
        }

        public void setContext(Context context) {
            this.context = context;
        }
    } //network calls shouldn't be called from main thread otherwise it will throw //NetworkOnMainThreadException

    /**
     * Tells whether Internet is reachable
     * @return true if Internet is reachable, false otherwise
     * @param context The context
     */
    public static boolean isInternetReachable(Context context) {
        try {
            return new InternetConnectionCheckAsync(context).execute().get();
        } catch (CancellationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Tells whether there is Internet connection
     * @param context The context
     * @return @code {true} if there is Internet connection
     */
    private static boolean isConnectedToInternet(Context context) {
        boolean isAvailable = false;
        if (!ConnectivityAndInternetAccessCheck.isConnected(context)) {
            isAvailable = false;
        } else {
            try {
                foreachloop: for (String h: new ConnectivityAndInternetAccessCheck().getHosts()) {
                    if (isHostAvailable(h)) {
                        isAvailable = true;
                        break foreachloop;
                    }
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }

        return isAvailable;

    }

    /**
     * Checks if the host is available
     * @param hostName
     * @return
     * @throws IOException
     */
    private static boolean isHostAvailable(String hostName) throws IOException {
        try (Socket socket = new Socket()) {
            int port = 80;
            InetSocketAddress socketAddress = new InetSocketAddress(hostName, port);
            socket.connect(socketAddress, 3000);

            return true;
        } catch (UnknownHostException unknownHost) {
            return false;
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.