シンプルなウィジェットを作成する

アプリ ウィジェットは、他のアプリのビューに埋め込むことができる小型のアプリビューです。 アプリは定期的に更新され、定期的な更新を受信します。これらの ビューはユーザー インターフェースではウィジェットと呼ばれます。また、 もう 1 つはアプリ ウィジェット プロバイダ(ウィジェット プロバイダ)を使用する方法です。アプリのコンポーネントを これ以外のウィジェットは、アプリ ウィジェット ホスト(またはウィジェット ホスト)と呼ばれます。図 1 サンプルの音楽ウィジェットを表示します。

音楽ウィジェットの例
図 1. 音楽ウィジェットの例

このドキュメントでは、ウィジェット プロバイダを使用してウィジェットを公開する方法について説明します。対象 独自のAppWidgetHostを作成して アプリ ウィジェットをホストする方法については、ウィジェット ホストを作成するをご覧ください。

ウィジェットの設計方法については、アプリ ウィジェットの概要をご覧ください。

ウィジェット コンポーネント

ウィジェットを作成するには、次の基本コンポーネントが必要です。

AppWidgetProviderInfo オブジェクト
ウィジェットのレイアウト、更新など、ウィジェットのメタデータを記述します。 頻度、AppWidgetProvider クラスがあります。 AppWidgetProviderInfo は次のように XML で定義されます。 説明します。
AppWidgetProvider クラス
プログラマティックに API とやり取りできる基本的なメソッドを定義します。 追加します。これを使用して、ウィジェットの更新時にブロードキャストを受信し、 有効または無効にできます。AppWidgetProvider を マニフェストを作成し、それを次のように実装します。 構成する必要があります。
ビューのレイアウト
ウィジェットの初期レイアウトを定義します。レイアウトは XML です。

図 2 は、これらのコンポーネントがアプリ ウィジェット処理全体でどのように位置付けられるかを示しています。 できます。

アプリ ウィジェットの処理フロー
図 2. アプリ ウィジェットの処理フロー。
で確認できます。

