App-Widget mit Glance erstellen

In den folgenden Abschnitten wird beschrieben, wie Sie mit Glance ein einfaches App-Widget erstellen.

AppWidget im Manifest deklarieren

Nachdem Sie die Einrichtungsschritte ausgeführt haben, deklarieren Sie das AppWidget und seine Metadaten in Ihrer App.

  1. Erweitern Sie den AppWidget-Empfänger von GlanceAppWidgetReceiver:

    class MyAppWidgetReceiver : GlanceAppWidgetReceiver() {
        override val glanceAppWidget: GlanceAppWidget = TODO("Create GlanceAppWidget")
    }

  2. Registrieren Sie den Anbieter des App-Widgets in der Datei AndroidManifest.xml und der zugehörigen Metadatendatei:

        <receiver android:name=".glance.MyReceiver"
        android:exported="true">
        <intent-filter>
            <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
        </intent-filter>
        <meta-data
            android:name="android.appwidget.provider"
            android:resource="@xml/my_app_widget_info" />
    </receiver>
    

AppWidgetProviderInfo-Metadaten hinzufügen

Folgen Sie als Nächstes der Anleitung zum Erstellen eines Widgets, um die App -Widget-Informationen in der @xml/my_app_widget_info Datei zu erstellen und zu definieren.

Der einzige Unterschied bei Glance besteht darin, dass es kein initialLayout-XML gibt, das Sie aber definieren müssen. Sie können das vordefinierte Ladelayout verwenden, das in der Bibliothek bereitgestellt wird:

<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/glance_default_loading_layout">
</appwidget-provider>

`AppWidgetProviderInfo`-XML deklarieren

Das AppWidgetProviderInfo-Objekt definiert die wesentlichen Eigenschaften Ihres Widgets. Definieren Sie AppWidgetProviderInfo in der XML-Metadatenressourcendatei (res/xml/my_app_widget_info.xml) in einem <appwidget-provider> Element:

<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/glance_default_loading_layout"
    android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
    android:resizeMode="horizontal|vertical"
    android:widgetCategory="home_screen"
    android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>

Attribute für die Widgetgröße

Die Standardpositionen für Widgets auf dem Startbildschirm werden in einem Fenster basierend auf einem Raster aus Zellen mit einer definierten Höhe und Breite festgelegt. Auf den meisten Startbildschirmen können Widgets nur Größen annehmen, die ganzzahlige Vielfache der Rasterzellen sind, z. B. zwei Zellen horizontal und drei Zellen vertikal.

Mit den Attributen für die Widgetgröße können Sie eine Standardgröße für Ihr Widget angeben und untere und obere Grenzwerte für die Größe des Widgets festlegen. In diesem Zusammenhang ist die Standardgröße eines Widgets die Größe, die das Widget annimmt, wenn es zum ersten Mal dem Startbildschirm hinzugefügt wird.

In der folgenden Tabelle werden die <appwidget-provider> Attribute beschrieben, die sich auf die Widgetgröße beziehen:

Attribute und Beschreibung
targetCellWidth und targetCellHeight (Android 12), minWidth und minHeight
  • Ab Android 12 geben die targetCellWidth und targetCellHeight Attribute die Standardgröße des Widgets in Bezug auf Raster Zellen an. Diese Attribute werden in Android 11 und niedriger ignoriert und können ignoriert werden, wenn der Startbildschirm kein rasterbasiertes Layout unterstützt.
  • Die minWidth und minHeight Attribute geben die Standardgröße des Widgets in dp an. Wenn die Werte für die Mindestbreite oder ‑höhe eines Widgets nicht mit den Abmessungen der Zellen übereinstimmen, werden die Werte auf die nächste Zellengröße aufgerundet.
