프로그래밍 언어/Android

Android에서 인터넷 액세스를 확인하는 방법

Rateye 2021. 10. 1. 12:07
728x90
반응형
질문 : Android에서 인터넷 액세스를 확인하는 방법은 무엇입니까? 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입니다. 2018 년 현재 하루에 1 조 건이 넘는 쿼리를 처리했습니다 [1]. 여러분의 앱이 오늘의 화제가 아닐 것입니다.
  • 어떤 권한이 필요합니까?
    <uses-permission android:name="android.permission.INTERNET" />
    그냥 인터넷 액세스-놀랍습니다 ^^ (Btw 당신은 여기에서 제안한 방법 중 일부 가이 권한없이 인터넷 액세스에 대한 원격 접착제를 가질 수 있는지 생각해 본 적이 있습니까?)

 

추가: RxJava/RxAndroid 예 (Kotlin)

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 */}

 

추가: RxJava/RxAndroid 예 (Java)

public static Single<Boolean> hasInternetConnection() {
    return Single.fromCallable(() -> {
        try {
            // Connect to Google DNS to check for connection
            int timeoutMs = 1500;
            Socket socket = new Socket();
            InetSocketAddress socketAddress = new InetSocketAddress("8.8.8.8", 53);

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

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

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

    hasInternetConnection().subscribe((hasInternet) -> {
        if(hasInternet) {

        }else {

        }
    });

 

추가: AsyncTask 예

주의 : 이것은 요청을 수행하는 방법의 또 다른 예를 보여줍니다. 그러나 AsyncTask 는 더 이상 사용되지 않으므로 앱의 스레드 예약, Kotlin Coroutines, Rx 등으로 대체해야합니다.

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 */ });
출처 : https://stackoverflow.com/questions/1560788/how-to-check-internet-access-on-android-inetaddress-never-times-out
728x90
반응형