본문 바로가기

소프트웨어/Android/Java/Ndk

Android] Wifi Connected State와 관련해..

기기간 Network Change 변화

Wifi가 연결되면 Server와 통신을 위해 Socket을 연결한다. 연결을 위해서는 완벽하게 Wifi가 연결된 상태가 되야한다. 그런데 Network Change StateReceive하는 Filter를 갖는 ReceiverNetwrokStateChange Action을 받았을 때 Network의 연결상태가 기기별로 천차 만별이었다. 일부 삼성기기는 'Connected' State2~4번 받고 연결하였고, 타 회사의 기기에서는 'Connecting' State에서 연결 되버리는 상황도 발생하였다. 그래서 WifiModule 제조사마다 받는 수치가 다르다고 생각해서 이 부분에서는 Thread Timer를 돌려서 일정시간동안 더 이상 NetworkState Receving을 하지 않으면 Wifi Connection으로 판단하고 Socket을 연결하게 만들었다. 물론 결과적으로 이 방식을 사용하면 아주 특이한 경우가 아니면 딜레이가 생기지만 Socket이 잘 연결되었다. 그러나 얼마전 Network Change 변화를 받는 방법을 새로 알게되어 프로젝트에 적용하게 되었다.

 

원래 사용하던 방법은 아래와 같다. 아래의 과정은 BroadCastReceiveronReceive()를 수행하면서 진행되는 과정이다.

 

1. 전달된 IntentAction을 토대로 Wifi ModuleON/OFF상태를 판단하고 OFFON Action이 전달 될 때까지는 작업을 수행하지 않는다.

(이 때는 WifiManagerWIFI_STATE_CHANGED_ACTION으로 Wifi ModuleON/OFF상태변화를 체크한다)

2. WIFI_STATE_CHANGED_ACTIONWIFI_STATE_ENABLED가 되면 ON 상태이므로 이 후 Receving 부터는 Network의 변화를 감지해서 WifiConnection 되기를 기다린다. 이 때 같이 검사되어야 하는 조건은 NetworkInfo ClassType을 확인해서 현재 변화된 NetworkTYPE_WIFI에 관한게 맞는지에 관한 것이다.

3. 이 후 NETWORK_STATE_CHANGED_ACTIONNetworkInfo ClassgetState() 매서드를 통해 StateCONNECTED가 되면 연결이 완료되었다고 판단한다.

 

여러 방법을 시도해보면서 위의 방법이 깔끔하다고 판단되서 계속 개발을 했다. 그런데 어째서인지 3번 순서에서 예상대로라면 'DISCONNECT->CONNECTING->CONNECTED'가 검사되야 하는데 실제로 Log를 출력해보면 굉장히 달랐다. 제조사 별로도 CONNECTING만 불리고 접속되는 기기도 있었고 CONNECTED만 여러번 불리는 기기도 있었다. 그래서 대체로 CONNECTED에서 연결되는 것을 관찰하여 한번 CONNECTED가 들어오면 약 수 초동안 다시 CONNECTED가 불리는지를 Thread Timer로 체크하여 판단하는 방식으로 구현을 했었다. 결론적으로는 연결이 됬지만 제대로된 방법이 아닌 것 같아 여러 방법을 찾아보던 중 지인으로부터 분명 내부적으로 체크하는 다른 방법이 있을거라는 피드백을 받아서 프로젝트 완료 며칠 전에 새로운 방법을 찾기 시작했고 발견해서 적용하였다.

새롭게 적용한 방식은 아래와 같다.

1. (동일) 전달된 IntentAction을 토대로 Wifi ModuleON/OFF상태를 판단하고 OFFON Action이 전달 될 때까지는 작업을 수행하지 않는다.

(이 때는 WifiManagerWIFI_STATE_CHANGED_ACTION으로 Wifi ModuleON/OFF상태변화를 체크한다)

2. 이전 방법과는 다르게 NETWORK_STATE_CHANGED_ACTION을 바로 검사한다. MOBILE Type의 신호이건, 3g/4g의 신호이건, Wifi Type의 신호이건 무조건 다 받은 후

3. 전달받은 Intent에서 getParcelableExtra()매서드를 통해서 NetworkInfo를 전달받는다. 이 때 매서드의 입력변수는 WifiManager.EXTRA_NETWORK_INFO로서 따로 WIFI STATE인지 검사를 하지 않아도 된다. 전달받는 값은 Parcelable value 형태이다. (이전에는 NetworkInfoConnectivityManagergetNetworkInfo() 매서드를 통해 전달받았다)

4. NetworkInfoisConnected()함수를 통해서 CONNECTED STATE를 받으면 실제로 Wifi가 연결된 상태로 들어간다.

 

정확하게 연결될때만 CONNECTED가 날라오기 때문에, 위와 같은 방법을 사용해서 접속완료를 판단하고 소켓에 연결하였다.





실제 적용된 소스 부분이다. 말은 길었는데 코드는 짧다.

여기서 잡다한건 볼 필요 없고 intent에서 getParcelableExtra() 부분만 보면된다. 저렇게 갖고온 networkInfo는 완벽하게 WifiModule이 AP와 Connected 되었을 때만 Connected State를 return한다.