Android에서 인터넷 액세스를 확인하는 방법은 무엇입니까? InetAddress는 절대로 시간 초과되지 않습니다.


Answers

네트워크 연결 / 인터넷 액세스

  • isConnectedOrConnecting() (대부분의 답변에서 사용됨) 네트워크 연결을 확인합니다.
  • 해당 네트워크에 인터넷에 액세스 할 수 있는지 알아 보려면 다음 중 하나를 사용하십시오.

A) 서버 핑 (쉬운)

// ICMP 
public boolean isOnline() {
    Runtime runtime = Runtime.getRuntime();
    try {
        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int     exitValue = ipProcess.waitFor();
        return (exitValue == 0);
    }
    catch (IOException e)          { e.printStackTrace(); }
    catch (InterruptedException e) { e.printStackTrace(); }

    return false;
}

+ 주 스레드에서 실행할 수 있습니다.

- 일부 오래된 기기 (Galays S3 등)에서는 작동하지 않으며 인터넷을 사용할 수없는 경우 잠시 차단됩니다.

B) 인터넷 소켓 연결 (고급)

// TCP/HTTP/DNS (depending on the port, 53=DNS, 80=HTTP, etc.)
public boolean isOnline() {
    try {
        int timeoutMs = 1500;
        Socket sock = new Socket();
        SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 53);

        sock.connect(sockaddr, timeoutMs);
        sock.close();

        return true;
    } catch (IOException e) { return false; }
}

+ 매우 빠른 (어느 쪽이든), 모든 장치에서 작동하며 매우 안정적입니다.

~ UI 작업에서 실행할 수 없습니다.

- 없음

이것은 모든 장치에서 매우 안정적으로 작동하며 매우 빠릅니다. 그것은 별도의 작업 (예 : ScheduledExecutorService 또는 AsyncTask )에서 실행해야합니다.

가능한 질문들

  • 정말 빠릅니까?

    예, 매우 빠릅니다 ;-)

  • 인터넷에서 뭔가를 테스트하는 것 이외에 인터넷을 확인할 수있는 확실한 방법이 있습니까?

    내가 아는 한 멀지 만 내게 알려 주면 내 대답을 편집 할 것입니다.

  • DNS가 다운되면 어떻게 될까요?

    Google DNS (예 : 8.8.8.8 )는 전 세계에서 가장 큰 공개 DNS입니다. 2013 년 현재 1 억 3 천억 건의 요청을 처리했습니다. 말하자면 앱이 당일 대화가 아닐 것입니다.

  • 어떤 권한이 필요합니까?

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

    그냥 인터넷 접속 - 깜짝 ^ ^ (Btw 혹시 생각해 봤어, 여기에 제안 된 방법 중 일부는이 허가없이 인터넷 액세스에 대한 원격 접착제를 가질 수 있습니까?)

Extra : 원 샷 AsyncTask 예제

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

    private Consumer mConsumer;
    public  interface Consumer { void accept(Boolean internet); }

    public  InternetCheck(Consumer consumer) { mConsumer = consumer; execute(); }

    @Override protected Boolean doInBackground(Void... voids) { try {
        Socket sock = new Socket();
        sock.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
        sock.close();
        return true;
    } catch (IOException e) { return false; } }

    @Override protected void onPostExecute(Boolean internet) { mConsumer.accept(internet); }
}

///////////////////////////////////////////////////////////////////////////////////
// Usage

    new InternetCheck(internet -> { /* do something with boolean response */ });
Question

호스트 이름에 대한 네트워크 액세스를 확인해야하는 AsyncTask 가 있습니다. 그러나 doInBackground() 는 절대로 타임 아웃되지 않습니다. 누구나 단서가 있습니까?

public class HostAvailabilityTask extends AsyncTask<String, Void, Boolean> {

    private Main main;

    public HostAvailabilityTask(Main main) {
        this.main = main;
    }