Wir empfehlen, beide Attributsätze anzugeben: targetCellWidth und targetCellHeight sowie minWidth und minHeight. So kann Ihre App auf minWidth und minHeight zurückgreifen, wenn das Gerät des Nutzers targetCellWidth und targetCellHeight nicht unterstützt. Wenn die Attribute targetCellWidth und targetCellHeight Vorrang haben, haben sie Vorrang vor den Attributen minWidth und minHeight.
minResizeWidth und minResizeHeight Geben Sie die absolute Mindestgröße des Widgets an. Diese Werte geben die Größe an, unter der das Widget unleserlich oder anderweitig unbrauchbar ist. Mit diesen Attributen kann der Nutzer die Größe des Widgets auf eine Größe verkleinern, die kleiner als die Standardgröße des Widgets ist. Das Attribut minResizeWidth wird ignoriert, wenn es größer als minWidth ist oder wenn die horizontale Größenänderung nicht aktiviert ist. Siehe resizeMode. Ebenso wird das minResizeHeight Attribut ignoriert, wenn es größer als minHeight ist oder wenn die vertikale Größenänderung nicht aktiviert ist.
maxResizeWidth und maxResizeHeight Geben Sie die empfohlene maximale Größe des Widgets an. Wenn die Werte kein Vielfaches der Abmessungen der Rasterzellen sind, werden sie auf die nächste Zellengröße aufgerundet. Das Attribut maxResizeWidth wird ignoriert, wenn es kleiner als minWidth ist oder wenn die horizontale Größenänderung nicht aktiviert ist. Siehe resizeMode. Ebenso wird das maxResizeHeight Attribut ignoriert, wenn es kleiner als minHeight ist oder wenn die vertikale Größenänderung nicht aktiviert ist. In Android 12 eingeführt.
resizeMode Gibt die Regeln an, nach denen die Größe eines Widgets geändert werden kann. Mit diesem Attribut können Sie die Größe von Widgets auf dem Startbildschirm horizontal, vertikal, oder auf beiden Achsen ändern. Nutzer halten ein Widget gedrückt, um die Ziehpunkte für die Größenänderung anzuzeigen, und ziehen dann die horizontalen oder vertikalen Ziehpunkte, um die Größe im Layoutraster zu ändern. Zu den Werten für das Attribut resizeMode gehören horizontal, vertical und none. Wenn Sie ein Widget als horizontal und vertikal anpassbar deklarieren möchten, verwenden Sie horizontal|vertical.

Beispiel

Um zu veranschaulichen, wie sich die Attribute in der vorherigen Tabelle auf die Widgetgröße auswirken, nehmen wir die folgenden Spezifikationen an:

  • Eine Rasterzelle ist 30 dp breit und 50 dp hoch.
  • Die folgende Attributspezifikation wird bereitgestellt:
<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" />

Ab Android 12 :

Verwenden Sie die Attribute targetCellWidth und targetCellHeight als Standardgröße des Widgets.

Die Standardgröße des Widgets ist 2 × 2. Die Größe des Widgets kann auf 2 × 1 verkleinert oder auf 4 × 3 vergrößert werden.

Android 11 und niedriger :

Verwenden Sie die Attribute minWidth und minHeight, um die Standardgröße des Widgets zu berechnen.

Standardbreite = Math.ceil(80 / 30) = 3

Standardhöhe = Math.ceil(80 / 50) = 2

Die Standardgröße des Widgets ist 3 × 2. Die Größe des Widgets kann auf 2 × 1 verkleinert oder auf Vollbildgröße vergrößert werden.

Zusätzliche Widgetattribute

In der folgenden Tabelle werden die <appwidget-provider> Attribute beschrieben, die sich auf andere Eigenschaften als die Widgetgröße beziehen.

Attribute und Beschreibung
updatePeriodMillis Defines how often the widget framework requests an update from the GlanceAppWidgetReceiver by calling the onUpdate() callback method. Wir empfehlen, so selten wie möglich zu aktualisieren, höchstens einmal pro Stunde, um den Akku zu schonen. Weitere Informationen finden Sie im Abschnitt Wann sollten Widgets aktualisiert werden? unter Glance-Statusverwaltung.
initialLayout Verweist auf die Layoutressource, die das Ladelayout des Widgets definiert, bevor die Glance-UI-Kompositionen gerendert werden. Sie können das vordefinierte Ladelayout verwenden, das in der Bibliothek bereitgestellt wird: @layout/glance_default_loading_layout.
configure Definiert die Konfigurationsaktivität, die gestartet wird, wenn der Nutzer das Widget hinzufügt. Weitere Informationen finden Sie im Abschnitt Widget-Konfigurationsaktivität implementieren auf dieser Seite.
description Gibt die Beschreibung an, die in der Widget-Auswahl für Ihr Widget angezeigt werden soll. In Android 12 eingeführt.
previewLayout (Android 12) und previewImage (Android 11 und niedriger)
  • Ab Android 12 gibt das previewLayout Attribut eine skalierbare Vorschau an, die Sie als XML-Layout in der Standardgröße des Widgets bereitstellen. Im Idealfall, dies verweist auf eine statische XML-Zuordnung, die Ihrem Designlayout entspricht.
  • In Android 11 oder niedriger gibt das previewImage Attribut einen statischen Screenshot des Widgets an, der in der Widget-Auswahl angezeigt wird.
