Android2014. 1. 24. 15:01

화면꺼짐 상태에서 GCM 메시지 수신 안되는 문제



갑자기 잘 되던 GCM 메시지 수신이 화면이 잠긴(꺼진, Screen Off)상태에서 수신이 안되는 현상이 발생했다.

화면을 켜면 그때 바로 수신이 된다. 정확히 말하면 화면을 켜고 잠금화면을 풀면 그때 바로 수신이 된다.

또한, 다른 스마트폰에서는 잘되기도 한다. 이유가 뭘까?


그 이유는 GCM을 구글쪽에 발송하는 중계 서버에 문제였는데 GCM을 구글 GCM서버로 발송할 때 "delay_while_idle" 이라는 옵션이 있다. 이 옵션의 Default 값이 안드로이드4.0 이전에는 false였다가 4.0부터 true로 바뀌었기 때문이다. (문제가 발생한 단말기의 버전은 4.1.2 입니다.)


관련해서 안드로이드 공식페이지에서 내용을 찾아봤다.


If the device is connected but idle, the message will still be delivered right away unless the delay_while_idle flag is set to true. Otherwise, it will be stored in the GCM servers until the device is awake.  


dealy_while_idle 옵션은 "true" 또는 "false" 값에 따라 수신되는 동작을 변경할 수 있는데, 만약, false로 설정하면 화면이 꺼진 후 스마트폰이 idle상태가 된 상태에서도 GCM은 바로 수신이 되지만, true로 설정하면 GCM 서버에 저장되었다가 스마트폰이 켜질 때(awake) 수신이 된다.


조금 더 내용을 살펴보면...


If the device is not connected to GCM, the message will be stored until a connection is established (again respecting the collapse key rules). When a connection is established, GCM will deliver all pending messages to the device, regardless of the delay_while_idle flag. If the device never gets connected again (for instance, if it was factory reset), the message will eventually time out and be discarded from GCM storage. The default timeout is 4 weeks, unless the time_to_live flag is set.


스마트폰이 GCM서버에 연결되어 있지 않으면 메시지는 연결이 될때까지 저장되고, 이후에 연결이 완료되면 GCM서버는 그때 미루고 있었던 메시지를 스마트폰으로 전달하게 된다. 중요한 것은 이 과정에서 dealy_while_idle 옵션이 어떻게 되어 있는지 상관없이 동작을 한단다. 스크린을 끈 상태에서 테스트했을 때, 계속 수신이 안되다가도 한 번씩 수신이 되기도 했는데 OS 내부에서 주기적으로 GCM서버에 연결을 하는 동작이 있는 것으로 추측만 했는데 바로 이 내용인가 싶다. 이건 그저 추측이다. (혹시 아시는 분 계시면 명쾌한 답 부탁드립니다. ^^) 


만약, 스마트폰이 공장초기화 등으로 인해 GCM 서버에 더이상 연결을 하지 않으면 4주간 유지했다가 이후에 "time out"이 되어 소멸됩니다. 이 time out 시간은 "time_to_live"옵션으로 변경이 가능하다. (테스트까지는 안했음)


그런데, delay_while_idle이란 옵션이 왜 존재하고 왜 default값을 false에서 true로 변경을 한걸까?


GCM will usually deliver messages immediately after they are sent. However, this might not always be possible. For example, the device could be turned off, offline, or otherwise unavailable. In other cases, the sender itself might request that messages not be delivered until the device becomes active by using the delay_while_idle flag. Finally, GCM might intentionally delay messages to prevent an application from consuming excessive resources and negatively impacting battery life.


이 내용으로 짐작해보면, 결국 사용자가 스마트폰을 사용하지 않을 때 GCM을 수신받아서 뭔가 작업을 하는 것은 결과적으로 더 많은 리소스와 배터리를 소비하게되는데 이를 방지하기 위해 제공하는 옵션이다. 결국, 사용자가 스마트폰을 보고있지 않은 상황에서 꼭 하지 않아도 되는 기능이라면 잠시 미뤄두라는 거다.


결론

GCM을 전송할 때는 중요한 기능은 delay_while_idle 옵션을 false로, 그렇지 않다면 true로 전송을 하자. 또한, OS별로 Default 값이 다를 수 있으니, GCM 중계 서버(구글꺼 말고 우리꺼)에서 별도의 default 값을 반드시 정하고 서비스하는 것이 맞다.




[참고문서]




Posted by 데브로망스