    protected Boolean doInBackground(String... params) {
        Main.Log("doInBackground() isHostAvailable():"+params[0]);

        try {
            return InetAddress.getByName(params[0]).isReachable(30); 
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;       
    }

    protected void onPostExecute(Boolean... result) {
        Main.Log("onPostExecute()");

        if(result[0] == false) {
            main.setContentView(R.layout.splash);
            return;
        }

        main.continueAfterHostCheck();
    }   
}



getActiveNetworkInfo() 를 작동 시키려면 매니페스트에 다음을 추가해야합니다.

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



지금까지 본 모든 것 중에서 가장 짧고 깨끗한 방법은 다음과 같아야합니다.

public final static boolean isConnected( Context context )
{   
   final ConnectivityManager connectivityManager = 
         (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE );  
   final NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();    
   return networkInfo != null && networkInfo.isConnected();
}

추신 : 이것은 어떤 호스트도 핑하지 않으며, 단지 connectionstatus를 검사합니다. 따라서 라우터에 인터넷 연결이없고 장치가 연결되어 있으면 인터넷이 없어도이 메서드는 true를 반환 합니다 .
실제 테스트를 위해 HttpHead 요청 (예 : www.google.com)을 실행 하고 상태를 확인하는 것이 좋습니다. 200 개의 OK 항목 모두 정상적으로 작동하고 기기에 인터넷이 연결되어있는 경우입니다.




Update 29/06/2015 If you are using Xamarin.Android and want to check for connectivity, you can use a Nuget package that would give you this functionality on multiple platforms. Good candidates are here and here . [End of Update]

The Answers above are quite good, but they are all in Java, and almost all of them check for a connectivity. In my case, I needed to have connectivity with a specific type of connection and I am developing on Xamarin.Android. Moreover, I do not pass a reference to my activities Context in the Hardware layer, I use the Application Context. So here is my solution, in case somebody comes here with similar requirements. I have not done full testing though, will update the answer once I am done with my testing

using Android.App;
using Android.Content;
using Android.Net;

namespace Leopard.Mobile.Hal.Android
{
    public class AndroidNetworkHelper
    {
        public static AndroidNetworkStatus GetWifiConnectivityStatus()
        {
            return GetConnectivityStatus(ConnectivityType.Wifi);
        }

        public static AndroidNetworkStatus GetMobileConnectivityStatus()
        {
            return GetConnectivityStatus(ConnectivityType.Mobile);
        }

        #region Implementation

        private static AndroidNetworkStatus GetConnectivityStatus(ConnectivityType connectivityType)
        {
            var connectivityManager = (ConnectivityManager)Application.Context.GetSystemService(Context.ConnectivityService);
            var wifiNetworkInfo = connectivityManager.GetNetworkInfo(connectivityType);
            var result = GetNetworkStatus(wifiNetworkInfo);
            return result;
        }

        private static AndroidNetworkStatus GetNetworkStatus(NetworkInfo wifiNetworkInfo)
        {
            var result = AndroidNetworkStatus.Unknown;
            if (wifiNetworkInfo != null)
            {
                if (wifiNetworkInfo.IsAvailable && wifiNetworkInfo.IsConnected)
                {
                    result = AndroidNetworkStatus.Connected;
                }
                else
                {
                    result = AndroidNetworkStatus.Disconnected;
                }
            }
            return result;
        } 

        #endregion
    }

    public enum AndroidNetworkStatus
    {
        Connected,
        Disconnected,
        Unknown
    }



ConnectivityManager를 사용하는 다른 대답은 잘못된 것입니다. 네트워크 연결을한다고해서 인터넷에 접속할 수있는 것은 아니기 때문입니다. 예를 들어 사용자가 커피 숍의 WiFi 포털에 연결되어 있지만 인터넷에 연결할 수는 없습니다. 인터넷에 액세스 할 수 있는지 확인하려면 실제 서버에 연결해야합니다. 일반적으로이 작업을 수행하려는 경우 연결하려는 특정 서버를 염두에두고 있으므로 해당 서버에 연결할 수 있는지 확인하십시오. 다음은 서버에 대한 연결을 확인하는 간단한 방법입니다.

private boolean isOnTheInternet() {
    try {
        URLConnection urlConnection = new URL("http://yourserver").openConnection();
        urlConnection.setConnectTimeout(400);
        urlConnection.connect();
        return true;
    } catch (Exception e) {
        return false;
    }
}

ConnectTimeout을 설정하는 이유는 기본값 인 TCP 시간 초과를 기본값으로 사용하기 때문에 수 초가 걸릴 수 있기 때문입니다.

안드로이드는 메인 스레드에서 이것을 실행할 수 없게됩니다.




public boolean isOnline() {
    boolean var = false;
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    if ( cm.getActiveNetworkInfo() != null ) {
        var = true;
    }
    return var;
} 

I have done it this way. A little bit shorter and more readable I guess.

건배!

Saiyan




ConnectivityManager 클래스를 살펴보십시오. 이 클래스를 사용하여 호스트의 활성 연결에 대한 정보를 얻을 수 있습니다. http://developer.android.com/reference/android/net/ConnectivityManager.html

편집 : 당신은 사용할 수 있습니다

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_MOBILE) 

또는

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_WIFI) 

반환 된 NetworkInfo 객체의 DetailedState 열거 형을 구문 분석합니다.

수정 편집 : 호스트에 액세스 할 수 있는지 여부를 확인하려면 다음을 사용할 수 있습니다.

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .requestRouteToHost(TYPE_WIFI, int hostAddress)

분명히 Context.getSystemService (Context.CONNECTIVITY_SERVICE)를 프록시로 사용하고 있습니다.

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