ウィジェットにユーザー構成が必要な場合は、アプリ ウィジェット構成を実装します。 できます。このアクティビティでは、ユーザーはウィジェットの設定( 時計ウィジェットのタイムゾーン

また、次の改善もおすすめします: 柔軟なウィジェット レイアウトその他の拡張機能高度なウィジェットコレクション ウィジェットウィジェットの作成 ホストします

AppWidgetProviderInfo XML を宣言する

AppWidgetProviderInfo オブジェクトは、ウィジェットの基本品質を定義します。 単一の要素を使用して、XML リソース ファイル内で AppWidgetProviderInfo オブジェクトを定義します。 <appwidget-provider> 要素を作成し、プロジェクトの res/xml/ フォルダに保存します。

これを次の例に示します。

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="40dp"
    android:minHeight="40dp"
    android:targetCellWidth="1"
    android:targetCellHeight="1"
    android:maxResizeWidth="250dp"
    android:maxResizeHeight="120dp"
    android:updatePeriodMillis="86400000"
    android:description="@string/example_appwidget_description"
    android:previewLayout="@layout/example_appwidget_preview"
    android:initialLayout="@layout/example_loading_appwidget"
    android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen"
    android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>

ウィジェットのサイズ設定属性

デフォルトのホーム画面では、セルのグリッドに基づいてウィンドウ内にウィジェットが配置されます。 サイズも定義できます。ほとんどのホーム画面ではウィジェットしか使用されない グリッドセルの整数の倍数のサイズ(例: 2 つのセル) 横方向に 3 つのセルを配置します。

ウィジェットのサイズ設定属性を使用すると、ウィジェットのデフォルトのサイズを指定し、 ウィジェットのサイズの下限と上限を指定しますここでは、 ウィジェットのデフォルト サイズは、ウィジェットが最初に表示されるときに使用するサイズです。 ホーム画面に追加されました。

次の表に、これに関連する <appwidget-provider> 属性を示します。 ウィジェットのサイズ設定を次のように変更します。

属性と説明
targetCellWidthtargetCellHeight(Android 12)、 minWidthminHeight
  • Android 12 以降では、 targetCellWidth および targetCellHeight 属性は、ウィジェットのデフォルト サイズをグリッド単位で指定します。 選択します。Android 11 では、これらの属性は無視されます。 以下に表示され、ホーム画面が表示されていなければ無視可能です。 グリッドベースのレイアウトを サポートしています
  • minWidthminHeight 属性では、ウィジェットのデフォルト サイズを指定します。 単位は dp です。ウィジェットの最小の幅または最小の高さの値が一致しない場合 セルの寸法を計算すると、値は 最も近いセルサイズになります。
で確認できます。 両方のタグのセットを 属性 - targetCellWidthtargetCellHeightminWidthminHeight を使用します。これにより、アプリは ユーザーのデバイスの場合は minWidthminHeight targetCellWidth と、 targetCellHeight。サポートされている場合、 targetCellWidth 属性と targetCellHeight 属性 minWidthminHeight より優先される 属性です。
minResizeWidthminResizeHeight ウィジェットの絶対最小サイズを指定します。これらの値により ウィジェットが判読できない、または使用できない使用 これらの属性を使用すると、ユーザーはウィジェットのサイズをより小さいサイズに変更できます。 最小サイズになるように調整します。minResizeWidth 属性は次のとおりです。 minWidth より大きい場合、または水平方向の場合は無視されます。 サイズ変更が有効になっていません。詳しくは、 resizeMode。同様に minResizeHeight 属性が次の値より大きい場合は無視されます。 minHeight。または、縦方向のサイズ変更が有効になっていない場合。
maxResizeWidthmaxResizeHeight ウィジェットの推奨最大サイズを指定します。値が一致しなかった場合 グリッドセルの寸法の倍数の場合、最も近い値に切り上げられます。 指定します。maxResizeWidth 属性は、次の場合は無視されます。 minWidth より小さい場合、または横方向のサイズ変更が 有効にします。resizeMode を参照してください。同様に maxResizeHeight 属性がより大きい場合は無視されます。 minHeight よりも大きい値であるか、縦方向のサイズ変更が有効になっていない場合です。 Android 12 で導入されました。
resizeMode ウィジェットのサイズを変更できるルールを指定します。こちらの 属性を使用して、ホーム画面のウィジェットを水平方向や垂直方向にサイズ変更できるようにし、 または両方の軸で設定できます。ユーザーによるウィジェットを長押しすると、そのサイズ変更ハンドルが表示されます。 次に、水平または垂直のハンドルをドラッグして、 配置できますresizeMode 属性の値は次のとおりです。 horizontalverticalnone。宛先 ウィジェットを水平方向や垂直方向にサイズ変更可能として宣言するには、 horizontal|vertical

上の表の属性がウィジェットのサイズ設定にどのように影響するかを説明するため、 以下の仕様を想定しています。

  • グリッドセルの幅は 30 dp、高さは 50 dp です。
  • 次の属性が指定されています。
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="80dp"
    android:minHeight="80dp"
    android:targetCellWidth="2"
    android:targetCellHeight="2"
    android:minResizeWidth="40dp"
    android:minResizeHeight="40dp"
    android:maxResizeWidth="120dp"
    android:maxResizeHeight="120dp"
    android:resizeMode="horizontal|vertical" />

Android 12 以降:

targetCellWidth 属性と targetCellHeight 属性をデフォルトとして使用する ウィジェットのサイズを調節できます

ウィジェットのサイズは、デフォルトで 2x2 です。ウィジェットのサイズは 2x1 に縮小できます。 最大 4x3。

Android 11 以前:

minWidth 属性と minHeight 属性を使用して、デフォルトのサイズを計算します。 クリックします。

デフォルトの幅 = Math.ceil(80 / 30) = 3

デフォルトの高さ = Math.ceil(80 / 50) = 2

ウィジェットのサイズは、デフォルトで 3x2 です。ウィジェットのサイズは 2x1 に縮小できます。 全画面表示されます。

その他のウィジェット属性

次の表に、これに関連する <appwidget-provider> 属性を示します。 品質に大きく影響します

属性と説明
updatePeriodMillis ウィジェット フレームワークが onUpdate() を呼び出すことで AppWidgetProvider コールバック メソッドを指定します。実際の更新は、Cloud Storage の実行時に この値で変更できます。また、更新頻度は バッテリーを節約します。 適切な更新期間を選択するための考慮事項の一覧については、 ウィジェットの更新の最適化 コンテンツをご覧ください。
initialLayout ウィジェット レイアウトを定義するレイアウト リソースを参照します。
configure ユーザーがウィジェットを追加したときに起動するアクティビティを定義します。 ウィジェットのプロパティを設定できます詳しくは、 ユーザーがウィジェットを設定できるようにする。 Android 12 以降では、アプリは最初の できます。 ウィジェットのデフォルト構成をご覧ください。
description 表示するウィジェット ピッカーの説明を指定します。 追加します。Android 12 で導入されました。
previewLayout(Android 12) および previewImage(Android 11 以前)
  • Android 12 以降では、 previewLayout 属性は、スケーラブルなプレビューを指定します。 XML レイアウトとして設定し、ウィジェットのデフォルトのサイズとして設定する必要があります。次のことが理想的です。 この属性に指定されたレイアウト XML が、 デフォルト値で実際のウィジェットを使用します。
  • Android 11 以前では、previewImage 属性は、ウィジェットの作成後にどのように表示されるかのプレビューを指定します。 ユーザーがアプリ ウィジェットを選択したときに表示されます。回答が「いいえ」の場合 指定されている場合、ユーザーには代わりにアプリのランチャー アイコンが表示されます。この このフィールドは、次の android:previewImage 属性に対応します。 <receiver> 要素 AndroidManifest.xml ファイル。
で確認できます。 注: previewImage と指定した URL の両方を指定することをおすすめします。 および previewLayout 属性を使用して、アプリがフォールバックできるように previewImage を使用するには、ユーザーのデバイスが previewLayout。詳しくは、 スケーラブル ウィジェットのプレビュー
autoAdvanceViewId 自動進行するウィジェット サブビューのビュー ID を指定します。 表示されます。
widgetCategory ウィジェットをホーム画面に表示できるかどうかを宣言します (home_screen)、ロック画面(keyguard)、または あります。Android 5.0 以降では、home_screen のみが有効です。
widgetFeatures ウィジェットでサポートされている機能を宣言します。たとえば ユーザーがウィジェットを追加したときにデフォルト構成を使用するように設定するには、 両方の configuration_optional および reconfigurable 使用できます。これにより、ユーザーが指定した過去の設定アクティビティの開始が ウィジェットを追加します。ユーザーは ウィジェットを再構成する できます。

AppWidgetProvider クラスを使用してウィジェット ブロードキャストを処理する

AppWidgetProvider クラスがウィジェット ブロードキャストを処理してウィジェットを更新する ウィジェットのライフサイクル イベントに応答します。以降のセクションでは、 マニフェストで AppWidgetProvider を宣言して実装する。

マニフェストでウィジェットを宣言する

まず、アプリの AndroidManifest.xmlAppWidgetProvider クラスを宣言します。 必要があります。

<receiver android:name="ExampleAppWidgetProvider"
                 android:exported="false">
    <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>

<receiver> 要素には android:name 属性が必要です。この属性では、 ウィジェットで使用される AppWidgetProvider。このコンポーネントはエクスポートしないでください。 ただし、別のプロセスで AppWidgetProvider にブロードキャストする必要がある場合は除きます。 違います

<intent-filter> 要素には、<action> 要素を android:name 属性。この属性は、AppWidgetProvider 受け入れられる ACTION_APPWIDGET_UPDATE あります。明示的に宣言する必要があるブロードキャストはこれだけです。「 AppWidgetManager 他のすべてのウィジェット ブロードキャストを、次のように自動的に AppWidgetProvider に送信します。 できます。

<meta-data> 要素には、AppWidgetProviderInfo リソースを指定します。 次の属性が必要です。

  • android:name: メタデータ名を指定します。使用 android.appwidget.provider: データを AppWidgetProviderInfo 記述子。
  • android:resource: AppWidgetProviderInfo リソースを指定します。 あります。

AppWidgetProvider クラスを実装する

AppWidgetProvider クラスの拡張 BroadcastReceiver: ウィジェットのブロードキャストを処理するコンビニエンス クラスが用意されています。この関数が受け取るのは、 ウィジェットに関連するブロードキャスト(ウィジェットの更新時など)に、 無効化、有効化、無効化されます。これらのブロードキャスト イベントが発生すると、 AppWidgetProvider メソッドが呼び出されます。

onUpdate()
これは、定義された間隔でウィジェットを更新するために呼び出されます。 AppWidgetProviderInfoupdatePeriodMillis 属性。表をご覧ください。 追加のウィジェット属性について説明します ご確認ください。
で確認できます。
このメソッドは、ユーザーがウィジェットを追加したときにも呼び出されるため、 イベント ハンドラの定義など、 View オブジェクト、またはデータの読み込み先のジョブを開始する ウィジェットに表示されますただし、サービス アカウントを指定せずに構成アクティビティを宣言し、 configuration_optional フラグ。このメソッドは、ユーザーがリクエストしたときに呼び出されません。 ウィジェットを追加しますが、その後の更新では呼び出されます。これは、 最初の更新を行うのは設定アクティビティの責任です。 完了です。詳しくは、ユーザーにアプリ ウィジェットの設定を許可するをご覧ください。
で確認できます。
最も重要なコールバックは onUpdate() です。 onUpdate() クラスをご覧ください。
onAppWidgetOptionsChanged()

このメソッドは、ウィジェットが最初に配置されたときに呼び出されます。また、 サイズ変更されます。このコールバックを使用して、ウィジェットのサイズに応じてコンテンツを表示または非表示にします。 あります。サイズ範囲を取得します。Android 12 以降では、 呼び出すことにより、ウィジェット インスタンスが取ることができるサイズのリストを getAppWidgetOptions() これは、次を含む Bundle を返します。 次のとおりです。

  • OPTION_APPWIDGET_MIN_WIDTH: ウィジェット インスタンスの幅の下限が dp 単位で格納されます。
  • OPTION_APPWIDGET_MIN_HEIGHT: ウィジェット インスタンスの高さの下限が dp 単位で格納されます。
  • OPTION_APPWIDGET_MAX_WIDTH: ウィジェット インスタンスの幅の上限を dp 単位で指定します。
  • OPTION_APPWIDGET_MAX_HEIGHT: には、ウィジェット インスタンスの高さの上限が dp 単位で格納されています。
  • OPTION_APPWIDGET_SIZES: リクエスト可能なサイズ(List<SizeF>)のリストが dp 単位で格納され、 指定することもできます。Android 12 で導入されました。
onDeleted(Context, int[])

このメソッドは、ウィジェットがウィジェット ホストから削除されるたびに呼び出されます。

onEnabled(Context)

これは、ウィジェットのインスタンスが初めて作成されるときに呼び出されます。 たとえば、ユーザーがウィジェットのインスタンスを 2 つ追加した場合、 説明します。新しいデータベースを開く必要がある場合や、設定変更のために別の設定を行う必要がある場合は、 すべてのウィジェット インスタンスに対して一度だけ実行すればよい場合は、 できます。

onDisabled(Context)

このメソッドは、ウィジェットの最後のインスタンスが 作成します。ここで、onEnabled(Context) での作業内容をクリーンアップします。 一時データベースの削除などを行います

onReceive(Context, Intent)

これはブロードキャストのたびに呼び出され、先行する各コールバックの前に呼び出されます。 あります。通常は、このメソッドを実装する必要はありません。デフォルト AppWidgetProvider 実装は、すべてのウィジェット ブロードキャストをフィルタリングし、 上記のメソッドを適宜使用する必要があります。

AppWidgetProvider クラスの実装をブロードキャストとして宣言する必要があります。 AndroidManifest<receiver> 要素を使用するレシーバ。詳細については、 このページのマニフェストのウィジェットをご覧ください。

onUpdate() クラスを使用してイベントを処理する

最も重要な AppWidgetProvider コールバックは onUpdate() です。これは、 構成を使用する場合を除き、ウィジェットがホストに追加されたときに呼び出されます。 configuration_optional フラグのないアクティビティです。ウィジェットが このコールバックにイベント ハンドラを登録します。条件 ウィジェットが一時ファイルやデータベースを作成したり、 クリーンアップが必要な場合、onUpdate() が唯一のコールバック メソッドとなる可能性があります。 定義する必要はありません。

たとえば、特定のタイミングでアクティビティを起動するボタンを備えたウィジェットが 次の AppWidgetProvider の実装を使用できます。

Kotlin

class ExampleAppWidgetProvider : AppWidgetProvider() {

    override fun onUpdate(
            context: Context,
            appWidgetManager: AppWidgetManager,
            appWidgetIds: IntArray
    ) {
        // Perform this loop procedure for each widget that belongs to this
        // provider.
        appWidgetIds.forEach { appWidgetId ->
            // Create an Intent to launch ExampleActivity.
            val pendingIntent: PendingIntent = PendingIntent.getActivity(
                    /* context = */ context,
                    /* requestCode = */  0,
                    /* intent = */ Intent(context, ExampleActivity::class.java),
                    /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )

            // Get the layout for the widget and attach an onClick 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
            // widget.
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }
}

Java

public class ExampleAppWidgetProvider extends AppWidgetProvider {

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // Perform this loop procedure for each widget that belongs to this
        // provider.
        for (int i=0; i < appWidgetIds.length; i++) {
            int appWidgetId = appWidgetIds[i];
            // Create an Intent to launch ExampleActivity
            Intent intent = new Intent(context, ExampleActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(
                /* context = */ context,
                /* requestCode = */ 0,
                /* intent = */ intent,
                /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
            );

            // Get the layout for the widget and attach an onClick listener to
            // the button.
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget_layout);
            views.setOnClickPendingIntent(R.id.button, pendingIntent);

            // Tell the AppWidgetManager to perform an update on the current app
            // widget.
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }
    }
}

この AppWidgetProvider では、onUpdate() メソッドのみを定義しています。このメソッドを使用して以下を行います。 以下を起動する PendingIntent を作成します。 Activity を呼び出し、ウィジェットの ボタン setOnClickPendingIntent(int, PendingIntent) を使用します。各エントリを反復処理するループが含まれています。 appWidgetIds: によって作成される各ウィジェットを識別する ID の配列 関連付けられていますユーザーがウィジェットのインスタンスを複数作成すると、 すべて同時に更新されますただし、updatePeriodMillis のスケジュールは 1 つのみです ウィジェットのすべてのインスタンスで管理されます。たとえば、更新スケジュールが 2 時間ごとに実行されるように定義され、ウィジェットの 2 つ目のインスタンスが追加されます。 最初のイベントから 1 時間後に 2 回目は無視されますどちらも 2 秒ごとに 1 時間ごとではありません。

詳しくは、 ExampleAppWidgetProvider.java サンプル クラスをご覧ください。

ウィジェット ブロードキャスト インテントを受け取る

AppWidgetProvider はコンビニエンス クラスです。ウィジェットを 独自の BroadcastReceiver を実装することも、オーバーライドすることもできます。 onReceive(Context,Intent) コールバック。注意が必要なインテントは、 次のとおりです。

ウィジェット レイアウトを作成する

ウィジェットの初期レイアウトを XML で定義し、 プロジェクトの res/layout/ ディレクトリに配置します。設計 ガイドラインをご覧ください。

ウィジェット レイアウトの作成は、 layouts です。ただしウィジェットは レイアウトは RemoteViews に基づいています。 レイアウトやビュー ウィジェットをすべてサポートしているわけではありません。カスタム RemoteViews でサポートされているビューのサブクラス。

RemoteViewsViewStub もサポートしています。 これは目に見えないゼロサイズの View で、これを使用してレイアウトをゆっくりとインフレートできます。 実行時に決定できます。

ステートフル動作のサポート

Android 12 では、以下を使用したステートフル動作のサポートが追加されています。 必要があります。

このウィジェットはまだステートレスであるため、アプリが状態を保存し、状態変化イベントを登録できるようにする必要があります。

ステートフル動作を示すショッピング リスト ウィジェットの例
図 3. ステートフル動作の例。
で確認できます。

次のコードサンプルは、これらのコンポーネントを実装する方法を示しています。

Kotlin

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true)

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2)

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
        R.id.my_checkbox,
        RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent)
)

