Glance ile uygulama widget'ı oluşturma

manifest, metadata

Aşağıdaki bölümlerde, Glance ile temel bir uygulama widget'ının nasıl oluşturulacağı açıklanmaktadır.

Manifest dosyasında AppWidget öğesini bildirin

Kurulum adımlarını tamamladıktan sonra uygulamanızda AppWidget ve meta verilerini bildirin.

  1. AppWidget alıcısını GlanceAppWidgetReceiver tarihinden itibaren uzatın:

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

  2. Uygulama widget'ının sağlayıcısını AndroidManifest.xml dosyanıza ve ilişkili meta veri dosyasına kaydedin:

        <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 meta verilerini ekleyin.

Ardından, @xml/my_app_widget_info dosyasında uygulama widget'ı bilgilerini oluşturmak ve tanımlamak için Widget oluşturma kılavuzundaki adımları uygulayın.

Glance'taki tek fark, initialLayout XML'nin olmamasıdır ancak bir tane tanımlamanız gerekir. Kitaplıkta sağlanan önceden tanımlanmış yükleme düzenini kullanabilirsiniz:

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

AppWidgetProviderInfo XML'ini bildirme

AppWidgetProviderInfo nesnesi, widget'ınızın temel özelliklerini tanımlar. XML meta veri kaynak dosyanızdaki AppWidgetProviderInfo öğesini <appwidget-provider> öğesi içinde tanımlayın: (res/xml/my_app_widget_info.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/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>

Widget boyutlandırma özellikleri

Varsayılan ana ekran, widget'ları penceresinde belirli bir yüksekliğe ve genişliğe sahip hücrelerden oluşan bir ızgaraya göre konumlandırır. Çoğu ana ekranda widget'lar yalnızca ızgara hücrelerinin tam sayı katları olan boyutları alabilir. Örneğin, yatayda iki hücreye, dikeyde üç hücreye denk gelen boyutlar.

Widget boyutlandırma özellikleri, widget'ınız için varsayılan bir boyut belirtmenize ve widget'ın boyutuyla ilgili alt ve üst sınırları sağlamanıza olanak tanır. Bu bağlamda, widget'ın varsayılan boyutu, widget'ın ana ekrana ilk kez eklendiğinde aldığı boyuttur.

Aşağıdaki tabloda, widget boyutlandırmayla ilgili <appwidget-provider> özellikleri açıklanmaktadır:

Özellikler ve açıklama
targetCellWidth ve targetCellHeight (Android 12), minWidth ve minHeight
  • Android 12'den itibaren targetCellWidth ve targetCellHeight özellikleri, widget'ın varsayılan boyutunu ızgara hücreleri açısından belirtir. Bu özellikler Android 11 ve önceki sürümlerde yoksayılır. Ana ekran, ızgara tabanlı düzeni desteklemiyorsa yoksayılabilir.
  • minWidth ve minHeight özellikleri, widget'ın dp cinsinden varsayılan boyutunu belirtir. Bir widget'ın minimum genişlik veya yükseklik değerleri hücrelerin boyutlarıyla eşleşmiyorsa değerler en yakın hücre boyutuna yuvarlanır.
