고급 위젯 만들기

이 페이지에서는 고급 위젯을 만들기 위한 권장사항을 설명합니다. 사용자 환경을 개선할 수 있습니다.

위젯 콘텐츠 업데이트를 위한 최적화

위젯 콘텐츠를 업데이트하는 데는 계산 비용이 많이 들 수 있습니다. 배터리 절약 업데이트 유형, 빈도, 타이밍을 최적화할 수 있습니다.

위젯 업데이트 유형

위젯을 업데이트하는 방법에는 전체 업데이트, 부분 업데이트, 그리고 컬렉션 위젯의 경우 데이터 새로고침이 발생할 수 있습니다 각각은 컴퓨팅 비용 및 파급 효과입니다.

다음은 각 업데이트 유형에 대한 설명과 각각에 대한 코드 스니펫을 제공합니다.

  • 전체 업데이트: AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)를 호출합니다. 위젯을 완전히 업데이트합니다 이는 이전에 제공된 RemoteViewsRemoteViews 계산 비용이 가장 많이 드는 업데이트입니다.

    Kotlin

    val appWidgetManager = AppWidgetManager.getInstance(context)
    val remoteViews = RemoteViews(context.getPackageName(), R.layout.widgetlayout).also {
    setTextViewText(R.id.textview_widget_layout1, "Updated text1")
    setTextViewText(R.id.textview_widget_layout2, "Updated text2")
    }
    appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
    

    자바

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
    remoteViews.setTextViewText(R.id.textview_widget_layout1, "Updated text1");
    remoteViews.setTextViewText(R.id.textview_widget_layout2, "Updated text2");
    appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
    
  • 부분 업데이트: 호출 AppWidgetManager.partiallyUpdateAppWidget 위젯의 일부를 업데이트합니다. 이렇게 하면 새 RemoteViews가 이전에 제공된 RemoteViews 위젯이 updateAppWidget(int[], RemoteViews)를 통해 하나 이상의 전체 업데이트를 받지 않음

    Kotlin

    val appWidgetManager = AppWidgetManager.getInstance(context)
    val remoteViews = RemoteViews(context.getPackageName(), R.layout.widgetlayout).also {
    setTextViewText(R.id.textview_widget_layout, "Updated text")
    }
    appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews)
    

    자바

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
    remoteViews.setTextViewText(R.id.textview_widget_layout, "Updated text");
    appWidgetManager.partiallyUpdateAppWidget(appWidgetId, remoteViews);
    
  • 컬렉션 데이터 새로고침: 호출 AppWidgetManager.notifyAppWidgetViewDataChanged 위젯에서 컬렉션 뷰의 데이터를 무효화할 수도 있습니다. 이렇게 하면 RemoteViewsFactory.onDataSetChanged 그때까지는 위젯에 이전 데이터가 표시됩니다. 안전하게 고가의 작업을 동기식으로 수행할 수 있습니다.

    Kotlin

    val appWidgetManager = AppWidgetManager.getInstance(context)
    appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview)
    

    자바

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview);
    

앱이 같은 UID를 AppWidgetProvider 클래스

위젯 업데이트 빈도 결정

위젯은 updatePeriodMillis 드림 속성의 값을 제공합니다. 위젯은 사용자 상호작용, 브로드캐스트에 대한 응답으로 또는 둘 다로 수행될 수 있습니다.

주기적으로 업데이트

주기적 업데이트 빈도를 제어할 수 있습니다. appwidget-provider XML의 AppWidgetProviderInfo.updatePeriodMillis 각 업데이트는 AppWidgetProvider.onUpdate() 메서드를 트리거합니다. 여기서 개발자는 위젯을 업데이트하는 코드를 배치할 수 있습니다. 하지만 이 레이어의 broadcast receiver 업데이트에 설명되어 있습니다. 위젯이 데이터를 비동기식으로 로드해야 하거나 10초가 지나면 시스템이 업데이트로 간주하기 때문에 BroadcastReceiver:

updatePeriodMillis는 30분 미만의 값을 지원하지 않습니다. 그러나 주기적인 업데이트를 사용 중지하려면 0으로 지정하면 됩니다.

