이번 포스팅에서는 단말의 인터넷 연결상태를 체크하는 법에 대해 알아보도록 하겠습니다.
앱을 만들다보면 WIFI를 사용할 수 있는 환경에서 대용량 데이터를 다운로드하도록 하는 등의 처리를 위해 단말의 인터넷 연결상태를 체크해야 할 일이 있습니다.
이때 ConnectivityManager 를 사용하면 단말이 어떤 접속환경을 통해 인터넷에 연결되어 있는지 확인할 수 있습니다.
권한추가
인터넷에 접근하고 네트워크 상태를 가져오기 위해 AndroidManifest.xml
에 다음 권한을 추가합니다.
1
2
<uses-permission android:name= "android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name= "android.permission.INTERNET" />
네트워크 타입 확인
우선은 단말이 연결된 네트워크가 와아파이인지 셀룰러인지 확인하는 코드를 써 보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private fun getNetworkType ( context : Context ): String {
val connMgr =
context . getSystemService ( Context . CONNECTIVITY_SERVICE ) as ConnectivityManager
if ( Build . VERSION . SDK_INT >= Build . VERSION_CODES . M ) {
val nw = connMgr . activeNetwork ?: return "NO_CONNECTION"
val actNw = connMgr . getNetworkCapabilities ( nw ) ?: return "NO_CONNECTION"
return when {
actNw . hasTransport ( NetworkCapabilities . TRANSPORT_WIFI ) -> "WIFI_STATE"
actNw . hasTransport ( NetworkCapabilities . TRANSPORT_CELLULAR ) -> "CELLULAR_STATE"
actNw . hasTransport ( NetworkCapabilities . TRANSPORT_ETHERNET ) -> "ETHERNET_STATE"
else -> "NO_CONNECTION"
}
} else {
val nwInfo = connMgr . activeNetworkInfo ?: return "NO_CONNECTION"
return nwInfo . typeName
}
}
기본은 ConnectivityManager
인스턴스를 만들고 그 인스턴스로부터 네트워크 타입을 가져오는 방식입니다. API Level 23 마시멜로우까지는 connMgr.activeNetworkInfo 를 통해 NetworkInfo 인스턴스를 만든 뒤 typeName 프로퍼티로 네트워크 타입을 문자열 형태로 확인할 수 있었습니다.
그러나 마시멜로우 이상에서는 ConnectivityManager
의 activeNetwork 프로퍼티로 Network 인스턴스를 받아옵니다. 이 인스턴스를 getNetworkCapabilities 로 전달하여 NetworkCapabilities 의 인스턴스를 얻은 뒤 hasTransport 를 실행하여 네트워크 타입을 가져오게 됩니다. 이 시점에서 접속이 확인되지 않을 경우 네트워크에 접속되지 않은 것입니다.
네트워크 접속여부 확인
NetworkInfo 인스턴스의 isConnected 메소드를 사용하면 현재 인터넷에 접속되어있는지를 확인할 수 있습니다. 그런데 이 메소드로는 버스나 공항에서 접속할 수 있는 인증이 필요한 와이파이에 대해서는 인증이 되지 않아서 실제로는 와이파이를 사용할 수 없어도 true를 반환하게 됩니다.
따라서 실제로 임의의 주소에 핑을 날려보는게 더 확실합니다. 구글에서는 이렇게 네트워크 접속을 확인할 때 쓰라고 Network Portal Detection 서비스 를 제공하고 있는데요, 그 주소는 다음과 같습니다.
http://clients3.google.com/generate_204
이 주소로 접속에 성공하면 HTTP 204 No Content 를 반환합니다. 204 응답이 돌아오면 단말이 인터넷을 사용할 수 있는 상태라는 거지요.
우선은 http://clients3.google.com/generate_204 에 접속하여 response code를 받아오는 함수를 작성합니다. 네트워크에 접속해야 하므로 비동기로 처리하기 위해 Thread 를 상속받도록 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private class CheckConnection ( private val host : String ) : Thread () {
var isSuccess = false
override fun run () {
var urlConnection : HttpURLConnection ? = null
try {
urlConnection = URL ( host ). openConnection () as HttpURLConnection
urlConnection . setRequestProperty ( "User-Agent" , System . getProperty ( "http.agent" ))
urlConnection . connectTimeout = 1000
urlConnection . connect ()
val responseCode = urlConnection . responseCode
if ( responseCode == 204 ) {
isSuccess = true
}
} catch ( e : Exception ) {
e . printStackTrace ()
}
urlConnection ?. disconnect ()
}
}
다음은 CheckConnection
을 실행시켜주면 되겠죠. 스레드를 시작하고 204 응답이 돌아왔다면 true를 반환하는 함수를 만들어줍니다. 메인스레드에서 작업이 끝날때까지 대기하도록 하기 위해 join 을 추가로 실행시켜 줍니다.
1
2
3
4
5
6
7
8
9
10
11
private fun isOnline (): Boolean {
val cc = CheckConnection ( "http://clients3.google.com/generate_204" )
cc . start ()
try {
cc . join ()
return cc . isSuccess
} catch ( e : Exception ) {
e . printStackTrace ()
}
return false
}
이렇게 해서 단말의 네트워크 상태를 체크하는 법에 대해 알아보았습니다.
VIDEO