넥서스(롤리팝)에서 WiFi 연동 개발시 유의사항

|

안드로이드 개발시, 혹은 스마트폰을 사용하면서 기본적으로 알고 있는 내용이,

wifi가 연결되어 있으면 모바일(3G/LTE) 네트워크보다 wifi가 우선되어 사용된다는 점이고,

안드로이드 4.x 까지도 이 내용이 기본이었는데...


이 내용이 Android L (롤리팝)이 되면서 변경이 되었다.


아직까지 확인한 내용으로는 넥서스 시리즈(레퍼런스...)에서만 나타나는 현상인데,

인터넷이 안되는 wifi와 인터넷이 되는 모바일 네트워크가 연결되어있는 상태일 때,

기존처럼 다른 조작 없이 소켓을 열거나 URL.openConnection() 등을 시도하면

wifi로 붙는것이 아니라 모바일 네트워크로 붙게 된다.


이게 문제가 되는게 무엇이냐면

요즘 IoT라 하여 가전기구 등에 연결을 할 때, 그 기기 자체가 wifi AP가 되어 접속하는 경우가 많은데,

이 경우라면 당연히 인터넷이 안되는 AP이고, 그러면 기존 코드로는 통신을 못하는 상황이 되어버린다.


그럼 이걸 어떻게 해결해야 하나.


API Level 21부터 추가된 클래스 중 NetworkRequest 라는게 있다.

그리고 ConnectivityManager 쪽에 이와 관련하여 추가된 메소드가 있다.


프로세스 내 기본 네트워크를 ConnectivityManager.setProcessDefaultNetwork()를 통해 고정시킬 수 있는데,

여기서 인자로 받는 게 Network 인스턴스다.


Network 인스턴스는 기기 내 인터페이스를 지칭하는것으로 봐도 무관할 듯 싶은데,

이게, 직접적인 생성자가 없다.


이 인스턴스를 받으려면 ConnectivityManager의 requestNetwork()나 registerNetworkCallback()로 등록된

리스너를 통해 인스턴스를 받아올 수 있다.


(일반 모바일 네트워크 + 인터넷이 안되는 wifi) 환경에서 wifi로 연결하고 싶은 경우엔 아래처럼 하면 된다.



기존에 소켓으로 사용했던거라면 Network.bindSocket()이나 Network.getSocketFactory()를 사용하고,

URL.openConnection() 으로 사용했던거라면 Network.openConnection()을 사용하면 된다.


requestNetwork()와 registerNetworkCallback()의 차이는,

문서상으로 봤을 땐 NetworkRequest에 추가한 조건들의 AND결합이냐, OR 결합이냐의 차이인 것 같은데

동작은 생각대로 되지 않는다...


리스너는 unregisterNetworkCallback()을 통해 해제하거나 프로세스가 죽을때까지 호출되므로

목적에 맞게 취소 및 플래그 처리가 필요하다.


NetworkCallback 에는 onAvailable() 말고도, onLost, onLinkPropertiesChanged(), onCapabilitiesChanged(), onLosing() 의 메소드가 준비되어 있다.



물론, 해당 앱의 타겟 SDK는 21 이상으로 잡아야 하고, 4.x 이하 단말을 지원한다면 SDK_VER 으로 분기를 태워야 함은 당연지사...





구글이 이 기능을 추가한 이유로는,

인터넷이 가능한 네트워크를 선택적으로 사용한다거나,

일정 속도 이하로 떨어지면 다운로드를 중지한다든가(onLinkPropertiesChanged)든가 하는 목적이겠지만...

정상적인 동작은... 글쎄다....


NetworkRequest에 조건을 Transport와 Capability 두가지로 줄 수 있는데,

위에서 예시로 든 상황에서는 (아직까진) 제대로 잡히지만, 그 외의 상황을 만들어 테스트 해보면.....

동작이 생각만큼 제대로 들어오진 않는다.


업링크를 빼놓은 무선공유기로 연결해둔 상태에서 CAPABILITY_INTERNET 으로 요청해도 wifi로 들어온다거나...

인터넷이 가능한 wifi가 연결된 상태에서 TRANSPORT_CELLUAR로 요청하면 아예 안들어온다던가.... 등등...



wifi보다 모바일이 우선시되는 내용도 넥서스에서만 나타나는 현상이다.


삼성 갤럭시S5에서 테스트 해 보면 기존과 동일하게 wifi가 우선되어 처리된다.

LG단말에서는 연결한 wifi가 인터넷이 되지 않으면 그냥 끊어버린다. (신호세기 관련 없이. 환경설정에서 끌 수 있는듯.)




제조사마다, 모델마다 동작이 달라서

아예 모바일네트워크의 Network instance, wifi의 Network instance를 받아놓고

명시적으로 쓰는게 확실할 것 같다.

And