안드로이드에서 인터넷 접속을 확인하는 방법? InetAddress가 시간 초과되지 않습니다

내가 가지고 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();
    }
}


답변

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

  • 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,300 억 건의 요청을 처리했습니다. 당신의 앱이 아마도 오늘의 이야기가 아닐 수도 있습니다.

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

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

    그냥 인터넷 액세스-놀람 ^^ (Btw 당신은 여기에 제안 된 방법 중 일부 가이 허락없이 인터넷 액세스에 대한 원격 접착제를 가질 수있는 방법에 대해 생각해 본 적이 있습니까?)

 

추가 : 원샷 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 */ });

추가 : 원샷 RxJava/RxAndroid예 (코 틀린)

fun hasInternetConnection(): Single<Boolean> {
  return Single.fromCallable {
    try {
      // Connect to Google DNS to check for connection
      val timeoutMs = 1500
      val socket = Socket()
      val socketAddress = InetSocketAddress("8.8.8.8", 53)

      socket.connect(socketAddress, timeoutMs)
      socket.close()

      true
    } catch (e: IOException) {
      false
    }
  }
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
}

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

    hasInternetConnection().subscribe { hasInternet -> /* do something */}

답변

기기가 비행기 모드 인 경우 (또는 사용 가능한 네트워크가없는 다른 상황 일 경우)로 cm.getActiveNetworkInfo()표시 null되므로 null확인 을 추가해야합니다 .

아래 에서 수정 된 ( Eddie ‘s solution ) :

public boolean isOnline() {
    ConnectivityManager cm =
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    return netInfo != null && netInfo.isConnectedOrConnecting();
}

또한 다음 권한을 다음에 추가하십시오 AndroidManifest.xml.

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

하나의 다른 작은 지점은 주어진 시점에 네트워크 연결이 절대적으로 필요한 경우 netInfo.isConnected()보다 오히려 사용하는 것이 좋습니다 netInfo.isConnectedOrConnecting. 그러나 이것은 개별 사용 사례에 달려 있습니다.


답변

복잡 할 필요는 없습니다. 가장 간단한 프레임 워크 방식은 ACCESS_NETWORK_STATE권한 을 사용 하고 연결된 방법을 만드는 것입니다.

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

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

또한 requestRouteToHost특정 호스트 및 연결 유형 (wifi / mobile)을 염두에두고 사용할 수도 있습니다.

또한 다음이 필요합니다.

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

당신의 안드로이드 매니페스트에서.


답변

getActiveNetworkInfo()작업 하려면 매니페스트에 다음을 추가해야합니다.

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

답변

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();

답변

이 코드를 확인하십시오 … 그것은 나를 위해 일했습니다 🙂

public static void isNetworkAvailable(final Handler handler, final int timeout) {
    // ask fo message '0' (not connected) or '1' (connected) on 'handler'
    // the answer must be send before before within the 'timeout' (in milliseconds)

    new Thread() {
        private boolean responded = false;
        @Override
        public void run() {
            // set 'responded' to TRUE if is able to connect with google mobile (responds fast) 
            new Thread() {
                @Override
                public void run() {
                    HttpGet requestForTest = new HttpGet("http://m.google.com");
                    try {
                        new DefaultHttpClient().execute(requestForTest); // can last...
                        responded = true;
                    }
                    catch (Exception e) {
                    }
                }
            }.start();

            try {
                int waited = 0;
                while(!responded && (waited < timeout)) {
                    sleep(100);
                    if(!responded ) {
                        waited += 100;
                    }
                }
            }
            catch(InterruptedException e) {} // do nothing 
            finally {
                if (!responded) { handler.sendEmptyMessage(0); }
                else { handler.sendEmptyMessage(1); }
            }
        }
    }.start();
}

그런 다음 핸들러를 정의합니다.

Handler h = new Handler() {
    @Override
    public void handleMessage(Message msg) {

        if (msg.what != 1) { // code if not connected

        } else { // code if connected

        }
    }
};

… 그리고 테스트를 시작하십시오 :

isNetworkAvailable(h,2000); // get the answser within 2000 ms

답변

에서 확인할 수 있고이에서 수정 (!) 링크 :

매니페스트 파일에서 최소한 다음을 추가하십시오.

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

인터넷 액세스 권한이있을 수 있습니다. 연결성을 테스트 할 수있는 부울 함수는 다음과 같습니다.

private boolean checkInternetConnection() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    // test for connection
    if (cm.getActiveNetworkInfo() != null
            && cm.getActiveNetworkInfo().isAvailable()
            && cm.getActiveNetworkInfo().isConnected()) {
        return true;
    } else {
        Log.v(TAG, "Internet Connection Not Present");
        return false;
    }
}