Uygulamanız, kullanıcının cihazı targetCellWidth ve targetCellHeight özelliklerini desteklemiyorsa minWidth ve minHeight özelliklerini kullanmaya geri dönebilmesi için her iki özellik grubunu da (targetCellWidth ve targetCellHeight ile minWidth ve minHeight) belirtmenizi öneririz. Destekleniyorsa targetCellWidth ve targetCellHeight özellikleri, minWidth ve minHeight özelliklerine göre öncelikli olur.
minResizeWidth ve minResizeHeight Widget'ın mutlak minimum boyutunu belirtin. Bu değerler, widget'ın okunamayacak veya kullanılamayacak kadar küçük olduğu boyutu belirtir. Bu özellikleri kullanarak kullanıcı, widget'ı varsayılan widget boyutundan daha küçük bir boyuta yeniden boyutlandırabilir. minResizeWidth özelliği, minWidth değerinden büyükse veya yatay yeniden boyutlandırma etkin değilse yoksayılır. resizeMode sayfasına göz atın. Benzer şekilde, minResizeHeight özelliği minHeight değerinden büyükse veya dikey yeniden boyutlandırma etkin değilse yoksayılır.
maxResizeWidth ve maxResizeHeight Widget'ın önerilen maksimum boyutunu belirtin. Değerler, ızgara hücresi boyutlarının katı değilse en yakın hücre boyutuna yuvarlanır. maxResizeWidth özelliği, minWidth değerinden küçükse veya yatay yeniden boyutlandırma etkin değilse yoksayılır. resizeMode sayfasına göz atın. Benzer şekilde, maxResizeHeight özelliği minHeight değerinden küçükse veya dikey yeniden boyutlandırma etkin değilse yoksayılır. Android 12'de kullanıma sunulmuştur.
resizeMode Bir widget'ın yeniden boyutlandırılabilmesini sağlayan kuralları belirtir. Bu özelliği, ana ekran widget'larının yatay, dikey veya her iki eksende de yeniden boyutlandırılabilir olmasını sağlamak için kullanabilirsiniz. Kullanıcılar, yeniden boyutlandırma tutma yerlerini göstermek için bir widget'a dokunup basılı tutar, ardından düzen ızgarasında boyutunu değiştirmek için yatay veya dikey tutma yerlerini sürükler. resizeMode özelliği için değerler arasında horizontal, vertical ve none yer alır. Bir widget'ı yatay ve dikey olarak yeniden boyutlandırılabilir ilan etmek için horizontal|vertical kullanın.

Örnek

Önceki tablodaki özelliklerin widget boyutlandırmasını nasıl etkilediğini göstermek için aşağıdaki özellikleri varsayalım:

  • Bir ızgara hücresi 30 dp genişliğinde ve 50 dp yüksekliğindedir.
  • Aşağıdaki özellik spesifikasyonu sağlanır:
<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'den itibaren:

targetCellWidth ve targetCellHeight özelliklerini widget'ın varsayılan boyutu olarak kullanın.

Widget'ın boyutu varsayılan olarak 2x2'dir. Widget, 2x1 veya 4x3 boyutlarına kadar yeniden boyutlandırılabilir.

Android 11 ve önceki sürümler:

Widget'ın varsayılan boyutunu hesaplamak için minWidth ve minHeight özelliklerini kullanın.

Varsayılan genişlik = Math.ceil(80 / 30) = 3

Varsayılan yükseklik = Math.ceil(80 / 50) = 2

Widget'ın boyutu varsayılan olarak 3x2'dir. Widget'ın boyutu 2x1'e kadar küçültülebilir veya tam ekrana kadar büyütülebilir.

Ek widget özellikleri

Aşağıdaki tabloda, widget boyutlandırması dışındaki niteliklerle ilgili <appwidget-provider> özellikleri açıklanmaktadır.

Özellikler ve açıklama
updatePeriodMillis Widget çerçevesinin, onUpdate() geri çağırma yöntemini çağırarak GlanceAppWidgetReceiver öğesinden ne sıklıkta güncelleme isteyeceğini tanımlar. Pilden tasarruf etmek için mümkün olduğunca seyrek (saatte en fazla bir kez) güncellemenizi öneririz. Ayrıntılar için Glance durum yönetimi bölümündeki Widget'ları ne zaman güncellemelisiniz? başlıklı makaleyi inceleyin.
initialLayout Glance kullanıcı arayüzü kompozisyonları oluşturulmadan önce widget'ın yükleme düzenini tanımlayan düzen kaynağını gösterir. Kitaplıkta sağlanan önceden tanımlanmış yükleme düzenini (@layout/glance_default_loading_layout) kullanabilirsiniz.
configure Kullanıcı widget'ı eklediğinde başlatılan yapılandırma etkinliğini tanımlar. Bu sayfadaki Widget yapılandırma etkinliği uygulama bölümüne bakın.
description Widget seçicide widget'ınız için gösterilecek açıklamayı belirtir. Android 12'de kullanıma sunulmuştur.
previewLayout (Android 12) ve previewImage (Android 11 ve önceki sürümler)
  • Android 12'den itibaren previewLayout özelliği, ölçeklenebilir bir önizleme belirtir. Bu önizlemeyi, widget'ın varsayılan boyutuna ayarlanmış bir XML düzeni olarak sağlarsınız. İdeal olarak bu, tasarım düzeninize uygun statik bir XML eşlemeye işaret eder.
  • Android 11 veya önceki sürümlerde previewImage özelliği, widget seçicide görünen ve widget'ın nasıl göründüğünü gösteren statik bir resim çizilebilir ekran görüntüsünü belirtir.
