このページでは、より高度なウィジェットを作成するためのおすすめの方法について説明します。 ユーザーエクスペリエンスが向上します
ウィジェット コンテンツの更新の最適化
ウィジェットのコンテンツを更新すると、計算コストが高くなる可能性があります。バッテリー消費を抑えるには、更新タイプ、頻度、タイミングを最適化します。
ウィジェットの更新の種類
ウィジェットを更新する方法には、完全な更新、部分更新、 データを更新しますそれぞれに異なる 影響を及ぼします
以下では、各更新タイプについて説明し、それぞれのコード スニペットを示します。
完全な更新:
AppWidgetManager.updateAppWidget(int, android.widget.RemoteViews)
を呼び出して、ウィジェットを完全に更新します。これにより、以前に提供されたRemoteViews
が新しいRemoteViews
に置き換えられます。これは最も計算コストの高い更新です。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)
Java
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)
を通じてフル アップデートを 1 回以上受信していない。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)
Java
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)
Java
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_listview);
これらのメソッドは、
同じ UID を
AppWidgetProvider
クラス。
ウィジェットを更新する頻度を決定する
ウィジェットは、updatePeriodMillis
属性に指定された値に応じて定期的に更新されます。ウィジェットは、ユーザー操作、ブロードキャスト アップデート、またはその両方に対応して更新できます。
定期的に更新する
定期的な更新の頻度は、appwidget-provider
XML で AppWidgetProviderInfo.updatePeriodMillis
の値を指定することで制御できます。各
update は AppWidgetProvider.onUpdate()
メソッドをトリガーします。
ウィジェットを更新するコードを配置できますただし、別の仮想マシン(VM)に
ブロードキャスト レシーバの更新が記述され、
ウィジェットでデータを非同期で読み込む必要がある場合や、
更新に 10 秒はかかります。10 秒が経過すると、システムは更新に
BroadcastReceiver
は、応答しなくなります。
updatePeriodMillis
は 30 分未満の値に対応していません。ただし、
定期的な更新を無効にする場合は、0 を指定します。
ユーザーが設定で更新頻度を調整できるようにします。たとえば、株価情報を 15 分おきに更新する、1 日 4 回のみ更新する、といった設定ができます。この場合、updatePeriodMillis
を 0 に設定して、
WorkManager
をご利用ください。
ユーザーの操作に応じて更新する
ユーザーの操作に応じてウィジェットを更新するためのおすすめの方法を以下に示します。
アプリのアクティビティから: ユーザー操作(ユーザーのタップなど)に応じて
AppWidgetManager.updateAppWidget
を直接呼び出します。通知やアプリ ウィジェットなどのリモート操作から:
PendingIntent
を作成してから、呼び出された場所からウィジェットをActivity
、Broadcast
、Service
。優先度はご自身で選択できます。たとえば、PendingIntent
にBroadcast
を選択した場合は、フォアグラウンド ブロードキャストを選択してBroadcastReceiver
に優先度を設定できます。
ブロードキャスト イベントに応じて更新する
ウィジェットの更新を必要とするブロードキャスト イベントの例としては、ユーザーが写真を撮影したときなどがあります。この場合、新しい写真が検出されたときにウィジェットを更新します。
JobScheduler
でジョブのスケジュールを設定し、JobInfo.Builder.addTriggerContentUri
メソッドを使用してブロードキャストをトリガーとして指定できます。
ブロードキャスト用に BroadcastReceiver
を登録することもできます(ACTION_LOCALE_CHANGED
をリッスンするなど)。ただし、これはデバイスのリソースを消費するため、注意して使用し、特定のブロードキャストのみを聞き取るようにしてください。ブロードキャストの導入により、
Android の制限事項
7.0(API レベル 24)と Android 8.0(API レベル 26)では、アプリは暗黙的に
ブロードキャストをマニフェスト内で使用し、特定の
例外があります。
BroadcastReceiver からウィジェットを更新する際の考慮事項
ウィジェットが BroadcastReceiver
(AppWidgetProvider
を含む)から更新される場合は、ウィジェットの更新時間と優先度に関する次の考慮事項に注意してください。
更新の所要時間
原則として、ブロードキャスト レシーバは、通常はアプリの 最大 10 秒間実行した後で、そのスレッドは応答しないと見なされ、 Application Not 応答中(ANR)エラー。ウィジェットの更新に時間がかかる場合は、次の代替手段を検討してください。
WorkManager
を使用してタスクのスケジュールを設定する。メッセージで応答時間を長くする
goAsync
メソッドを使用します。 これにより、レシーバーは 30 秒間実行できます。
詳細については、セキュリティに関する考慮事項とベスト プラクティスをご覧ください。
アップデートの優先度
デフォルトでは、ブロードキャスト(
AppWidgetProvider.onUpdate
- バックグラウンド プロセスとして実行します。つまり
システム リソースが過負荷状態になると、ブロードキャストの呼び出しが遅延する可能性がある
受信します。ブロードキャストを優先するには、フォアグラウンド プロセスにします。
たとえば、ユーザーがウィジェットの特定の部分をタップしたときに PendingIntent.getBroadcast
に渡される Intent
に Intent.FLAG_RECEIVER_FOREGROUND
フラグを追加します。
動的アイテムを含む正確なプレビューを作成する
<ph type="x-smartling-placeholder">このセクションでは、
コレクションを含むウィジェットのウィジェット プレビュー
ビューがあります。つまり、
ListView
、GridView
、または StackView
。
ウィジェットでこれらのビューのいずれかを使用している場合、直接 実際のウィジェットを レイアウトによって ウィジェットのプレビューにアイテムが表示されない場合があります。これは、コレクション ビューのデータが実行時に動的に設定されるためで、図 1 に示す画像のようになります。
コレクション ビューを含むウィジェットのプレビューがウィジェット内で正しく表示されるようにする
専用のレイアウト ファイルを
プレビューします。この個別のレイアウト ファイルには、実際のウィジェット レイアウトと、偽のアイテムを含むプレースホルダ コレクション ビューが含まれています。たとえば、Python や Curl など、
ListView
(プレースホルダ LinearLayout
といくつかの架空のリストを指定)
あります。
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
で定義され、2 つの 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>
偽のリスト項目を指定するには、レイアウトを複数回含めることができますが、その場合、各リスト項目は同じになります。一意のリストアイテムを指定するには、次の操作を行います。
テキスト値の属性セットを作成します。
<resources> <attr name="widgetTitle" format="string" /> <attr name="widgetContent" format="string" /> </resources>
テキストを設定するには、次の属性を使用します。
<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>
プレビューに必要な数のスタイルを作成します。Deployment の 各スタイル:
<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>
プレビュー レイアウトの架空のアイテムにスタイルを適用します。
<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>