본문 바로가기
개발/안드로이드

안드로이드 App Widget 이야기

by darksilber 2011. 6. 21.
반응형

Android App Widget Stroy


안드로이드 App Widget 은 바탕화면에 위치한 간단한 어플리케이션입니다. 별거 아닌것 같아도 생각보다 유용한 이 기능은, 경쟁 플랫폼인 iOS4와 비교할 때 가장 눈에 띄는 차이점 중에 하나입니다. (바탕화면에서 바로 날씨를 확인 할 수 있습니다. 올레~) 그런데 이 AppWidget 을 가지고 어플리케이션을 만드는 일은 어째 좀 생소하고, 관련된 자료를 찾기도 쉽지 않습니다. 제 느낌으로는, 고등학교의 수학책으로 생각해보면 마지막에 위치한 공간 도형 단원과 비슷하다고 할까요? 왠만한 안드로이드 교재에서 가장 끝 부분쯤에 위치하고 있어서, 새책 마냥 하얗게 남아있기 일수인 부분입니다.

<이른바 눈길 한번 슥 주고 넘어가버리게 되는 공간도형 단원과 비슷하다고 할까...>


저도 최근에야 위젯 형식으로 구현해야할 어플리케이션이 하나 있어서 손을 대 보았는데, 막연히 상상했던 내용과는 다른 점이 많더군요. 이런 저런 삽질 끝에 이해한 내용을 간단하게 정리해 봅니다.

App Widget 이 뭐지?

정석대로, 안드로이드 개발자 사이트에서 App Widget 에 관해 설명한 내용을 번역해 보았습니다.

"App Widget 은 다른 어플리케이션(예를 들어 홈 화면과 같은)에 포함될 수 있는 작은 어플리케이션 View 이고 주기적으로 업데이트 이벤트를 받습니다. UX 적으로는 위젯이라고 하는데, 개발자들은 App Widget Provider 를 통해 이를 구현할 수 있습니다. 홈 어플리케이션과 같이 App Widget 들을 포함할 수 있는 어플리케이션 컴포넌트를 App Widget Host 라고 부릅니다. 아래의 이미지는 음악 Widget 의 스크린 샷입니다."


음... 개발자 사이트의 내용을 살펴보니, 하여간 바탕화면에 나타나는 작은 어플리케이션을 App Widget 이라고 하는 거 같습니다만은 어째 애매합니다.

사용자 관점에서 바라보는 대신, 개발자 관점으로 생각해 보면 어떨까요? App Widget 은 특별한 형식의 BroadcastReceiver 입니다. 위젯과 관련된 이벤트는 인텐트 형식으로 주고 받으며, 이벤트를 처리한 결과를 연결되어 있는 특정 View 에 반영할 수 있도록 구현된 모듈이라고 할 수 있습니다.

App Widget 의 구성

그렇다면, 일반적인 BroadcastReceiver 와 App Widget 은 구체적으로 어떤 차이점을 갖고 있을까요? App Widget 의 핵심 요소는 AppWidgetProvider 라고 불리는 놈인데, 이 녀석은 몇 가지 정해진 형식을 따르는 좀 특이한 BroadcastReceiver 라고 할 수 있습니다. 차이점은 크게 두 가지입니다.
  • App Widget 의 생명 주기와 관련된 시스템 Intent 를 수신합니다.
  • 위젯에 관한 기본 설정 값을 담고 있는 XML 리소스 경로를 포함합니다.
다음은 실제 App Widget 을 선언하고 있는 안드로이드 메니페스트 파일의 일부 입니다.

<receiver android:name=".TestWidget">
	<intent-filter>
		<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
	</intent-filter>
	<meta-data android:name="android.appwidget.provider"
	   android:resource="@xml/widget_info" />
</receiver>    	

Intent Filter 항목에 APPWIDGET_UPDATE 를 포함하고 있으며, 추가로 meta-data 항목에 '@xml/widget_info' 이라는 특정한 XML 파일을 가리키고 있음을 확인 할 수 있습니다.

<?xml version="1.0" encoding="UTF-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="294dp"
    android:minHeight="72dp"
    android:updatePeriodMillis="86400000"
    android:initialLayout="@layout/main">
</appwidget-provider> 

'@xml/widget_info' 이 나타내는 XML 파일의 내용을 살펴보면 위와 같습니다. 실재 화면상에 위치할 위젯 크기 정보와 화면 구성에 사용하게될 Layout 정보, 그리고 얼마나 자주 update 함수가 호출되어야 하는지에 관한 정보를 담고 있습니다.

즉, App Widget 을 다시 정의 하자면, APPWIDGET_UPDATE 를 처리하며, 위젯을 설정하기 위한 관련 정보를 갖고 있는 BroadcastReceiver 라고 말 할 수 있습니다.

App Widget 은 어떻게 그려지는 걸까?

App Widget 이 무엇이고 어떤 구성 요소를 갖고 있는지 대충 살펴 보았습니다. 하지만 실재로 App Widget 이 어떤식으로 작동하고 있는지에 관해 이해하고자 한다면 한 가지 좀더 자세하게 살펴봐야할 부분이 있습니다.

App Widget 은 어떻게 화면상에 그림을 그릴 수 있을까요?