Wir empfehlen, beides anzugeben, damit Ihre App auf älteren Plattformen ordnungsgemäß funktioniert. Für neuere Plattformen (Android 15 und höher) können Sie mit `GlanceAppWidget.providePreview` live generierte Vorschauen in Kotlin definieren. Weitere Informationen finden Sie in der Anleitung zu generierten Vorschauen.
autoAdvanceViewId Gibt die Ansichts-ID der Widget-Unteransicht an, die vom Host des Widgets automatisch weitergeleitet wird.
widgetCategory Gibt an, ob Ihr Widget auf dem Startbildschirm (home_screen), dem Sperrbildschirm (keyguard) oder beiden angezeigt werden kann. Für Android 5.0 und höher ist nur home_screen gültig.
widgetFeatures Gibt die vom Widget unterstützten Funktionen an. Wenn die Konfiguration Ihres Widgets beispielsweise optional ist, geben Sie sowohl configuration_optional als auch reconfigurable an.

GlanceAppWidget definieren

  1. Erstellen Sie eine neue Klasse, die von GlanceAppWidget abgeleitet wird, und überschreibt die provideGlance Methode. Mit dieser Methode können Sie Daten laden, die zum Rendern Ihres Widgets erforderlich sind:

    finden Sie unter Coroutinen für die Hauptthread-Sicherheit verwenden.

    class MyAppWidget : GlanceAppWidget() {
    
        override suspend fun provideGlance(context: Context, id: GlanceId) {
    
            // In this method, load data needed to render the AppWidget.
            // Use `withContext` to switch to another thread for long running
            // operations.
    
            provideContent {
                // create your AppWidget here
                Text("Hello World")
            }
        }
    }

  2. Instanziieren Sie sie in glanceAppWidget in Ihrem GlanceAppWidgetReceiver:

    class MyAppWidgetReceiver : GlanceAppWidgetReceiver() {
    
        // Let MyAppWidgetReceiver know which GlanceAppWidget to use
        override val glanceAppWidget: GlanceAppWidget = MyAppWidget()
    }

Sie haben jetzt ein AppWidget mit Glance konfiguriert.

Klasse „GlanceAppWidgetReceiver“ zum Verarbeiten von Widget-Broadcasts verwenden

Der GlanceAppWidgetReceiver koordiniert Widget-Broadcasts und Plattformstatus aktualisierungen, indem er den zugrunde liegenden AppWidgetProvider erweitert. Er empfängt Plattformereignisse, wenn Ihr Widget aktualisiert, gelöscht, aktiviert oder deaktiviert wird, und übersetzt sie in Compose-Lebenszyklusanfragen.

Widget im Manifest deklarieren

Deklarieren Sie die Unterklasse GlanceAppWidgetReceiver als Broadcast-Empfänger in der Datei AndroidManifest.xml:

<receiver android:name="ExampleAppWidgetReceiver"
          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/my_app_widget_info" />
</receiver>

Das <receiver> Element erfordert das android:name Attribut, das die Empfängerklasse angibt. Der Empfänger muss die ACTION_APPWIDGET_UPDATE Broadcast-Aktion im <intent-filter> akzeptieren.

Das <meta-data> Element muss als Name android.appwidget.provider angeben und das android:resource Attribut muss auf Ihre XML-Metadatenressource AppWidgetProviderInfo (@xml/my_app_widget_info) verweisen.

Klasse „GlanceAppWidgetReceiver“ implementieren

In Glance erweitern Sie GlanceAppWidgetReceiver anstelle von AppWidgetProvider direkt. Implementieren Sie es, indem Sie Ihren Empfänger mit Ihrer GlanceAppWidget-Instanz verknüpfen. Die primären Callbacks, die in GlanceAppWidgetReceiver verfügbar sind, funktionieren so:

  • onUpdate(): Wird automatisch von Glance überschrieben, um Kompositionsaktualisierungen auszuführen. Wenn Sie onUpdate manuell überschreiben, müssen Sie super.onUpdate aufrufen, damit Glance Kompositionsthreads erfolgreich starten kann.
  • onAppWidgetOptionsChanged(): Wird aufgerufen, wenn das Widget zum ersten Mal platziert oder in der Größe geändert wird. Glance liest Options-Bundle-Elemente im Hintergrund, sodass Ihr Layout nahtlos an die Laufzeitdimensionen angepasst wird.
  • onDeleted(Context, IntArray): Wird aufgerufen, wenn eine bestimmte Widget-Instanz vom Nutzer gelöscht wird.
  • onEnabled(Context): Wird ausgelöst, wenn die erste Instanz Ihres Widgets erfolgreich erstellt wurde. Ideal für die Ausführung globaler Migrationen.
  • onDisabled(Context): Wird aufgerufen, wenn die letzte aktive Instanz des Anbieters entfernt wird.
  • onReceive(Context, Intent): Fängt jeden Plattform-Broadcast vor bestimmten Callback-Methoden ab. Sie müssen sicherstellen, dass jede benutzerdefinierte Empfängerlogik die Sie schreiben, super.onReceive(context, intent) aufruft und niemals selbst goAsync aufruft, da Glance die Arbeit automatisch asynchron weiterleitet.