Uygulamanızın eski platformlarda sorunsuz bir şekilde geri dönmesi için her ikisini de belirtmenizi öneririz. Daha yeni platformlarda (Android 15 ve sonraki sürümler) `GlanceAppWidget.providePreview` kullanarak Kotlin'de canlı olarak oluşturulan önizlemeler tanımlayabilirsiniz. Oluşturulan Önizlemeler kılavuzuna bakın.
autoAdvanceViewId Widget'ın ana makinesi tarafından otomatik olarak ilerletilen widget alt görünümünün görünüm kimliğini belirtir.
widgetCategory Widget'ınızın ana ekranda (home_screen), kilit ekranında (keyguard) veya her ikisinde de gösterilip gösterilemeyeceğini bildirir. Android 5.0 ve sonraki sürümlerde yalnızca home_screen geçerlidir.
widgetFeatures Widget tarafından desteklenen özellikleri bildirir. Örneğin, widget'ınızın yapılandırması isteğe bağlıysa hem configuration_optional hem de reconfigurable öğesini belirtin.

GlanceAppWidget sözcüğünü tanımla

  1. GlanceAppWidget sınıfından türeyen ve provideGlance yöntemini geçersiz kılan yeni bir sınıf oluşturun. Bu yöntem, widget'ınızı oluşturmak için gereken verileri yükleyebileceğiniz yerdir:

    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. GlanceAppWidgetReceiver cihazınızdaki glanceAppWidget içinde başlatın:

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

Artık Glance'i kullanarak bir AppWidget yapılandırdınız.

Widget yayınlarını işlemek için AppWidgetProvider sınıfını kullanma

GlanceAppWidgetReceiverKoordinatlar widget'ı, temel AppWidgetProvider'ı genişleterek yayınları ve platform durumunu günceller. Widget'ınız güncellendiğinde, silindiğinde, etkinleştirildiğinde veya devre dışı bırakıldığında platform etkinliklerini alır ve bunları Compose yaşam döngüsü isteklerine çevirir.

Manifest dosyasında widget bildirme

GlanceAppWidgetReceiver sınıf alt sınıfınızı AndroidManifest.xml dosyanızda yayın alıcısı olarak bildirin:

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

<receiver> öğesi, alıcı sınıfını belirten android:name özelliğini gerektirir. Alıcı, ACTION_APPWIDGET_UPDATE <intent-filter> içinde yayın işlemini kabul etmelidir.

<meta-data> öğesi adını android.appwidget.provider olarak tanımlamalı ve android:resource özelliği, AppWidgetProviderInfo XML meta veri kaynağınıza (@xml/my_app_widget_info) işaret etmelidir.

AppWidgetProvider sınıfını uygulama