사용자가 구성의 업데이트 빈도를 조정하도록 허용할 수 있습니다. 대상 예를 들어 주식 티커가 15분마다 업데이트되도록 하거나 확인할 수 있습니다 이 경우 updatePeriodMillis를 0으로 설정하고 대신 WorkManager를 사용하세요.

사용자 상호작용에 대한 업데이트

다음은 사용자 상호작용에 기반하여 위젯을 업데이트하는 데 권장되는 몇 가지 방법입니다.

  • 앱 활동에서: 직접 호출 AppWidgetManager.updateAppWidget 등 사용자 상호작용에 응답 실시간으로 전달될 수 있습니다

  • 알림 또는 앱 위젯과 같은 원격 상호작용에서: PendingIntent를 구성한 후 호출된 Activity, Broadcast 또는 Service입니다. 우선순위를 직접 선택할 수 있습니다. 대상 예를 들어 PendingIntentBroadcast를 선택하면 포그라운드 브로드캐스트를 통해 BroadcastReceiver 우선순위.

방송 이벤트에 대한 응답으로 업데이트

업데이트가 필요한 브로드캐스트 이벤트의 예로는 사용자가 사진을 찍습니다. 이 경우에는 새 사진이 표시될 때 위젯을 업데이트하는 것이 좋습니다. 감지됩니다

JobScheduler를 사용하여 작업을 예약하고 브로드캐스트를 이 JobInfo.Builder.addTriggerContentUri 메서드를 사용하여 축소하도록 요청합니다.

브로드캐스트의 BroadcastReceiver를 등록할 수도 있습니다. 예를 들면 다음과 같습니다. 듣는 중 ACTION_LOCALE_CHANGED 하지만 이 경우 기기 리소스가 소모되므로 주의해서 사용하고 주의 깊게 들어 주세요. 특정 방송에만 적용됩니다 방송국의 도입으로 제한사항 7.0 (API 수준 24) 및 Android 8.0 (API 수준 26)의 경우 앱은 암시적으로 등록할 수 없습니다. 특정 브로드캐스트를 예외입니다.

BroadcastReceiver에서 위젯을 업데이트할 때의 고려사항

위젯이 다음을 포함하여 BroadcastReceiver에서 업데이트되는 경우 AppWidgetProvider님, 위젯 업데이트의 기간 및 우선순위입니다.

업데이트 기간

일반적으로 시스템은 앱의 자체 네트워크에서 실행되는 broadcast receiver를 허용합니다. 최대 10초 동안 실행한 후 응답이 없는 것으로 간주하고 애플리케이션이 응답 (ANR) 오류. 시간이 더 오래 걸리는 경우 다음과 같은 대안을 고려하세요.

  • WorkManager를 사용하여 작업을 예약합니다.

  • 수신자에게 더 많은 시간을 주고 goAsync 메서드를 사용하여 지도 가장자리에 패딩을 추가할 수 있습니다. 이렇게 하면 수신기가 30초 동안 실행될 수 있습니다.

자세한 내용은 보안 고려사항 및 권장사항 권장사항을 확인할 수 있습니다

업데이트 우선순위

기본적으로 AppWidgetProvider.onUpdate: 백그라운드 프로세스로 실행됩니다. 다시 말해 과부하된 시스템 리소스로 인해 브로드캐스트 호출이 지연될 수 있음 있습니다. 브로드캐스트의 우선순위를 지정하려면 포그라운드 프로세스로 설정하세요.

예를 들어 Intent.FLAG_RECEIVER_FOREGROUND 드림 사용자가 사용자가 메시지를 보낼 때 PendingIntent.getBroadcast에 전달되는 Intent에 대한 플래그 탭하는 동작입니다.

동적 항목이 포함된 정확한 미리보기 빌드

<ph type="x-smartling-placeholder">
</ph>
그림 1: 목록 항목이 없는 위젯 미리보기

이 섹션에서는 컬렉션이 포함된 위젯의 위젯 미리보기 뷰를 참조하세요. 즉, ListView, GridView 또는 StackView입니다.

위젯이 이러한 뷰 중 하나를 사용하는 경우 다음과 같이 직접 확장 가능한 미리보기를 만듭니다. 실제 위젯을 제공하고 위젯 미리보기에 항목이 표시되지 않을 때 발생합니다. 이러한 상황이 발생하는 이유는 다음과 같습니다. 컬렉션 뷰 데이터는 런타임에 동적으로 설정되며 이미지 캡션 모델을 테스트할 수 있습니다