나는이 코드를 만들었고, 그것은 가장 단순하며 부울 뿐이다. if(isOnline()){

연결이 있고 페이지에 상태 코드 200 (안정된 연결)을 연결할 수 있으면 얻을 수 있습니다.

올바른 INTERNETACCESS_NETWORK_STATE 권한을 추가해야합니다.

public boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnected()) {
        try {
            URL url = new URL("http://www.google.com");
            HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
            urlc.setConnectTimeout(3000);
            urlc.connect();
            if (urlc.getResponseCode() == 200) {
                return new Boolean(true);
            }
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    return false;
}



최상의 접근 방식 :

public static boolean isOnline() {
    try {
    InetAddress.getByName("google.com").isReachable(3);

    return true;
    } catch (UnknownHostException e){
    return false;
    } catch (IOException e){
    return false;
    }
    }



There's more than one way

First, shortest but Inefficient way

Network State Permission only needed

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

Then this method,

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

        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        boolean isConnected = activeNetwork != null &&
                activeNetwork.isConnected();

        return isConnected;

    }

As seen in answers ConnectivityManager is a solution, I just added it within a method this is a simplified method all use
ConnectivityManager returns true if there is a network access not Internet access, means if your WiFi is connected to a router but the router has no internet it returns true, it check connection availability

Second, Efficient way

Network State and Internet Permissions needed

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

Then this class,

 public class CheckInternetAsyncTask extends AsyncTask<Void, Integer, Boolean> {

        private Context context;

        public CheckInternetAsyncTask(Context context) {
            this.context = context;
        }

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

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

            assert cm != null;
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            boolean isConnected = activeNetwork != null &&
                    activeNetwork.isConnected();


            if (isConnected) {
                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();
                    if (urlc.getResponseCode() == 204 &&
                            urlc.getContentLength() == 0)
                        return true;

                } catch (IOException e) {
                    Log.e("TAG", "Error checking internet connection", e);
                    return false;
                }
            } else {
                Log.d("TAG", "No network available!");
                return false;
            }


            return null;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            Log.d("TAG", "result" + result);

            if(result){
                // do ur code
            }

        }


    }

Call CheckInternetAsyncTask

new CheckInternetAsyncTask(getApplicationContext()).execute();

Some Explanations :-

  • you have to check Internet on AsyncTask , otherwise it can throw android.os.NetworkOnMainThreadException in some cases

  • ConnectivityManager used to check the network access if true sends request (Ping)

  • Request send to http://clients3.google.com/generate_204 , This well-known URL is known to return an empty page with an HTTP status 204 this is faster and more efficient than http://www.google.com , read this . if you have website it's preferred to put you website instead of google, only if you use it within the app

  • Timeout can be changed range (20ms -> 2000ms), 1500ms is commonly used




모든 네트워크 연결을 반복하고 사용할 수있는 연결이 하나 이상 있는지 확인하십시오.

public boolean isConnected() {
    boolean connected = false;

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

    if (cm != null) {
        NetworkInfo[] netInfo = cm.getAllNetworkInfo();

        for (NetworkInfo ni : netInfo) {
            if ((ni.getTypeName().equalsIgnoreCase("WIFI")
                    || ni.getTypeName().equalsIgnoreCase("MOBILE"))
                    && ni.isConnected() && ni.isAvailable()) {
                connected = true;
            }

        }
    }

    return connected;
}



Im InetAddress 대신이 코드를 사용합니다.

    try {

        URL url = new URL("http://"+params[0]);

        HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
        urlc.setRequestProperty("User-Agent", "Android Application:"+Z.APP_VERSION);
        urlc.setRequestProperty("Connection", "close");
        urlc.setConnectTimeout(1000 * 30); // mTimeout is in seconds
        urlc.connect();
        if (urlc.getResponseCode() == 200) {
            Main.Log("getResponseCode == 200");
            return new Boolean(true);
        }
    } catch (MalformedURLException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }



public class Network {

Context context;

public Network(Context context){
    this.context = context;
}

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

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

}



그것은 나를 위해 일합니다. 그것을 밖으로 시도하십시오.

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    try {
        URL url = new URL("http://.com/posts/11642475/edit" );
        //URL url = new URL("http://www.nofoundwebsite.com/" );
        executeReq(url);
        Toast.makeText(getApplicationContext(), "Webpage is available!", Toast.LENGTH_SHORT).show();
    }
    catch(Exception e) {
        Toast.makeText(getApplicationContext(), "oops! webpage is not available!", Toast.LENGTH_SHORT).show();
    }
}

private void executeReq(URL urlObject) throws IOException
{
    HttpURLConnection conn = null;
    conn = (HttpURLConnection) urlObject.openConnection();
    conn.setReadTimeout(30000);//milliseconds
    conn.setConnectTimeout(3500);//milliseconds
    conn.setRequestMethod("GET");
    conn.setDoInput(true);

    // Start connect
    conn.connect();
    InputStream response =conn.getInputStream();
    Log.d("Response:", response.toString());
}}





Links