네트워크 상태 읽기

Android에서는 앱이 연결의 동적 변경사항을 학습할 수 있습니다. 다음 클래스를 사용하여 연결 변경사항을 추적하고 적절히 대응하세요.

  • ConnectivityManager는 앱에 시스템의 연결 상태를 알립니다.
  • Network 클래스는 기기가 현재 연결된 네트워크 중 하나를 나타냅니다. Network 객체를 키로 사용하여 ConnectivityManager와 함께 네트워크 정보를 수집하거나 네트워크에서 소켓을 결합할 수 있습니다. 네트워크 연결이 끊어지면 Network 객체는 사용이 중지됩니다. 나중에 기기가 동일한 어플라이언스에 다시 연결되더라도 새 Network 객체는 새 네트워크를 나타냅니다.
  • LinkProperties 객체에는 네트워크에 설치된 DNS 서버, 로컬 IP 주소, 네트워크 경로 목록 등의 네트워크 연결 정보가 포함됩니다.
  • NetworkCapabilities 객체에는 전송(Wi-Fi, 셀룰러, 블루투스) 및 네트워크에서 사용할 수 있는 기능과 같은 네트워크 속성 정보가 포함됩니다. 예를 들어, 객체를 쿼리하여 네트워크가 MMS를 전송할 수 있는지, 종속 포털을 지원하는지, 데이터 전송량 제한이 있는지 확인할 수 있습니다.

어느 때든 즉각적인 연결 상태를 알고자 하는 앱은 ConnectivityManager 메서드를 호출하여 사용할 수 있는 네트워크 종류를 확인할 수 있습니다. 이러한 메서드는 디버깅하는 데 도움이 되고, 어느 때든 사용 가능한 연결의 개요를 이따금 검토하는 데 유용합니다. 그러나 동기식 ConnectivityManager 메서드는 호출 후 발생하는 일에 관해 앱에 알리지 않으므로 이러한 메서드를 사용하면 네트워크 연결이 해제되거나 네트워크 기능이 변경될 때 UI를 업데이트하거나 앱 동작을 조정할 수 없습니다.

연결은 언제든지 변경될 수 있고 대부분의 앱은 기기에서 네트워킹 상태 뷰를 최신으로 유지해야 하므로 앱은 ConnectivityManager를 사용하여 콜백을 등록하고 관심 있는 변경사항에 관해 알림을 받을 수 있습니다. 콜백을 사용하면 빠른 업데이트를 놓칠 수 있는 값비싼 폴링에 의존하지 않고 앱에서 연결의 관련 변경사항에 즉시 반응할 수 있습니다.

순간적인 상태 가져오기

Android 기기는 동시에 많은 연결을 유지할 수 있습니다. 먼저 ConnectivityManager 인스턴스를 가져옵니다.

Kotlin

val connectivityManager = getSystemService(ConnectivityManager::class.java)

자바

ConnectivityManager connectivityManager = getSystemService(ConnectivityManager.class);

이 인스턴스를 사용하여 앱의 현재 기본 네트워크에 관한 참조를 가져옵니다.

Kotlin

val currentNetwork = connectivityManager.getActiveNetwork()

자바

Network currentNetwork = connectivityManager.getActiveNetwork();

앱은 네트워크 참조를 사용하여 네트워크 정보를 쿼리할 수 있습니다.

Kotlin

val caps = connectivityManager.getNetworkCapabilities(currentNetwork)
val linkProperties = connectivityManager.getLinkProperties(currentNetwork)

자바

NetworkCapabilities caps = connectivityManager.getNetworkCapabilities(currentNetwork);
LinkProperties linkProperties = connectivityManager.getLinkProperties(currentNetwork);

순간적인 상태를 쿼리하는 것은 디버깅을 제외하고 대부분의 앱에서 유용하지 않습니다. 새 네트워크가 들어올 때와 네트워크 연결이 끊길 때 알림을 받는 것과 같이 더 유용한 기능을 사용하려면 NetworkCallback을 등록하세요. 네트워크 콜백 등록에 관한 자세한 내용은 네트워크 이벤트 수신 대기를 참고하세요.

