앱 위젯은 홈 화면 등에 삽입되어 주기적인 업데이트를 받을 수 있는 소형 애플리케이션 뷰입니다.
이러한 뷰는 AppWidgetProvider를 사용하여 게시할 수 있습니다.
다른 앱 위젯을 포함할 수 있는 애플리케이션 구성요소를 앱 위젯 호스트라고 합니다. 아래 스크린샷은 음악 앱 위젯을 보여줍니다.
AppWidgetProvider 클래스 구현
브로드캐스트 이벤트를 기반으로 앱 위젯과의 상호작용 정의
AppWidgetProviderInfo (xml)
앱 위젯의 레이아웃, 업데이트 빈도, AppWidgetProvider 클래스 등 앱 위젯의 메타데이터 설정
레이아웃 파일
위젯의 레이아웃 정의
Manifest 설정
AppWidgetProvider 클래스 파일 정의 및 브로드캐스트(위젯 이벤트) 수신 설정
위젯 프로바이더가 위젯과 상호작용을 위해서 브로드캐스트를 받도록 아래와 같이 설정한다
<manifest ...>
<application ... >
...
<receiver android:name="ExampleAppWidgetProvider" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/example_appwidget_info" />
</receiver>
...
</application>
</manifest>
receiver - name : 설정할 리시버인 위젯 프로바이더를 정의한 클래스
action 태그 : 위젯이 보내는 브로드 캐스트가 정의되어 있다
meta-data - name : 프로바이더의 데이터를 AppWidgetProviderInfo 설명자로 표시하려면 위와 같이 설정
meta-data - resource : 위젯과 관련된 설정이 포함된 XML 파일이다
최소 레이아웃 크기, 초기 레이아웃 리소스, 앱 위젯을 업데이트하는 빈도, 작성 시 실행할 구성 활동(선택사항) 등 앱 위젯의 기본적인 특성을 정의합니다.
XML 리소스에서 단일 <appwidget-provider>
요소를 사용하여 AppWidgetProviderInfo 객체를 정의한다.
프로젝트의 res/xml/
폴더에 저장한다.
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="40dp"
android:minHeight="40dp"
android:updatePeriodMillis="86400000"
android:previewImage="@drawable/preview"
android:initialLayout="@layout/example_appwidget"
android:configure="com.example.android.ExampleAppWidgetConfigure"
android:resizeMode="horizontal|vertical">
</appwidget-provider>
minWidth, minHeight : 위젯의 최소 크기를 지정한다. 이에 따라 기본 사이즈가 정해진다.
updatePeriodMillis : 앱이 자동으로 업데이트 되는 주기(ms)를 정한다(최소 30분) 위젯 프로바이더의 onUpdate()를 호출함
previewImage : 위젯 생성 전 미리 보는 이미지, 없을 시 앱 아이콘으로 표시된다.
initialLayout : 앱 위젯의 레이아웃을 지정
configure : 위젯을 추가할 때 속성을 구성하기 위한 Activity 정의, 선택사항
resizeMode : 사용자가 홈 화면 위젯의 크기를 조절 할 수 있는 방향 정의, 모두 조절 가능 할 경우horizontal|vertical
위젯의 기본 셀 크기를 지정할 때의 가이드 라인입니다.
android:minWidth="40dp"
android:minHeight="40dp"
위 처럼 크기를 지정할 경우 1x1의 위젯을 제공합니다.
아래 표를 사용하여 원하는 수의 그리드 셀에 따라 위젯의 최소 크기를 대략적으로 추정할 수 있습니다.
앱 위젯의 초기 레이아웃을 XML로 정의하고 프로젝트의 res/layout/
디렉터리에 저장해야 한다.
구글이 제공하는 앱 위젯 디자인 가이드라인은 다음과 같다.
위젯 레이아웃은 RemoteViews기반이기에 사용할 수 있는 뷰들은 다음과 같다.
Layout
View
이러한 클래스의 하위 항목 또한 지원하지 않는다.
AppWidgetProvider 클래스는 BroadcastReceiver를 앱 위젯 브로드캐스트를 처리하기 위한 편의성 클래스로 확장한다.
위젯 업데이트, 삭제, 사용 설정 및 중지와 같은 이벤트 브로드 캐스트만을 수신해서 메서드를 호출한다.
class ExampleAppWidgetProvider : AppWidgetProvider() {
// 앱 위젯은 여러개가 등록 될 수 있는데, 최초의 앱 위젯이 등록 될 때 호출 됩니다. (각 앱 위젯 인스턴스가 등록 될때마다 호출 되는 것이 아님)
override fun onEnabled(context: Context) {
super.onEnabled(context)
}
// onEnabled() 와는 반대로 마지막의 최종 앱 위젯 인스턴스가 삭제 될 때 호출 됩니다
override fun onDisabled(context: Context) {
super.onDisabled(context)
}
// android 4.1 에 추가 된 메소드 이며, 앱 위젯이 등록 될 때와 앱 위젯의 크기가 변경 될 때 호출 됩니다.
// 이때, Bundle 에 위젯 너비/높이의 상한값/하한값 정보를 넘겨주며 이를 통해 컨텐츠를 표시하거나 숨기는 등의 동작을 구현 합니다
override fun onAppWidgetOptionsChanged(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int, newOptions: Bundle) {
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions)
}
// 위젯 메타 데이터를 구성 할 때 updatePeriodMillis 라는 업데이트 주기 값을 설정하게 되며, 이 주기에 따라 호출 됩니다.
// 또한 앱 위젯이 추가 될 떄에도 호출 되므로 Service 와의 상호작용 등의 초기 설정이 필요 할 경우에도 이 메소드를 통해 구현합니다
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
super.onUpdate(context, appWidgetManager, appWidgetIds)
}
// 이 메소드는 앱 데이터가 구글 시스템에 백업 된 이후 복원 될 때 만약 위젯 데이터가 있다면 데이터가 복구 된 이후 호출 됩니다.
// 일반적으로 사용 될 경우는 흔치 않습니다.
// 위젯 ID 는 UID 별로 관리 되는데 이때 복원 시점에서 ID 가 변경 될 수 있으므로 백업 시점의 oldID 와 복원 후의 newID 를 전달합니다
override fun onRestored(context: Context, oldWidgetIds: IntArray, newWidgetIds: IntArray) {
super.onRestored(context, oldWidgetIds, newWidgetIds)
}
// 해당 앱 위젯이 삭제 될 때 호출 됩니다
override fun onDeleted(context: Context, appWidgetIds: IntArray) {
super.onDeleted(context, appWidgetIds)
}
// 앱의 브로드캐스트를 수신하며 해당 메서드를 통해 각 브로드캐스트에 맞게 메서드를 호출한다.
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
}
}
중요한 메서드는 onUpdate()
다
각 위젯이 등록 될 때마다 호출되고, AppWidgetProviderInfo에서 설정한 업데이트 주기마다 호출된다.
따라서 사용자 상호작용 이벤트를 허용하는 경우 이 콜백에서 이벤트 핸들러를 등록한다.
클릭 시 이벤트를 등록할 부분을 상술한 바와 같이 onUpdate()
에서 등록한 예제이다.
class ExampleAppWidgetProvider : AppWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
// Perform this loop procedure for each App Widget that belongs to this provider
appWidgetIds.forEach { appWidgetId ->
// Create an Intent to launch ExampleActivity
val pendingIntent: PendingIntent = Intent(context, ExampleActivity::class.java)
.let { intent ->
PendingIntent.getActivity(context, 0, intent, 0)
}
// Get the layout for the App Widget and attach an on-click listener
// to the button
val views: RemoteViews = RemoteViews(
context.packageName,
R.layout.appwidget_provider_layout
).apply {
setOnClickPendingIntent(R.id.button, pendingIntent)
}
// Tell the AppWidgetManager to perform an update on the current app widget
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
}
각 위젯은 등록될 때마다 ID를 부여받는다.
이를appWidgetIds
에 받고 해당 ID마다 각 뷰에 이벤트를 등록해PendingIntent
를 통해 액티비티를 실행하게된다.
PendingIntent.getactivity(context, requestCode, Intent, Flags)
에서 Flags가 안될 경우 다음 참조
RemoteViews
생성자로 해당 View를 선택해 리스너 및 속성을 설정할 수 있다.
이후 AppWidgetManager의updateAppWidget
함수를 이용해 해당 위젯을 업데이트한다.
또는partiallyUpdateAppWidget
함수를 통해 일부분 업데이트를 한다.
https://developer.android.com/guide/topics/appwidgets?hl=ko
https://blog.naver.com/PostView.naver?blogId=pistolcaffe&logNo=222237065122&redirect=Dlog&widgetTypeCall=true&directAccess=false