컬렉션 뷰가 위젯에 제대로 표시되도록 하기 위해 콘텐츠 선택 도구를 사용하려면 광고 소재 유형에 대해서만 지정된 별도의 레이아웃 파일을 미리보기입니다. 이 별도의 레이아웃 파일에는 실제 위젯 레이아웃과 가짜 항목이 있는 자리표시자 컬렉션 뷰 예를 들어, 여러 가짜 목록이 있는 자리표시자 LinearLayout를 제공하여 ListView 개의 항목이 있습니다.

ListView의 예를 보여주려면 별도의 레이아웃 파일로 시작하세요.

// res/layout/widget_preview.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:background="@drawable/widget_background"
   android:orientation="vertical">

    // Include the actual widget layout that contains ListView.
    <include
        layout="@layout/widget_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    // The number of fake items you include depends on the values you provide
    // for minHeight or targetCellHeight in the AppWidgetProviderInfo
    // definition.

    <TextView android:text="@string/fake_item1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginVertical="?attr/appWidgetInternalPadding" />

    <TextView android:text="@string/fake_item2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginVertical="?attr/appWidgetInternalPadding" />

</LinearLayout>

다음 항목의 previewLayout 속성을 제공할 때 미리보기 레이아웃 파일을 지정합니다. AppWidgetProviderInfo 메타데이터 실제 위젯 레이아웃 지정 initialLayout 속성에 관한 정보를 확인하고 다음과 같은 경우 실제 위젯 레이아웃을 사용합니다. 런타임에 RemoteViews를 구성합니다.

<appwidget-provider
    previewLayout="@layout/widget_previe"
    initialLayout="@layout/widget_view" />

복잡한 목록 항목

이전 섹션의 예에서는 가짜 목록 항목을 제공합니다. 목록이 항목은 TextView 객체입니다. 가능 항목이 복잡한 레이아웃인 경우 모조 항목을 제공하기가 더 복잡해집니다.

widget_list_item.xml에 정의되어 있고 다음으로 구성된 목록 항목을 생각해 보세요. 두 개의 TextView 객체:

<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <TextView android:id="@id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/fake_title" />

    <TextView android:id="@id/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/fake_content" />
</LinearLayout>

모조 목록 항목을 제공하려면 레이아웃을 여러 번 포함할 수 있지만 각 목록 항목이 동일해집니다. 고유한 목록 항목을 제공하려면 다음 단계를 따르세요.

  1. 텍스트 값의 속성 집합을 만듭니다.

    <resources>
        <attr name="widgetTitle" format="string" />
        <attr name="widgetContent" format="string" />
    </resources>
    
  2. 다음 속성을 사용하여 텍스트를 설정합니다.

    <LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
        <TextView android:id="@id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="?widgetTitle" />
    
        <TextView android:id="@id/content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="?widgetContent" />
    </LinearLayout>
    
  3. 미리보기에 필요한 만큼의 스타일을 만듭니다. 다음에서 값을 다시 정의합니다. 각 스타일:

    <resources>
    
        <style name="Theme.Widget.ListItem">
            <item name="widgetTitle"></item>
            <item name="widgetContent"></item>
        </style>
        <style name="Theme.Widget.ListItem.Preview1">
            <item name="widgetTitle">Fake Title 1</item>
            <item name="widgetContent">Fake content 1</item>
        </style>
        <style name="Theme.Widget.ListItem.Preview2">
            <item name="widgetTitle">Fake title 2</item>
            <item name="widgetContent">Fake content 2</item>
        </style>
    
    </resources>
    
  4. 미리보기 레이아웃에서 모조 항목에 스타일을 적용합니다.

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" ...>
    
        <include layout="@layout/widget_view" ... />
    
        <include layout="@layout/widget_list_item"
            android:theme="@style/Theme.Widget.ListItem.Preview1" />
    
        <include layout="@layout/widget_list_item"
            android:theme="@style/Theme.Widget.ListItem.Preview2" />
    
    </LinearLayout>