NetworkCapabilities 및 LinkProperties

NetworkCapabilitiesLinkProperties 객체는 네트워크에 관해 시스템이 알고 있는 모든 속성 정보를 제공합니다. LinkProperties 객체는 경로, 링크 주소, 인터페이스 이름, 프록시 정보(있는 경우), DNS 서버에 관해 알고 있습니다. LinkProperties 객체의 관련 메서드를 호출하여 필요한 정보를 얻을 수 있습니다. NetworkCapabilities 객체는 네트워크 전송 및 관련 기능 정보를 캡슐화합니다.

전송은 네트워크가 작동하는 실제 매체의 추상화입니다. 전송의 일반적인 예로는 이더넷, Wi-Fi, 셀룰러가 있지만, VPN 또는 P2P Wi-Fi도 포함될 수 있습니다.

Android에서는 한 네트워크가 동시에 여러 개의 전송을 사용할 수 있습니다. 이러한 예로 Wi-Fi 네트워크와 셀룰러 네트워크에서 모두 작동하는 VPN을 들 수 있습니다. 이런 네트워크는 Wi-Fi, 셀룰러, VPN 전송을 사용할 수 있습니다. 네트워크가 특정 전송을 사용하는지 확인하려면 NetworkCapabilities.TRANSPORT_* 상수 중 하나와 함께 NetworkCapabilities.hasTransport(int)를 사용합니다.

기능은 네트워크 속성을 설명합니다. 기능의 예로 MMS, NOT_METERED, INTERNET을 들 수 있습니다. MMS 기능이 있는 네트워크는 멀티미디어 메시지 서비스의 메시지를 송수신할 수 있지만, 이 기능이 없는 네트워크는 할 수 없습니다. NOT_METERED 기능이 있는 네트워크는 사용자에게 데이터 요금을 청구하지 않습니다. 앱에서는 NetworkCapabilities.NET_CAPABILITY_* 상수 중 하나와 함께 NetworkCapabilities.hasCapability(int) 메서드를 사용하여 적절한 기능을 확인할 수 있습니다.

가장 유용한 NET_CAPABILITY_* 상수는 다음과 같습니다.

  • NET_CAPABILITY_INTERNET: 이 기능은 네트워크가 인터넷에 액세스하도록 설정되어 있음을 나타냅니다. 이는 공개 서버에 도달할 수 있는 실제 기능이 아니라 설정에 관한 것입니다. 예를 들어, 네트워크는 인터넷에 액세스하도록 설정할 수 있지만, 종속 포털의 영향을 받을 수 있습니다.

    일반적으로 이동통신사의 셀룰러 네트워크에는 INTERNET 기능이 있지만, 로컬 P2P Wi-Fi 네트워크에는 없습니다. 실제 연결은 NET_CAPABILITY_VALIDATED를 참고하세요.

  • NET_CAPABILITY_NOT_METERED: 이 기능은 네트워크에 데이터 전송량 제한이 없음을 나타냅니다. 사용자가 금전적 비용, 데이터 한도 또는 배터리/성능 문제로 인해 이 연결의 과도한 데이터 사용량에 민감한 경우 네트워크는 데이터 전송량 제한 있음으로 분류됩니다.

  • NET_CAPABILITY_NOT_VPN: 이 기능은 네트워크가 가상 사설망(VPN)이 아님을 나타냅니다.

  • NET_CAPABILITY_VALIDATED: 이 기능은 네트워크가 마지막으로 프로브되었을 때 공개 인터넷에 실제로 액세스할 수 있도록 확인되었음을 나타냅니다. 종속 포털을 지원하는 네트워크나 도메인 이름 확인을 제공하지 않는 네트워크는 이 기능을 지원하지 않습니다. 이 시스템은 실제로 액세스를 제공하는 네트워크에 관해 알려줄 수 있는 가장 근접한 시스템이지만, 확인된 네트워크는 원칙적으로 여전히 IP 기반 필터링 또는 약한 신호와 같은 문제로 인해 갑자기 연결 손실이 발생할 수 있습니다.

  • NET_CAPABILITY_CAPTIVE_PORTAL: 이 기능은 네트워크가 마지막으로 프로브되었을 때 종속 포털이 있는 네트워크로 확인되었음을 나타냅니다.

