Android Network Binding: Switching Wi-Fi and Cellular
이 글은 Tistory에서 이전된 포스팅입니다. 원본은 여기에서 확인할 수 있습니다.
Connect vs Bind
Connect: 안드로이드는 Wi-Fi와 셀룰러 네트워크를 동시에 연결할 수 있다.
Bind: 연결된(사용 가능한) 네트워크 중 하나를 프로세스에 바인딩하여 해당 네트워크를 사용할 수 있다.
프로세스가 사용하는 네트워크는 바인딩된 네트워크이며, 바인딩하지 않으면 Android 시스템이 적절한 네트워크를 선택한다.
Connect (requestNetwork)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
val specifier = WifiNetworkSpecifier.Builder()
.setSsid(ssid)
.setWpa2Passphrase(password)
.build()
val request = NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
.setNetworkSpecifier(specifier)
.build()
val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val hasResponded = AtomicBoolean(false)
deviceNetworkCb = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
if (hasResponded.compareAndSet(false, true)) {
timeoutHandler.removeCallbacks(timeoutRunnable!!)
deviceNetwork = network
bindProcessToNetworkIfNeeded(network) { msg -> setMessage(msg) }
setMessage("✅ 연결 성공")
}
}
override fun onUnavailable() {
if (hasResponded.compareAndSet(false, true)) {
timeoutHandler.removeCallbacks(timeoutRunnable!!)
setMessage("❌ 연결 실패")
}
}
}
cm.requestNetwork(request, deviceNetworkCb!!)
Connect/Bind 모두 ConnectivityManager 객체를 통해 실행할 수 있다.
requestNetwork()는 요청할 네트워크와 콜백 함수를 지정할 수 있다.
요청한 네트워크를 사용할 수 없는 경우, 콜백은 호출되지 않는다.
SSID와 PassPhrase를 지정해 특정 Wi-Fi에 연결할 수도 있고,
인터넷이 가능한 네트워크만 요청하도록 옵션을 설정할 수도 있다.
Bind
1
2
3
4
5
private fun bindProcessToNetworkIfNeeded(bindNetwork: Network?, setMessage: (String) -> Unit) {
...
val cm = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val success = cm.bindProcessToNetwork(bindNetwork)
...
bindProcessToNetwork()는 Bind 동작에 해당한다.
requestNetwork()만 호출하고 바인딩하지 않으면, Android 시스템은 가장 적절한 네트워크를 자동으로 선택해 사용한다.
예를 들어, requestNetwork()로 Wi-Fi에 연결을 요청했더라도 해당 Wi-Fi에 인터넷 연결이 없으면, 시스템은 셀룰러 네트워크를 기본으로 사용한다.
Example
https://github.com/cornpip/android_network_bind_example
Wi-Fi와 셀룰러 네트워크 간의 바인딩을 전환하며 API 요청을 테스트해보자.
테스트 환경에서 Wi-Fi는 인터넷이 연결되지 않은 AP이고, 셀룰러는 인터넷이 가능한 네트워크이다.
테스트 흐름
- 인터넷이 되지 않는 Wi-Fi에 requestNetwork()로 연결한다.
- 셀룰러와 Wi-Fi를 바꿔가면 binding 한다.
- API 요청을 실행한다.
결과
- Wi-Fi에 바인딩된 상태에서는 API 요청이 실패한다.
- 셀룰러에 바인딩된 상태에서는 API 요청이 성공한다.
