본 블로그는 페이스북 댓글을 지원합니다.
게임처럼 대부분의 의미있는 활동을 foreground activity에서 진행하는 앱이 아니라, 주기적으로 서버 자원을 관찰하여
변동사항이 있을 경우 이를 사용자에게 notify 해줘야하는 앱을 만들어야할 때가 있다.
이럴 경우 android.app.Service를 상속하여 서비스를 만들고 이를 manifest 파일에 추가하고 적절한 시점에
Activity.startService를 불러 서비스를 띄우면 된다.
순진한 접근으로 이를 해결하려하면 Service.onStart 메서드에서 Thread를 하나 만들고 해당 Thread 속에서 주기적으로 서버자원을 체크하다 변동이 있을 경우 notification을 주고, onDestroy에서 스레드를 종료시키면 끝이다.
그러나
폰별로 시간 차이가 있을 수 있겠으나, 내 Motorola Droid에서는 스크린이 꺼지고 폰이 IDLE 상태가 된지 15분이
지나면 배터리 절약을 위해 Wi-Fi를 비활성화 한다. 효율적인 방법이라고 생각한다. 하지만 개발자가 원하는 것은
아니다. 15분동안 주고 받은 패킷이 전혀 없어야 꺼지는 게 아니라 패킷을 계속 주고 받든 말든 어찌됐든 15분 후면
Wi-Fi가 비활성화되고 2G 혹은 3G로 절체되기 때문이다.
만약 당신이 원하는 것이 매 1분마다 HTTP 연결을 만들어 자원을 확인하고 연결을 종료하는 것이라면 크게 문제가
안될지도 모른다. 그저 2G/3G 망으로 바뀌어 재요청을 날리는 것이므로, 네트워크 절체도중 요청을 날리지만 않으면
아무런 문제없이 계속 요청을 보내고 응답을 받을 수 있기 때문이다.
그런데 2G/3G를 사용하면 배터리를 적게 소모하는 대신 ‘돈’을 쓰게 된다. 사용자는 이것을 원하지 않을 수도 있다.
이런 경우 android.net.wifi.WifiManager.WifiLock를 사용하여 서비스가 활성화중일 때 WifiLock을 잡아 Wi-Fi를
끊기지 않게 할 수 있다. 물론 더 많은 배터리를 소모하기 때문에 사용자에게 알려줘야할 필요가 있을 것이다.
(Setting 등으로)
문서에도 나와있지만, 여러분이 만든 앱이 락을 잡지 않더라도 다른 앱이 락을 잡고 있으면 Wi-Fi는 끊기지 않는다.
reference count라고 보는 편이 좋겠다. OS가 WifiLock reference acount를 주시하고 있다가 0보다 크면 끄지 않고 0이 되면 끄고.
여기까지하면 다 된 기분이 들지도 모른다. 아니다. 30분~1시간동안 사용자의 활동이 없으면 배터리 절약을 위해 CPU도
동작하지 않게 된다. 이럴땐 android.os.PowerManager.WakeLock이 필요하다. 백그라운드 서비스의 경우 스레드가 계속 돌기만 하면 되므로 스크린이 꺼지지 않도록 SCREEN_BRIGHT_WAKE_LOCK, SCREEN_DIM_WAKE_LOCK 같은 것을 잡을 필요는 없고, 그저 PARTIAL_WAKE_LOCK 을 잡아 CPU 동작이 멈추는 것만 방지하면 된다.
그런데 이것들이 왜 ‘주의사항‘ 인걸까?
안드로이드 폰에 기본탑재된 Google Talk이나 각종 background sync들을 비활성화하지 않았다면 당신이 CPU WakeLock을 잡지않아도 Google Talk이나 다른 녀석들이 잡아주기 때문에, 테스트 할 때 이런 사항들을 알아내기 어렵기 때문이다.
이런 것들을 다 적용하더라도 여전히 주의할 점이 있다. 당신이 만든 앱만 깔면 배터리가 미친듯이 빨리 소모된다고
고객이 화를 낼지도 모르니 Setting에서 이러한 사항들을 고객이 조정가능하게 해줘야 함을.
물론 android.permission.WAKE_LOCK이 필요함을 잊지 마시고.
2010-06-18 16:40 에 Jeong, Bong su님이 마지막으로 수정본 블로그는 페이스북 댓글을 지원합니다.
http://ryuhyunjin.com ......................... grosh@naver.com by 커널제로 |
||