좀 더 전문화된 앱에서 관심을 가질만한 다른 기능도 있습니다. 자세한 내용은 NetworkCapabilities.hasCapability(int)의 매개변수 정의를 읽어보세요.

네트워크의 기능은 언제든지 변경될 수 있습니다. 시스템에서 종속 포털을 감지하면 사용자가 로그인하도록 초대하는 알림을 표시합니다. 이 작업이 실행되는 동안 네트워크에 NET_CAPABILITY_INTERNETNET_CAPABILITY_CAPTIVE_PORTAL 기능은 있지만, NET_CAPABILITY_VALIDATED 기능은 없습니다. 사용자가 작업을 실행하고 종속 포털 페이지에 로그인하면 기기는 공개 인터넷에 액세스할 수 있고 네트워크는 NET_CAPABILITY_CAPTIVE_PORTAL 기능 대신 NET_CAPABILITY_VALIDATED 기능을 사용합니다. 마찬가지로, 네트워크 전송은 동적으로 변경될 수 있습니다. 예를 들어, VPN은 셀룰러에서 Wi-Fi로 기본 네트워크를 전환하는 등 방금 인식된 더 빠른 네트워크를 사용하도록 자체적으로 재구성할 수 있습니다. 이 경우 네트워크는 TRANSPORT_CELLULAR 전송 대신 TRANSPORT_WIFI 전송을 사용하지만, TRANSPORT_VPN 전송은 유지합니다.

네트워크 이벤트 수신 대기

네트워크 이벤트를 알아보려면 NetworkCallback 클래스를 ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback)ConnectivityManager.registerNetworkCallback(NetworkCallback)과 함께 사용합니다. 이 두 가지 방법은 서로 다른 용도로 사용됩니다.

모든 Android 앱에는 기본 네트워크가 있습니다. 기본으로 사용할 네트워크는 시스템에서 결정합니다. 시스템은 일반적으로 데이터 전송량 제한이 있는 네트워크보다 무제한 네트워크를, 느린 네트워크보다 빠른 네트워크를 선호합니다. 앱에서 네트워크 요청이 발생하면(예: HttpsURLConnection) 시스템은 기본 네트워크를 사용하여 이 요청을 처리합니다. 앱은 다른 네트워크에서도 트래픽을 전송할 수 있습니다. 자세한 내용은 추가 네트워크를 참고하세요.

기본 네트워크로 설정된 네트워크는 앱의 전체 기간 중 언제든지 변경될 수 있습니다. 일반적인 예로는 활성화되고 무제한이며 셀룰러보다 빠르다고 알려진 Wi-Fi 액세스 포인트의 범위 내에 있는 기기를 들 수 있습니다. 그러면 기기에서 이 액세스 포인트에 연결하고 모든 앱의 기본 네트워크를 새로운 Wi-Fi 네트워크로 전환합니다.

새로운 네트워크가 기본값이 되면 앱이 여는 새 연결은 모두 이 네트워크를 사용합니다. 어느 시점이 지나면, 이전의 기본 네트워크에 남아있는 모든 연결이 강제 종료됩니다. 앱에서 기본 네트워크가 변경되는 시점을 알려면, 다음과 같이 기본 네트워크 콜백을 등록해야 합니다.

Kotlin

connectivityManager.registerDefaultNetworkCallback(object : ConnectivityManager.NetworkCallback() {
    override fun onAvailable(network : Network) {
        Log.e(TAG, "The default network is now: " + network)
    }

    override fun onLost(network : Network) {
        Log.e(TAG, "The application no longer has a default network. The last default network was " + network)
    }

    override fun onCapabilitiesChanged(network : Network, networkCapabilities : NetworkCapabilities) {
        Log.e(TAG, "The default network changed capabilities: " + networkCapabilities)
    }

    override fun onLinkPropertiesChanged(network : Network, linkProperties : LinkProperties) {
        Log.e(TAG, "The default network changed link properties: " + linkProperties)
    }
})

자바

connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback() {
    @Override
    public void onAvailable(Network network) {
        Log.e(TAG, "The default network is now: " + network);
    }

    @Override
    public void onLost(Network network) {
        Log.e(TAG, "The application no longer has a default network. The last default network was " + network);
    }

    @Override
    public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
        Log.e(TAG, "The default network changed capabilities: " + networkCapabilities);
    }

    @Override
    public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
        Log.e(TAG, "The default network changed link properties: " + linkProperties);
    }
});

새 네트워크가 기본값이 되면 앱에서 새 네트워크의 onAvailable(Network) 호출을 수신합니다. onCapabilitiesChanged(Network,NetworkCapabilities), onLinkPropertiesChanged(Network,LinkProperties) 또는 둘 다 구현하여 연결의 변경사항에 적절하게 반응해야 합니다.

registerDefaultNetworkCallback()에 등록된 콜백의 경우 onLost()는 네트워크가 기본 네트워크로 설정된 상태를 상실했다는 의미입니다. 연결이 해제된 상태인지 확실하지 않습니다.

NetworkCapabilities.hasTransport(int)를 쿼리하여 기본 네트워크가 사용 중인 전송 방법을 알아볼 수 있지만, 이는 네트워크 대역폭 또는 한도 측정을 위한 프록시로 적합하지 않습니다. 앱은 Wi-Fi가 항상 무제한이고 언제나 셀룰러보다 더 나은 대역폭을 제공한다고 가정해서는 안 됩니다. 대신, NetworkCapabilities.getLinkDownstreamBandwidthKbps()를 사용하여 대역폭을 측정하고 NET_CAPABILITY_NOT_METERED 인수로 NetworkCapabilites.hasCapability(int)를 호출하여 데이터 전송량에 제한이 있는지 확인해야 합니다. 자세한 내용은 NetworkCapabilities 및 LinkProperties를 참고하세요.

기본적으로 콜백 메서드는 ConnectivityManager에서 사용하는 별도의 스레드인 앱의 연결 스레드에서 호출됩니다. 콜백 구현에서 더 많은 작업을 해야 한다면 ConnectivityManager.registerDefaultNetworkCallback(NetworkCallback, Handler)의 변형을 사용하여 별도의 작업자 스레드에서 콜백을 호출합니다.

더 이상 콜백을 사용하지 않는다면 ConnectivityManager.unregisterNetworkCallback(NetworkCallback)을 호출하여 콜백을 등록 취소하세요. 기본 활동의 onPause()는 이를 처리하기 좋은 장소이며, 특히 onResume()에 콜백을 등록한 경우 더 그렇습니다.

추가 네트워크

기본 네트워크가 대부분의 앱과 관련된 유일한 네트워크이지만, 일부 앱은 사용 가능한 다른 네트워크에 관심이 있을 수 있습니다. 이러한 네트워크를 찾기 위해 앱은 요구사항에 맞는 NetworkRequest를 빌드하고 ConnectivityManager.registerNetworkCallback(NetworkRequest, NetworkCallback)을 호출합니다. 프로세스는 기본 네트워크를 수신하는 것과 유사합니다. 지정된 시점에 앱에 적용되는 기본 네트워크가 하나만 있을 수 있지만, 추가 네트워크의 주요 차이점은 이 버전을 사용하면 앱에서 사용할 수 있는 모든 네트워크를 동시에 볼 수 있다는 것입니다. 따라서, onLost(Network) 호출은 네트워크가 더 이상 기본이 아니라는 것이 아니라 영구적으로 연결 해제되었다는 의미입니다.

앱은 NetworkRequest를 빌드하여 수신 대기하려는 네트워크의 종류를 ConnectivityManager에 알립니다. 예를 들어, 앱이 무제한 인터넷 연결에만 관심이 있는 경우 다음과 같이 합니다.

Kotlin

val request = NetworkRequest.Builder()
  .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
  .addCapability(NET_CAPABILITY_INTERNET)
  .build()

connectivityManager.registerNetworkCallback(request, myNetworkCallback)

자바

NetworkRequest request = new NetworkRequest.Builder()
  .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
  .addCapability(NET_CAPABILITY_INTERNET)
  .build();

