App Widgets 이란?

아래 사진과 같이 런처 앱에서 설치된 앱의 기능을 사용할 수 있도록 해줍니다.

Widget을 만드는 방법


아래의 안드로이드 공식 문서를 통해 기본적인 제작 방법을 학습할 수 있습니다.
Create app widget - Android developers

App widget processing flow


앱 위젯을 처리하는 흐름

  • 핵심
    • BroadcastReceiver로 위젯 업데이트 처리
    • RemoteViews로 위젯 UI를 처리

위젯 제작 과정


아래는 예시 입니다. 전체 예제 코드

  1. res 디렉토리 내에 위젯 관련 파일을 담을 적절한 디렉토리를 만듭니다.
  2. res/layout 디렉토리 내에 위젯 레이아웃 파일view_widget을 만들고 레이아웃을 제작합니다.
  3. 만든 디렉토리 내에 nine-widget-info.xml라는 이름의 리소스 파일을 만들고 아래와 같이 작성합니다.
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:configure="com.lifedawn.bestweather.widget.ConfigureWidgetActivity" // 위젯을 런처에 생성하고자 할때 사용하는 위젯 설정 화면, 생성이 필수는 아님
    android:initialLayout="@layout/view_widget" // 위젯 레이아웃
    android:minWidth="@dimen/ninthWidgetWidth"
    android:minHeight="@dimen/ninthWidgetHeight"
    android:minResizeWidth="@dimen/ninthWidgetWidth"
    android:minResizeHeight="@dimen/ninthWidgetHeight"
    android:previewImage="@drawable/widget_preview_9" // 런처 앱에서 위젯 추가  나오는 이미지
    android:resizeMode="vertical|horizontal" // 위젯 크기 조정 가능한 모드, 수평/수직 모두 조정   있도록 하겠다는 의미
    android:updatePeriodMillis="0" // 위젯 업데이트 주기, 0이면 자동 업데이트 하지 않고 수동 업데이트로만 가능
    android:widgetCategory="home_screen" //  화면에 위젯을 보여준다는 의미, 안드로이드 5 부터는 이것만 가능
/>
  1. 위젯 업데이트와 같은 처리는 BroadcastReceiver를 통해서 진행하기 때문에 관련 로직을 처리할 NinthWidgetProvider 클래스를 만들고 내용을 작성합니다.
  2. AndroidManifest.xmlapplication태그 내에 앱 위젯 내용을 추가합니다.
<receiver
    android:name=".widget.widgetprovider.NinthWidgetProvider"
    android:exported="true"
    android:label="@string/ninthWidgetLabel">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> // 필수
        <action android:name="android.intent.action.BOOT_COMPLETED" />
        <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
    </intent-filter>

    <meta-data
        android:name="android.appwidget.provider" // 필수
        android:resource="@xml/ninth_widget_info" />
</receiver>
  1. 완료

위젯을 런처 앱에 추가하는 경우에 사용자가 위젯에 대해 부가적인 설정이 가능하도록 하고자 하는 경우에는 위의 ConfigureWidgetActivity를 생성하면 됩니다. 런처 앱에서 위젯 추가 버튼을 클릭시 이 액티비티가 나오고 관련 설정이 가능해집니다.

위젯 레이아웃 제작의 한계점

앱 위젯은 해당 앱이 다른 프로세스인 런처 앱 상에서 RemoteViews라는 View로 원격으로 레이아웃을 보여주는 방식이기 때문에, 개발자가 원하는 대로 레이아웃을 제작하는 것이 어렵다는 한계점이 있습니다.

  • 앱 위젯에 사용 가능한 레이아웃 및 위젯
    • AdapterViewFlipper
    • FrameLayout
    • GridLayout
    • GridView
    • LinearLayout
    • ListView
    • RelativeLayout
    • StackView
    • ViewFlipper
    • AnalogClock
    • Button
    • Chronometer
    • ImageButton
    • ImageView
    • ProgressBar
    • TextClock
    • TextView
    • 안드로이드 12 부터 가능
      • CheckBox
      • RadioButton
      • RadioGroup
      • Switch

한계점을 벗어나, 원하는 레이아웃을 제작하는 방법

RemoteViews에서 사용가능한 위젯과 레이아웃으로는 아래의 위젯 제작이 매우 어렵습니다.

Bitmap으로 만들어 ImageView에 지정하여 해결

  • 작업 과정
    1. 동적으로 레이아웃 제작
      • RelativeLayout생성
        • 최상위 view
      • LinearLayout생성
        • RelativeLayout의 자식 View
        • 시간, 날씨 아이콘(맑음, 비 등)의 정보 표시
    2. nine-widget-info.xml에서 설정했던 위젯의 width, height정보를 pixel 값으로 변환
    3. 최상위 view의 width, height를 변환한 pixel 값으로 설정
    4. Bitmap viewBmp = rootLayout.getDrawingCache()
    5. remoteViews.setImageViewBitmap(R.id.bitmapValuesView, viewBmp);
    6. 완료

결과

아래의 사진은 ImageView를 사용하여 만든 위젯과, RemoteViews에서 사용가능한 뷰와 레이아웃으로 만든 위젯의 레이아웃 계층도를 보여줍니다.

Bitmap으로 처리한 위젯이 제대로 동작하고 있는 것을 확인할 수 있습니다.