본적으로 BroadcastReceiver 는 GUI 구성요소를 포함 할 수 없습니다. 또한, 위젯이라는 것이 특정 어플리케이션에 부록 형태로 딸려들어가는 작은 어플리케이션을 말하는 만큼, 일반적인 경우와는 달리 특정 어플리케이션이 일부분만을 점유해서 그림을 그릴 수 있어야 합니다. GUI 를 그릴 수 없는 AppWidgetProvider 와 어떤 위젯이 자신에게 적용될지 알 수 없는어플리케이션 사이에 자리를 잡고, 두 요소간의 연결 고리를 형성해 주는 누군가가 필요한 셈입니다. AppWidgetHost 가 바로 그 역할을 수행합니다.

AppWidgetHost 와 App Widget 그리고 어플리케이션은 꽤나 재미있는 관계를 유지하고 있습니다. 예를 들자면, 어플리케이션은 갑부인 '빌딩 주인', App Widget 은 '세입자', 그리고 마지막으로 'AppWidgetHost' 은 '건물 관리인' 이라고 할 수 있습니다.

<어플리케이션은 자신이 소유하고 있는 화면을 위젯에게 임대해준다.>

이야기는 이런식으로 돌아갑니다. 놀고있는 화면이 아까워진 건물 주 OO씨. 자신이 점유하고 있는 화면 중에 일정 부분을 App Widget 에게 빌려주고 임대료나 벌어볼까 머리를 굴립니다. OO씨는 자신의 화면의 어떤 부분을 빌려줄지만 결정한 후에, 건물 관리업을 전문으로 하는 AppWidgetHost 를 소환합니다. 다음은 세입자를 찾기위해 광고를 할 때 입니다. 이 때, 어플리케이션은 세입자를 찾기위해 전문 광고업자에게 광고를 위탁(App Widget Pickup Activity 를 실행)할 수도 있고, 원한다면 자신이 콕 찝어 직접 적절한 App Widget 을 선정할 수도 있습니다. 세입자가 결정되었다면 다음은 AppWidgetHost 의 역할입니다. AppWidget 과 계약서를 작성한 후 위젯이 요청하는 View 를 생성하고, 국가기관(안드로이드 시스템)에 새로운 임대 계약이 성공적으로 성사 되었음을 보고합니다. 이제 AppWidget 을 사용할 모든 절차가 완료되었음으로, 어플리케이션은 AppWidgetHost 가 생성해준 위젯 View 를 원하는 곳에 표시하면 됩니다.

그런데 이 야이기에는 한 가지 빠져있는 사실이 있습니다. 어떤 이벤트가 발생한 후, 위젯 화면이 업데이트되어야 하는 경우를 생각해 보면 한 가지 문제가 발생합니다. 위젯 관련된 이벤트를 수신한 App Widget Provider 는 해당 사실을 자신을 사용하고 있는 임의의 어플리케이션에게 알려야합니다. 위젯 입장에서는 자신을 사용하고 있는 어플리케이션이 누구인지 알 수도 없는 노릇이고, 설령 알고 있다 하더라도, 해당 어플리케이션과 위젯은 서로 다른 프로세스에서 작동하고 있는 만큼, 연락을 취할 방법이 마땅치 않습니다.

따라서, 어떤 위젯이 어떤 어플리케이션에 속해있는지에 관한 정보와 필요한 경우 특정 위젯에서 발생한 이벤트에 따라 타겟 어플리케이션이 적절한 명령을 수행하도록 연결을 취해주는 중간 조절자가 필요합니다. 안드로이드 시스템 서비스 중에 하나인 App Widget Service 가 이와 같은 일을 수행합니다.
App Widget Service 는 현재 시스템에 위치한 모든 App Widget 정보를 관리하며, 어플리케이션이 임대 사업을 위해 AppWidgetHost 를 시작할 때, 해당 호스트 정보 또한 저장해 둡니다. 저장되는 호스트 정보에는 해당 호스트를 구분하기 위한 ID 값과 더불어서 위젯 View 가 다시 그려져야할 때 호출되어야하는 콜백 함수 정보가 포함됩니다.

<App Widget 화면이 갱신되기 까지...>

따라서, 위젯 화면은 다음과 같은 과정을 통해 업데이트 됩니다. 위젯과 관련된 특정 이벤트가 발생되면, 우선 App Widget Provider 가 해당 내용을 처리하고, App Widget Service 의 API 를 호출 합니다(IPC). App Widget Service 는 해당 App Widget 과 연결되어 있는 AppWidgetHost 를 찾은 후에, 등록되어 있는 콜백 함수를 호출합니다(IPC). 해당 콜백 함수는 건물주인 격인 어플리케이션 상에서 호촐되게 됨으로, 별 다른 어려움 없이 위젯 View 의 그림을 갱신할 수 있습니다.

App Widget Host 를 활용하는 예제

App Widget 과 App Widget Host 가 어떻게 상호작용 할 수 있는지에 관해 이해를 돕기 위해, 예제 코드를 첨부해 두었습니다. 자신이 사용하고 있는 Window 상에 추가적으로 App Widget 을 덧 붙일 수 있는 아주 아주 간단한 어플리케이션입니다. 코드 내용의 다음의 경로로 접속해 보시면 확인 하실 수 있습니다.


ps. 포스트에 간간히 코드 구글 경로를 추가하고 있는데 몇 분이나 살펴 보실지 궁금하네요... 그쪽은 카운트 정보가 없어서;;;;
반응형

댓글