Java

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true);

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2);

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
    R.id.my_checkbox,
    RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent));

レイアウトを 2 つ用意します。1 つは Android 12 または res/layout-v31は高く、もう 1 つのターゲティングは以前 Android 11 以前(デフォルトの res/layout フォルダ)

角の丸みを実装する

Android 12 では、次のシステム パラメータが導入され、 ウィジェットの角の丸みの半径:

  • system_app_widget_background_radius: ウィジェットの背景の角の半径です。 28 dp

  • system_app_widget_inner_radius: ウィジェット内のビューのコーナー半径です。正確に 8 dp 背景の半径よりも小さくして、8 dp の使用時に適切に配置されるようにします。 調整できます。

次の例は、system_app_widget_background_radius をウィジェットの角に、system_app_widget_inner_radius をウィジェット内のビューに使用したウィジェットを示しています。

ウィジェットの背景の半径と、ウィジェット内のビューを表示しているウィジェット
図 4. 角が丸い。

1 ウィジェットの角。

2 ウィジェット内のビューの角。

角の丸みに関する重要な考慮事項

  • サードパーティのランチャーとデバイス メーカーは、 system_app_widget_background_radius パラメータを 28 dp 未満にする必要があります。 system_app_widget_inner_radius パラメータは常に system_app_widget_background_radius の値。
  • ウィジェットが @android:id/background を使用していないか、背景を定義していない場合 アウトラインに基づいてコンテンツをクリップします(android:clipToOutline を使用)。 true に設定すると、ランチャーは自動的にバックグラウンドと 最大 16 dp の角の丸い長方形を使用してウィジェットをクリップします。 ウィジェットの互換性を確認する Android 12

ウィジェットを以前のバージョンの Android と互換性を持たせるため、 カスタム属性を定義し、カスタムテーマを使用してその属性をオーバーライドできます。 Android 12(以下のサンプル XML ファイルに示す)

/values/attrs.xml

<resources>
  <attr name="backgroundRadius" format="dimension" />
</resources>

/values/styles.xml

<resources>
  <style name="MyWidgetTheme">
    <item name="backgroundRadius">@dimen/my_background_radius_dimen</item>
  </style>
</resources>

/values-31/styles.xml

<resources>
  <style name="MyWidgetTheme" parent="@android:style/Theme.DeviceDefault.DayNight">
    <item name="backgroundRadius">@android:dimen/system_app_widget_background_radius</item>
  </style>
</resources>

/drawable/my_widget_background.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="rectangle">
  <corners android:radius="?attr/backgroundRadius" />
  ...
</shape>

/layout/my_widget_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  ...
  android:background="@drawable/my_widget_background" />