connectivityManager.registerNetworkCallback(request, myNetworkCallback);

이렇게 하면, 앱에서 시스템의 무제한 네트워크와 관련된 모든 변경사항을 수신할 수 있습니다.

기본 네트워크 콜백의 경우 앱의 Connectivity 스레드를 로드하면 안 되므로 Handler를 허용하는 registerNetworkCallback(NetworkRequest, NetworkCallback, Handler) 버전이 있습니다. 콜백을 더 이상 사용하지 않는다면 ConnectivityManager.unregisterNetworkCallback(NetworkCallback)을 호출하세요. 앱은 동시에 여러 네트워크 콜백을 등록할 수 있습니다.

편의를 위해 NetworkRequest 객체에는 다음을 포함하여 대부분의 앱에서 필요한 공통 기능이 포함되어 있습니다.

앱을 작성할 때는 기본값을 확인하여 사용 사례와 일치하는지 확인하고 이러한 기능이 없는 네트워크에 관한 앱에 알림을 전송해야 한다면 이러한 기본값을 삭제해야 합니다. 반대로, 앱이 상호작용하지 않는 네트워크 연결에 변경사항으로 호출되지 않도록 앱에 기능을 추가해야 합니다.

예를 들어, 앱에서 MMS 메시지를 전송해야 한다면 앱에 MMS를 전송할 수 없는 모든 네트워크를 전달하지 않도록 앱의 NetworkRequestNET_CAPABILITY_MMS를 추가하거나 앱에서 P2P Wi-Fi 연결에만 관심이 있는 경우 TRANSPORT_WIFI_AWARE를 추가해야 합니다. NET_CAPABILITY_INTERNETNET_CAPABILITY_VALIDATED는 인터넷상의 서버로 데이터를 전송하는 기능에 관심이 있는 경우에 유용합니다.

이 섹션에서는 앱이 기본 콜백과 일반 콜백 모두 현재 모바일 연결이 있는 기기에 등록할 때 앱이 얻을 수 있는 콜백 시퀀스를 설명합니다. 이 예에서는 기기가 양호한 Wi-Fi 액세스 포인트에 연결한 다음 연결 해제합니다. 또한, 이 섹션에서는 기기가 모바일 데이터 상시 사용이 설정되어 있다고 가정합니다.