Bir Bakış'ta, GlanceAppWidgetReceiver öğesini doğrudan AppWidgetProvider yerine uzatırsınız. Alıcınızı GlanceAppWidget örneğinize bağlayarak bu özelliği uygulayın. GlanceAppWidgetReceiver içinde kullanılabilen birincil geri çağırma işlevleri aşağıdaki gibi çalışır:

  • onUpdate(): Bileşen güncellemelerini yürütmek için Glance tarafından otomatik olarak geçersiz kılınır. onUpdate değerini manuel olarak geçersiz kılarsanız Glance'in kompozisyon iş parçacıklarını başarıyla başlatmasına izin vermek için super.onUpdate değerini çağırmanız gerekir.
  • onAppWidgetOptionsChanged(): Widget ilk yerleştirildiğinde veya yeniden boyutlandırıldığında çağrılır. Glance okuma seçenekleri, öğeleri arka planda paketler. Böylece düzeniniz, çalışma zamanı boyutlarına göre sorunsuz bir şekilde ayarlanır.
  • onDeleted(Context, IntArray): Belirli bir widget örneği kullanıcı tarafından her silindiğinde çağrılır.
  • onEnabled(Context): Widget'ınızın ilk örneği başarıyla oluşturulduğunda tetiklenir. Küresel taşımaları çalıştırmak için mükemmeldir.
  • onDisabled(Context): Sağlayıcının son etkin örneği kaldırıldığında çağrılır.
  • onReceive(Context, Intent): Belirli geri çağırma yöntemlerinden önce her platform yayınını yakalar. Yazdığınız özel alıcı mantığının super.onReceive(context, intent) işlevini çağırdığından emin olmanız gerekir ve Glance, işi otomatik olarak eşzamansız yönlendirdiğinden goAsync işlevini asla kendiniz çağırmamalısınız.

Widget yayın amaçlarını alma

GlanceAppWidgetReceiver, temel platform widget'ı yayın amaçlarını filtreler ve aşağıdaki gibi işler:

Kullanıcı arayüzü oluşturma

Aşağıdaki snippet'te kullanıcı arayüzünün nasıl oluşturulacağı gösterilmektedir:

/* 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>()
                )
            }
        }
    }
}

Yukarıdaki kod örneği şunları yapar:

  • En üst düzeyde Column öğeler dikey olarak birbirinin altına yerleştirilir.
  • Column, GlanceModifier aracılığıyla kullanılabilir alana uyacak şekilde boyutunu genişletir, içeriğini üste (verticalAlignment) hizalar ve yatay olarak ortalar (horizontalAlignment).
  • Column öğesinin içeriği lambda kullanılarak tanımlanır. Sıra önemlidir.
    • Column içindeki ilk öğe, 12.dp dolguya sahip bir Text bileşenidir.
    • İkinci öğe, öğelerin yatay olarak yan yana yerleştirildiği bir Row'dir. Yatay olarak ortalanmış iki Buttons bulunur (horizontalAlignment). Son görüntü, mevcut alana bağlıdır. Aşağıdaki resimde, bu durumun nasıl görünebileceğine dair bir örnek verilmiştir:
destination_widget
Şekil 1. Kullanıcı arayüzü örneği.

Hizalama değerlerini değiştirebilir veya bileşenlerin yerleşimini ve boyutunu değiştirmek için farklı değiştirici değerler (ör. dolgu) uygulayabilirsiniz. Bileşenlerin, parametrelerin ve her sınıf için kullanılabilen değiştiricilerin tam listesi için referans belgelerine bakın.

Yuvarlak köşeleri uygulama

Android 12, uygulama widget'larınızın köşe yarıçaplarını dinamik olarak özelleştirmek için sistem parametrelerini kullanıma sunar:

  • system_app_widget_background_radius: Widget arka plan container'ının köşe yarıçapını belirtir (28 dp'den büyük olamaz).
  • İç yarıçap: İçeriğin kırpılmasını önlemek için sistem arka plan ana hattına göre iç içeriğiniz için orantılı bir yarıçap hesaplayın: systemRadiusValue - widgetPadding

Glance'te, GlanceModifier.cornerRadius(android.R.dimen.system_app_widget_background_radius) kullanarak kompozisyonda köşe yarıçapı boyutlandırma özelliklerini dinamik olarak uygulayabilirsiniz.

Android 11 (API düzeyi 30) veya daha eski sürümleri çalıştıran cihazlarda geriye dönük uyumluluk için özel özellikler ve özel tema kaynağı geri dönüşleri uygulayın:

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