Widget-Broadcast-Intents empfangen

Im Hintergrund filtert und verarbeitet GlanceAppWidgetReceiver die folgenden grundlegenden Widget-Broadcast-Intents der Plattform:

UI erstellen

Das folgende Snippet zeigt, wie Sie die UI erstellen:

/* Import Glance Composables
 In the event there is a name clash with the Compose classes of the same name,
 you may rename the imports per https://kotlinlang.org/docs/packages.html#imports
 using the `as` keyword.

import androidx.glance.Button
import androidx.glance.layout.Column
import androidx.glance.layout.Row
import androidx.glance.text.Text
*/
class MyAppWidget : GlanceAppWidget() {

    override suspend fun provideGlance(context: Context, id: GlanceId) {
        // Load data needed to render the AppWidget.
        // Use `withContext` to switch to another thread for long running
        // operations.

        provideContent {
            // create your AppWidget here
            MyContent()
        }
    }

    @Composable
    private fun MyContent() {
        Column(
            modifier = GlanceModifier.fillMaxSize(),
            verticalAlignment = Alignment.Top,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(text = "Where to?", modifier = GlanceModifier.padding(12.dp))
            Row(horizontalAlignment = Alignment.CenterHorizontally) {
                Button(
                    text = "Home",
                    onClick = actionStartActivity<MyActivity>()
                )
                Button(
                    text = "Work",
                    onClick = actionStartActivity<MyActivity>()
                )
            }
        }
    }
}

Das vorherige Codebeispiel führt folgende Schritte aus:

  • In der obersten Ebene Column werden Elemente vertikal nacheinander platziert.
  • Die Column wird so erweitert, dass sie dem verfügbaren Platz entspricht (über die GlanceModifier), und der Inhalt wird oben (verticalAlignment) und horizontal zentriert (horizontalAlignment) ausgerichtet.
  • Der Inhalt der Column wird mit der Lambda-Funktion definiert. Die Reihenfolge ist wichtig.
    • Das erste Element in der Column ist eine Text-Komponente mit einem Abstand von 12.dp.
    • Das zweite Element ist eine Row, in der Elemente horizontal nacheinander platziert werden, mit zwei Buttons, die horizontal zentriert sind (horizontalAlignment). Die endgültige Anzeige hängt vom verfügbaren Platz ab. Die folgende Abbildung zeigt ein Beispiel dafür, wie das aussehen kann:
destination_widget
Abbildung 1 Beispiel-UI.

Sie können die Ausrichtungswerte ändern oder verschiedene Modifikatorwerte (z. B. Abstand) anwenden, um die Platzierung und Größe der Komponenten zu ändern. Eine vollständige Liste der Komponenten, Parameter und verfügbaren Modifikatoren für jede Klasse finden Sie in der Referenz dokumentation.

Abgerundete Ecken implementieren

In Android 12 werden Systemparameter eingeführt, mit denen Sie die Eckradien Ihrer App-Widgets dynamisch anpassen können:

  • system_app_widget_background_radius: Gibt den Eckradius des Widget-Hintergrundcontainers an (nie größer als 28 dp).
  • Innenradius:Um zu verhindern, dass Inhalte abgeschnitten werden, berechnen Sie einen proportionalen Radius für Ihre internen Inhalte basierend auf der Systemhintergrundkontur: systemRadiusValue - widgetPadding

In Glance können Sie Eigenschaften für die Eckradiusgröße dynamisch in der Komposition mit GlanceModifier.cornerRadius(android.R.dimen.system_app_widget_background_radius) anwenden.

Für die Abwärtskompatibilität auf Geräten mit Android 11 (API-Level 30) oder niedriger implementieren Sie benutzerdefinierte Attribute und Fallbacks für benutzerdefinierte Designressourcen:

  • /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>