타임라인은 다음과 같습니다.

  1. 앱에서 registerNetworkCallback()을 호출하면 셀룰러 네트워크만 사용할 수 있으므로 콜백은 즉시 이 네트워크의 onAvailable(), onNetworkCapabilitiesChanged(), onLinkPropertiesChanged()에서 호출을 수신합니다. 다른 네트워크를 사용할 수 있었다면 앱은 다른 네트워크의 콜백도 수신했을 것입니다.

    네트워크 콜백 이벤트 등록과 이벤트에서 트리거하는 콜백을 보여주는 상태 다이어그램
    그림 1. registerNetworkCallback() 호출 후 앱 상태

  2. 그런 다음 앱에서 registerDefaultNetworkCallback()을 호출합니다. 셀룰러 네트워크가 기본 네트워크이므로 기본 네트워크 콜백은 셀룰러 네트워크의 onAvailable(), onNetworkCapabilitiesChanged(), onLinkPropertiesChanged() 호출을 수신하기 시작합니다. 기본이 아닌 다른 네트워크가 작동 중이었다면 앱은 기본이 아닌 네트워크의 호출을 수신하지 못했을 것입니다.

    기본 네트워크 콜백 이벤트 등록 및 이벤트에서 트리거하는 콜백을 보여주는 상태 다이어그램
    그림 2. 기본 네트워크를 등록한 후의 앱 상태

  3. 추후 기기가 (무제한) Wi-Fi 네트워크에 연결됩니다. 일반 네트워크 콜백은 Wi-Fi 네트워크의 onAvailable(), onNetworkCapabilitiesChanged(), onLinkPropertiesChanged() 호출을 수신합니다.

    앱이 새 네트워크에 연결될 때 트리거된 콜백을 보여주는 상태 다이어그램
    그림 3. 무제한 Wi-Fi 네트워크에 연결한 후의 앱 상태

  4. 이 시점에서 Wi-Fi 네트워크를 확인하는 데 시간이 걸릴 수 있습니다. 이 경우 일반 네트워크 콜백의 onNetworkCapabilitiesChanged() 호출은 NET_CAPABILITY_VALIDATED 기능을 포함하지 않습니다. 잠시 후, 새 기능에 NET_CAPABILITY_VALIDATED가 포함된 onNetworkCapabilitiesChanged() 호출을 수신합니다. 대부분의 경우는 확인 작업이 빠르게 진행됩니다.

    Wi-Fi 네트워크는 주로 무제한이므로 시스템은 Wi-Fi 네트워크가 확인되면 셀룰러 네트워크보다 Wi-Fi를 선호합니다. Wi-Fi 네트워크가 기본 네트워크가 되므로 기본 네트워크 콜백은 Wi-Fi 네트워크의 onAvailable(), onNetworkCapabilitiesChanged(), onLinkPropertiesChanged() 호출을 수신합니다. 셀룰러 네트워크가 백그라운드로 이동하고 일반 네트워크 콜백은 셀룰러 네트워크의 onLosing() 호출을 수신합니다.

    이 예는 이 기기에서 모바일 데이터가 상시 사용 설정되어 있다고 가정하므로 모바일 네트워크는 연결 해제되지 않습니다. 설정이 사용 중지되면 잠시 후 셀룰러 네트워크가 연결 해제되고 일반 네트워크 콜백은 onLost() 호출을 수신합니다.

    Wi-Fi 네트워크 연결을 확인할 때 트리거된 콜백을 보여주는 상태 다이어그램
    그림 4. Wi-Fi 네트워크 확인 후 앱 상태

  5. 추후 기기가 범위를 벗어났으므로 기기는 갑자기 Wi-Fi에서 연결 해제됩니다. Wi-Fi 연결이 해제되었으므로 일반 네트워크 콜백은 Wi-Fi의 onLost() 호출을 수신합니다. 셀룰러는 새로운 기본 네트워크이므로 기본 네트워크 콜백은 셀룰러 네트워크의 onAvailable(), onNetworkCapabilitiesChanged(), onLinkPropertiesChanged() 호출을 수신합니다.

    Wi-Fi 네트워크 연결이 끊어졌을 때 트리거된 콜백을 보여주는 상태 다이어그램
    그림 5. Wi-Fi 네트워크에서 연결 해제된 후 앱 상태

모바일 데이터 상시 사용 설정이 해제된 경우 Wi-Fi가 연결 해제되면 기기에서 셀룰러 네트워크에 다시 연결을 시도합니다. 그림은 비슷하지만, onAvailable() 호출에는 짧은 추가 지연이 있으며 일반 네트워크 콜백은 셀룰러를 사용할 수 있으므로 onAvailable(), onNetworkCapabilitiesChanged(), onLinkPropertiesChanged() 호출도 수신합니다.

데이터 전송 시 네트워크 사용 제한사항

네트워크 콜백으로 네트워크를 확인할 수 있어도 앱에서 데이터 전송에 네트워크를 사용할 수 있는 것은 아닙니다. 일부 네트워크는 인터넷 연결을 제공하지 않으며(인터넷 연결을 확인하려면 NET_CAPABILITY_INTERNETNET_CAPABILITY_VALIDATED 참고) 일부 네트워크는 권한이 있는 앱으로 제한될 수 있습니다.

백그라운드 네트워크를 사용할 때도 권한 확인이 적용됩니다. 앱에서 백그라운드 네트워크를 사용하려면 CHANGE_NETWORK_STATE 권한이 필요합니다. 이 권한을 가진 앱은 기기가 Wi-Fi 네트워크에 연결되어 있을 때 현재 사용하지 않는 네트워크(예: 셀룰러 네트워크)를 표시하도록 시스템에 요청할 수도 있습니다. 이러한 앱은 네트워크가 표시될 때 호출되는 NetworkCallback으로 ConnectivityManager.requestNetwork(NetworkRequest, NetworkCallback)을 호출합니다.