Membuat widget dengan fitur Sekilas

1. Sebelum memulai

Codelab ini memandu Anda menjalani proses membuat widget aplikasi untuk SociaLite. Pertama, Anda akan membuat widget Glance sederhana, dan menambahkannya ke SociaLite dan layar utama. Selanjutnya, Anda akan menambahkan status kosong ke widget menggunakan komponen dan tema Glance. Lalu, codelab ini akan memandu Anda dalam mendukung interaksi pengguna untuk memilih kontak favorit dari widget Anda. Terakhir, Anda akan mempelajari cara memperbarui widget dari aplikasi Anda.

Prasyarat

  • Pengetahuan Kotlin dasar.
  • Penyelesaian codelab Menyiapkan Android Studio, atau memahami cara menggunakan Android Studio dan menguji aplikasi di emulator Android 15 atau di perangkat fisik yang menjalankan Android 15.
  • Pengetahuan Hilt dasar.
  • Pengetahuan Compose dasar. Glance tidak menggunakan composable dari Jetpack Compose, tetapi Glance menggunakan kembali framework dan gaya coding-nya.

Yang akan Anda pelajari dalam codelab ini

  • Cara mengonfigurasi aplikasi Anda untuk mendukung widget.
  • Cara menggunakan komponen Glance untuk membuat tata letak responsif.
  • Cara menggunakan GlanceTheme untuk mendukung warna dinamis pada layar utama pengguna.
  • Cara menangani interaksi pengguna di widget.
  • Cara memperbarui widget dari aplikasi.

Yang Anda butuhkan

  • Versi terbaru Android Studio.
  • Perangkat pengujian atau emulator yang menjalankan Android 12 atau yang lebih baru.
  • SDK Android 12 atau yang lebih baru.

Layar Utama Android yang menampilkan widget Socialite

2. Memulai persiapan

Mendapatkan kode awal

  1. Jika Anda telah menyelesaikan codelab Menangani penerapan layar penuh di Android 15 atau Menambahkan animasi fitur Kembali prediktif, lanjutkan ke bagian Menambahkan Widget karena Anda sudah memiliki kode awalnya.
  2. Download kode awal dari GitHub.

Atau, Anda dapat membuat clone repositori dan melihat branch codelab_improve_android_experience_2024.

 git clone git@github.com:android/socialite.git
 cd socialite
 git checkout codelab_improve_android_experience_2024
  1. Buka SociaLite di Android Studio, lalu jalankan aplikasi di perangkat atau emulator Android 15 Anda. Anda akan melihat layar yang terlihat seperti berikut:

fb043d54dd01b3e5.png

SociaLite dengan navigasi gestur

3. Menambahkan widget

Apa itu widget?

Widget adalah bagian dari aplikasi Anda yang dapat disematkan di dalam aplikasi Android lainnya. Biasanya, aplikasi disematkan di layar utama pengguna.

Menambahkan widget ke aplikasi Anda dapat memberi pengguna kemampuan untuk memulai tugas umum dengan cepat, melihat informasi sekilas, dan menyesuaikan perangkat mereka dengan konten Anda.

Apa itu Glance?

Jetpack Glance adalah library untuk menulis widget menggunakan API seperti Compose di Kotlin. Glance memiliki beberapa keunggulan yang sama dengan Compose, seperti rekomposisi, kode UI deklaratif yang ditulis dalam Kotlin, dan komponen yang beropini. Glance menghilangkan sebagian besar kebutuhan akan tampilan jarak jauh XML di widget Anda.

Membuat widget

Widget di Android dideklarasikan di AndroidManifest sebagai elemen<receiver>. Penerima ini harus diekspor, tangani android.appwidget.action.APPWIDGET_UPDATE tindakan intent, dan sediakan file pengaturan widget aplikasi melalui elemen metadata bernama android.appwidget.provider.

Menambahkan widget ke SociaLite

Layar Utama Android yang menampilkan widget Socialite

Anda ingin menambahkan widget ke Socialite yang memungkinkan pengguna melihat kontak favorit mereka dan apakah mereka memiliki pesan yang belum dibaca dari orang tersebut. Jika ya, mengetuk widget akan membawa pengguna ke chat kontak favoritnya. Selain itu, Anda menggunakan komponen dan penerapan tema Glance untuk memastikan widget terlihat baik dengan menggunakan desain responsif dan warna dinamis.

Untuk memulai, tambahkan widget "Halo Dunia" ke Socialite. Setelah itu, perluas kemampuan widget Anda.

Untuk melakukannya, lakukan hal berikut:

  1. Tambahkan dependensi Glance ke aplikasi Anda.
  2. Buat implementasi GlanceAppWidget.
  3. Buat GlanceAppWidgetReceiver.
  4. Konfigurasi widget Anda dengan file XML info widget aplikasi.
  5. Tambahkan info penerima dan widget aplikasi ke file AndroidManifest.xml.

Menambahkan Glance ke project

Kode awal telah menambahkan versi Glance dan koordinat library ke katalog versi SociaLite: libs.versions.toml.

libs.versions.toml

[versions]
//..

glance = "1.1.0-beta02"

[libraries]
glance-appwidget = { group = "androidx.glance", name = "glance-appwidget", version.ref = "glance" }
glance-material = { group = "androidx.glance", name = "glance-material3", version.ref = "glance" }

Selain itu, dependensi Glance disertakan dalam file app/build.gradle.kts SociaLite.

build.gradle.kts
dependencies {
...
implementation(libs.glance.appwidget)
implementation(libs.glance.material)

...
}
  • Jika Anda memodifikasi file ini, sinkronkan project untuk mendownload library Glance.

Membuat GlanceAppWidget dan GlanceAppWidgetReceiver

Android menggunakan penerima siaran untuk memberi tahu SociaLite bahwa widget telah ditambahkan, perlu diperbarui, atau telah dihapus. Glance menyediakan class penerima abstrak, GlanceAppWidgetReceiver, yang memperluas AppWidgetProvider.

Implementasi GlanceAppWidgetReceiver juga bertanggung jawab untuk menyediakan instance GlanceAppWidget. Class ini merender composable Glance menjadi tampilan jarak jauh.

Kode awal ini menyertakan dua class : SocialiteAppWidget, yang memperluas GlanceAppWidget, dan SocialiteAppWidgetReceiver, yang memperluas GlanceAppWidgetReceiver.

Untuk memulai, ikuti langkah-langkah berikut:

  1. Buka paket widget di app/src/main/java/com/google/android/samples/socialite/.
  2. Buka class SociaLiteAppWidget. Class ini menggantikan metode provideGlance.
  3. Ganti TODO dengan panggilan ke provideContent lalu teruskan fungsi composable widget Anda sebagai parameter. Untuk sekarang, widget hanya menampilkan pesan Hello World, tetapi nanti Anda akan menambahkan lebih banyak fungsi di codelab ini.
package com.google.android.samples.socialite.widget

import android.content.Context
import androidx.glance.GlanceId
import androidx.glance.GlanceTheme
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.provideContent
import androidx.glance.text.Text

class SociaLiteAppWidget : GlanceAppWidget() {
   override suspend fun provideGlance(context: Context, id: GlanceId) {
       provideContent {
           GlanceTheme {
               Text("Hello World")
           }
       }
   }
}
  1. Buka class SociaLiteAppWidgetReceiver dalam paket widget. Untuk sekarang, penerima Anda menyediakan instance SociaLiteWidget, tetapi nanti Anda akan menambahkan lebih banyak fungsi di bagian yang akan datang.
  2. Ganti TODO dengan konstruktor SociaLiteAppWidget():
package com.google.android.samples.socialite.widget

import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver

class SociaLiteAppWidgetReceiver : GlanceAppWidgetReceiver() {
   override val glanceAppWidget: GlanceAppWidget = SociaLiteAppWidget()
}

Anda sekarang siap mengonfigurasi Android untuk menampilkan widget Anda dan memungkinkan pengguna untuk menambahkannya ke layar utama mereka.

Menambahkan informasi penyedia widget aplikasi

  1. Klik kanan res/xml > New > XML resource file.
  2. Masukkan socialite_widget_info sebagai nama file dan appwidget-provider sebagai elemen root, lalu klik OK. File ini menyertakan metadata untuk appwidget Anda yang digunakan oleh AppWidgetHost untuk menampilkan widget pada awalnya.
  3. Tambahkan kode berikut ke file socialite_widget_info.xml:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
   android:resizeMode="horizontal|vertical"
   android:updatePeriodMillis="3600000"
   android:minHeight="128dp"
   android:minWidth="128dp"

   android:minResizeHeight="128dp"
   android:minResizeWidth="128dp"
   android:configure="com.google.android.samples.socialite.widget.SociaLiteAppWidgetConfigActivity"
   android:widgetFeatures="configuration_optional|reconfigurable"
   android:previewImage="@drawable/widget_preview"
   android:maxResizeHeight="512dp"
   android:maxResizeWidth="512dp"
   android:targetCellWidth="2"
   android:targetCellHeight="2"
   android:initialLayout="@layout/glance_default_loading_layout">
</appwidget-provider>

Tabel berikut memberikan ringkasan atribut dalam kode ini dan menjelaskan masing-masing atribut:

Nama atribut

Deskripsi

resizeMode

Widget Anda dapat diubah ukurannya secara vertikal dan horizontal.

targetCellWidth, targetCellHeight

Menentukan ukuran default widget saat ditambahkan ke layar utama.

updatePeriodMillis

Mengontrol kapan host widget dapat memutuskan untuk me-refresh widget Anda. Aplikasi Anda dapat memperbarui widget Anda kapan pun widget sedang berjalan dan memiliki informasi baru untuk ditampilkan.

minResizeHeight,minResizeWidth

Menyetel seberapa kecil Anda dapat mengubah ukuran widget.

minHeight,minWidth

Menentukan ukuran default minimum widget saat ditambahkan ke layar utama.

initialLayout

Menyediakan tata letak awal yang ditampilkan saat Glance merender composable.

previewImage

Menyediakan gambar statis widget untuk ditampilkan di alat pilih widget.

widgetFeatures

Menunjukkan berbagai fitur yang didukung oleh widget. Ini merupakan petunjuk bagi host widget dan tidak benar-benar mengubah perilaku widget.

Dalam codelab ini, flag Anda memberi tahu host bahwa widget tidak memerlukan konfigurasi sebelum widget ditambahkan ke layar utama dan bahwa widget dapat dikonfigurasi setelah ditambahkan.

configure

Nama class aktivitas konfigurasi. Ini adalah aktivitas yang nanti mengonfigurasi widget.

Untuk melihat semua atribut yang tersedia, termasuk fitur di API 31 atau yang lebih baru, lihat AppWidgetProviderInfo.

Perbarui AndroidManifest dan uji

Akhirnya, Anda siap untuk memperbarui file AndroidManifest.xml dan menguji widget Anda. Anda mendefinisikan elemen receiver sebagai turunan elemen application dalam file. Penerima ini menangani intent APPWIDGET_UPDATE dan memberikan metadata appwidget ke Peluncur Android.

Untuk memulai, ikuti langkah-langkah berikut:

  1. Buat elemen receiver untuk SociaLiteAppWidgetReceiver yang akan diekspor. Salin dan tempel yang berikut ke file AndroidManifest.xml setelah elemen application:
<receiver
   android:name=".widget.SociaLiteAppWidgetReceiver"
   android:exported="true"
   android:label="Favorite Contact">

   <intent-filter>
       <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
   </intent-filter>

   <meta-data
       android:name="android.appwidget.provider"
       android:resource="@xml/socialite_widget_info" />
</receiver>
  1. Kompilasikan dan jalankan aplikasi Anda.
  2. Setelah aplikasi berjalan, tambahkan widget ke layar utama Anda. Misalnya, di Pixel, tekan lama latar belakang Anda, pilih Widget > SociaLite. Anda akan dapat menambahkan widget ke layar utama Anda.

Di Layar Utama Android yang menampilkan widget pekerjaan yang sedang berlangsung. Widgetnya transparan dan menampilkan pesan

Widget Anda bertuliskan "Halo Dunia" dan memiliki latar belakang transparan. Harus diakui, ini bukan widget yang paling bagus tampilannya ataupun yang paling fungsional. Di bagian berikutnya, Anda menambahkan tata letak yang lebih rumit dan mempercantik widget dengan percikan warna Desain Material.

4. Memperbaiki desain

Sekarang, Anda memiliki widget statis yang tidak memiliki banyak fitur yang menjadikannya widget yang bagus. Widget yang baik melakukan hal berikut:

  • Menjaga konten tetap segar dan singkat, serta menjaga fungsi tetap sederhana.
  • Meminimalkan celah yang tidak nyaman melalui tata letak yang dapat diubah ukurannya.
  • Menerapkan warna dari latar belakang host widget aplikasi.

Untuk diskusi mendalam tentang apa yang membuat widget bagus, lihat Widget.

Menambahkan scaffold

Sekarang Anda memperbarui widget Anda untuk ditampilkan di komponen Scaffold Glance.

Scaffold disediakan oleh library Glance. Ini adalah API slot sederhana untuk menampilkan UI widget dengan TitleBar. Ini menyetel warna latar belakang ke GlanceTheme.colors.widgetBackground dan menerapkan padding. Ini akan menjadi komponen tingkat atas Anda.

Untuk memulai, ikuti langkah-langkah berikut:

  1. Ganti implementasi SociaLiteAppWidget dengan kode berikut:
package com.google.android.samples.socialite.widget

import android.content.Context
import androidx.compose.runtime.Composable
import androidx.glance.GlanceId
import androidx.glance.GlanceModifier
import androidx.glance.GlanceTheme
import androidx.glance.ImageProvider
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.components.Scaffold
import androidx.glance.appwidget.components.TitleBar
import androidx.glance.appwidget.provideContent
import androidx.glance.layout.fillMaxSize
import androidx.glance.text.Text
import com.google.android.samples.socialite.R

class SociaLiteAppWidget : GlanceAppWidget() {
   override suspend fun provideGlance(context: Context, id: GlanceId) {
       provideContent {
           GlanceTheme() {
               Content()
           }
       }
   }

   @Composable
   private fun Content() {
       Scaffold(titleBar = {TitleBar(startIcon = ImageProvider(R.drawable.ic_launcher_monochrome), title = "SociaLite")},
           modifier = GlanceModifier.fillMaxSize()) {
           Text("Hello World")
       }
   }
}
  1. Untuk melihat pembaruan Anda, jalankan ulang aplikasi lalu tambahkan salinan widget baru ke layar utama Anda.

Di Layar Utama Android yang menampilkan widget pekerjaan yang sedang berlangsung. Widget memiliki latar belakang dan judul tidak transparan

Ingat, widget adalah tampilan jarak jauh yang ditampilkan oleh host eksternal. Kemudian, Anda menambahkan kemampuan untuk memperbarui widget di dalam aplikasi secara otomatis. Sebelum itu, Anda harus menambahkan widget dari alat pilih widget untuk melihat perubahan kode.

Seperti yang Anda lihat, hasilnya jauh lebih baik, tetapi jika Anda membandingkan widget Anda dengan widget lain, warnanya tampak tidak pas. Di layar utama, widget biasanya akan mengatur warnanya berdasarkan setelan tema pengguna. Dengan token warna dinamis, Anda dapat membuat tema widget Anda beradaptasi dengan wallpaper dan tema perangkat Anda.

Menambahkan warna dinamis

Sekarang Anda menambahkan token warna widgetBackground ke latar belakang scaffold dan token warna onSurface ke teks dan Komponen teks TitleBar. Untuk memperbarui gaya teks, Anda perlu mengimpor classTextStyle Glance. Untuk memperbarui latar belakang scaffold, Anda menetapkan properti backgroundColor Scaffold ke GlanceTheme.colors.widgetBackground.

Untuk memulai, ikuti langkah-langkah berikut:

  1. Sertakan impor baru tersebut dalam file SociaLiteAppWidget.kt.
//Add to the imports section of your Kotlin code.
import androidx.glance.text.TextStyle
  1. Perbarui composable Content untuk menambahkan widgetBackground.
Scaffold(
   titleBar = {
       TitleBar(
           textColor = GlanceTheme.colors.onSurface,
           startIcon = ImageProvider(R.drawable.ic_launcher_monochrome),
           title = "SociaLite",
       )
   },
   backgroundColor = GlanceTheme.colors.widgetBackground,
   modifier = GlanceModifier.fillMaxSize(),
) {
   Text(text = "Hello World", style = TextStyle(color = GlanceTheme.colors.onSurface))
}
  1. Untuk melihat pembaruan Anda, jalankan ulang aplikasi dan tambahkan salinan widget baru ke layar utama Anda.

Temanya cocok dengan widget lain di layar utama, dan secara otomatis memperbarui warna jika Anda mengubah latar belakang atau mengatur mode gelap. Untuk latar belakang yang benar-benar berwarna, widget beradaptasi dengan bagian latar belakang tempatnya berada.

Di Layar Utama Android yang menampilkan widget Halo Dunia dengan tema terangLayar utama dengan tema terang

Di Layar Utama Android yang menampilkan widget Halo Dunia dengan tema gelap.Layar utama dengan tema gelap

Menambahkan status kosong

Sekarang Anda perlu memikirkan tentang status dan mengonfigurasi widget Anda. Saat widget ditambahkan ke layar utama dan memerlukan konfigurasi, sebaiknya tampilkan status kosong. Status kosong meminta pengguna mengonfigurasi widget. Anda menambahkan aktivitas konfigurasi ke widget Anda dan menautkannya dari status kosong.

Codelab ini menyediakan class untuk menyimpan, mengakses, dan mengubah status konfigurasi widget. Anda akan menambahkan kode untuk memperbarui UI widget agar menampilkan status ini, dan membuat tindakan lambda untuk menangani tindakan ketukan pengguna.

Meninjau model widget

Luangkan waktu untuk meninjau class dalam paket com.google.android.samples.socialite.widget.model.

Ini termasuk class WidgetModel, serta class WidgetModelDao dan WidgetModelRepository. Class ini sudah ada dalam kode awal codelab dan menangani penyimpanan status widget ke database Room yang mendasarinya. Selain itu, class ini menggunakan Hilt untuk mengelola siklus prosesnya.

Class WidgetModel berisi widgetId yang ditetapkan oleh Android, contactId kontak SociaLite yang ditampilkannya, displayName dan photo yang akan ditampilkan, dan Boolean jika kontak memiliki pesan yang belum dibaca. Ini dipakai oleh composable SociaLiteAppWidget dan ditampilkan di dalam widget.

WidgetModelDao adalah objek akses data yang mengabstraksi akses ke database SociaLite. WidgetModelRepository menyediakan fungsi praktis untuk membuat, membaca, memperbarui, dan menghapus instance WidgetModel. Class ini dibuat oleh Hilt dan dimasukkan ke dalam aplikasi dengan pemasukan dependensi.

  • Buka file WidgetModel.kt dalam paket model yang ada di app/src/main/java/com/google/android/samples/socialite/widget/model/.

Ini adalah class data dengan anotasi Entity. Setiap instance widget diberi ID khusus oleh Android dan ID ini digunakan oleh SociaLite sebagai kunci utama untuk data model. Setiap instance model melacak informasi dasar kontak terkait dan apakah ada pesan yang belum terbaca dari kontak tersebut.

@Entity(
    foreignKeys = [
        ForeignKey(
            entity = Contact::class,
            parentColumns = ["id"],
            childColumns = ["contactId"],
            onDelete = ForeignKey.CASCADE,
        ),
    ],
    indices = [
        Index("widgetId"),
        Index("contactId"),
    ],
)
data class WidgetModel(
    @PrimaryKey val widgetId: Int,
    val contactId: Long,
    val displayName: String,
    val photo: String,
    val unreadMessages: Boolean = false,
) : WidgetState

Status kosong

Anda ingin composable Content memuat model widget dari WidgetModelRepository dan menampilkan status kosong jika tidak ada model yang tersedia; jika tidak, Anda ingin menampilkan konten normal widget Anda. Untuk saat ini, ini akan menjadi pesan "Halo Dunia" Anda, tetapi di bagian berikutnya Anda membuat antarmuka yang lebih baik.

Anda akan mengganti composable Content dengan ekspresi when yang menampilkan composable ZeroState, atau placeholder Text.

  1. Dalam metode provideGlance, di luar composable Anda, dapatkan referensi ke WidgetModelRepository dan ID widget saat ini. Tambahkan baris berikut sebelum provideContent dalam metode SociaLiteAppWidget provideGlance.
override suspend fun provideGlance(context: Context, id: GlanceId) {
   val widgetId = GlanceAppWidgetManager(context).getAppWidgetId(id)
   val repository = WidgetModelRepository.get(context)

Anda mungkin juga perlu menambahkan impor berikut:

import com.google.android.samples.socialite.widget.model.WidgetModel
import com.google.android.samples.socialite.widget.model.WidgetModelRepository
import com.google.android.samples.socialite.widget.model.WidgetState.Loading
import androidx.glance.appwidget.GlanceAppWidgetManager
  1. Dalam fungsi composable Content, tambahkan ID repositori dan widget sebagai parameter, dan gunakan untuk memuat model Anda. Perbarui tanda tangan fungsi composable Content dan tambahkan baris berikut:
private fun Content(repository: WidgetModelRepository, widgetId: Int) {
   val model = repository.loadModel(widgetId).collectAsState(Loading).value
  1. Jika Android Studio tidak menambahkan impor berikut secara otomatis, tambahkan secara manual:.
import androidx.compose.runtime.collectAsState

Anda juga perlu memperbarui provideGlance untuk meneruskan ID widget dan repositori ke Content.

Ganti provideGlance dengan yang berikut:

override suspend fun provideGlance(context: Context, id: GlanceId) {
        val widgetId = GlanceAppWidgetManager(context).getAppWidgetId(id)
        val repository = WidgetModelRepository.get(context)

        provideContent {
            GlanceTheme {
                Content(repository, widgetId)
            }
        }
    }
  1. Dalam fungsi composable Content, tentukan status mana yang akan ditampilkan berdasarkan keberadaan suatu model. Pindahkan Scaffold konten widget ke composable ZeroState dengan mengganti komponen Scaffold komponen dan isinya dengan blok ini:
   when (model) {
       is WidgetModel -> {Text("Hello World")}
       else -> ZeroState(widgetId)
   }

Composable ZeroState sudah disertakan di kode awal dalam paket com.google.android.samples.socialite.widget.ui.

  1. Jika Android Studio tidak secara otomatis mengimpor paketcom.google.android.samples.socialite.widget.ui, tambahkan kode berikut ke bagian impor SociaLiteAppWidget.
import com.google.android.samples.socialite.widget.ui.ZeroState
  1. Untuk melihat pembaruan Anda, jalankan ulang aplikasi dan tambahkan salinan widget baru ke layar utama Anda. Anda akan melihat widget menampilkan komponen ZeroState dan Tombol. Tombol akan membuka aktivitas konfigurasi saat Anda mengkliknya, dan di bagian berikutnya Anda akan memperbarui status widget dari aktivitas ini.

Layar Utama Android yang menampilkan Status Kosong dari widget SociaLite. Status kosong memiliki satu tombol.

Aktivitas Konfigurasi AppWidget SociaLite menampilkan 4 pilihan kontak.

Aktivitas konfigurasi

Tinjau fungsi Composable ZeroState. Fungsi ini ditemukan dalam paket com.google.android.samples.socialite.widget.ui di file ZeroState.kt.

@Composable
fun ZeroState(widgetId: Int) {
   val widgetIdKey = ActionParameters.Key<Int>(AppWidgetManager.EXTRA_APPWIDGET_ID)
Scaffold(
   titleBar = {
       TitleBar(
           modifier = GlanceModifier.clickable(actionStartActivity(MainActivity::class.java)),
           textColor = GlanceTheme.colors.onSurface,
           startIcon = ImageProvider(R.drawable.ic_launcher_monochrome),
           title = "SociaLite",
       )
   },
   backgroundColor = GlanceTheme.colors.widgetBackground,
   modifier = GlanceModifier.fillMaxSize(),
) {
   Box(modifier = GlanceModifier.fillMaxSize(), contentAlignment = Alignment.Center) {
       Button(
           text = "Select Favorite Contact",
           onClick = actionStartActivity<SociaLiteAppWidgetConfigActivity>(
               parameters = actionParametersOf(widgetIdKey to widgetId),
           ),
       )
   }
}

}

Composable Scaffold dipindahkan ke composable ZeroState. TitleBar memiliki pengubah clickable, yang membuka aktivitas utama SociaLite. ZeroState Anda menggunakan composable Button Glance untuk menampilkan pesan ajakan (CTA) kepada pengguna dan, ketika diklik, akan membuka aktivitas SociaLiteAppWidgetConfigActivity dan menyertakan ID widget sebagai ekstra intent. Kedua tindakan ini menggunakan actionStartActivity fungsi praktis Glance. Untuk informasi lebih lanjut tentang tindakan, lihat Menangani interaksi pengguna.

  1. Tinjau bagaimana SociaLiteAppWidgetConfigActivity digunakan untuk memperbarui konfigurasi widget Anda. Class ini juga merupakan aktivitas konfigurasi untuk widget Anda. Aktivitas konfigurasi membaca ekstra bilangan bulat intent dengan kunci AppWidgetManager.*EXTRA_APPWIDGET_ID.*Untuk informasi lebih lanjut tentang aktivitas konfigurasi, lihat Memungkinkan pengguna mengonfigurasi widget aplikasi.
  2. Di SociaLiteAppWidgetConfigActivity, ganti TODO di properti ContactRow onClick dengan kode berikut:
{
  coroutineScope.launch {

     widgetModelRepository.createOrUpdate(
       WidgetModel(
           appWidgetId,
           contact.id,
           contact.name,
           contact.iconUri.toString(),
           false,
       ),
     )
     SociaLiteAppWidget().updateAll(this@SociaLiteAppWidgetConfigActivity)
     val resultValue = Intent().putExtra(
       AppWidgetManager.EXTRA_APPWIDGET_ID,
       appWidgetId,
     )
     setResult(RESULT_OK, resultValue)
     finish()
  }
}

Tambahkan penyertaan berikut jika Android Studio tidak melakukannya secara otomatis

import com.google.android.samples.socialite.widget.model.WidgetModel
import androidx.glance.appwidget.updateAll
import kotlinx.coroutines.launch

Blok kode ini memperbarui status widget Anda. Pertama, blok kode menggunakan repositori untuk menyimpan atau memperbarui WidgetModel dengan informasi dari kontak yang dipilih. Selanjutnya, blok kode ini memanggil fungsi penangguhan updateAll. Fungsi ini memperbarui semua widget di layar utama dan dapat dipanggil dari mana saja di aplikasi Anda. Terakhir, blok ini menetapkan hasil aktivitas konfigurasi untuk memberi sinyal bahwa widget berhasil diperbarui.

  1. Jalankan dan ganti widget Anda di layar utama. Anda akan melihat status kosong yang baru.

Layar Utama Android yang menampilkan Status Kosong dari widget SociaLite. Status kosong memiliki satu tombol.

  1. Klik Pilih kontak favorit. Ini membawa Anda ke aktivitas konfigurasi.

Screenshot aktivitas konfigurasi yang menampilkan empat kontak untuk dipilih Di Layar Utama Android yang menampilkan widget Halo Dunia dengan tema terang

  1. Pilih kontak. Ini memperbarui widget Anda. Namun, widget belum menampilkan kontak favorit Anda karena Anda menambahkan kemampuan itu di bagian berikutnya.

Mengelola data widget

  1. Buka alat App inspection, hubungkan ke suatu proses jika perlu, dan pilih tab Database inspector untuk melihat isi database aplikasi.
  2. Pilih kontak favorit di widget dan lihat apakah diperbarui menjadi "Halo Dunia". Kembali ke alat App inspection, Anda akan melihat tabModel widget tab dengan satu entri untuk widget Anda. Anda mungkin perlu me-refresh tabel atau menekan Info terbaru langsung untuk melihat perubahannya.

dd030cce6a75be25.png

  1. Tambahkan widget lain dan pilih kontak lain. Anda mungkin harus menekan Refresh tabel atau Info terbaru langsung to untuk melihat model baru.
  2. Hapus widget dan perhatikan bahwa model tertinggal dalam database setelah widget dihapus.

Anda dapat memperbarui SociaLiteAppWidgetReceiver untuk membersihkan database Anda ketika widget dihapus dengan mengganti onDeleted.

Untuk membersihkan model widget yang usang, Anda dapat memanggil WidgetModelRepository.cleanupWidgetModels. Class repositori dikelola oleh Hilt dan Anda perlu menggunakan pemasukan dependensi untuk mengakses instance-nya.

  1. Dalam SociaLiteAppWidgetReceiver, tambahkan instance AndroidEntryPoint Anotasi Hilt ke deklarasi class penerima Anda dan memasukkan WidgetModelRepository.
  2. Panggil WidgetModelRepository.cleanupWidgetModels dalam metode penggantian untuk onDeleted.

Kode akan terlihat seperti ini:

package com.google.android.samples.socialite.widget

import android.content.Context
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.GlanceAppWidgetReceiver
import com.google.android.samples.socialite.widget.model.WidgetModelRepository
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

@AndroidEntryPoint
class SociaLiteAppWidgetReceiver : GlanceAppWidgetReceiver() {
   override val glanceAppWidget: GlanceAppWidget = SociaLiteAppWidget()

   @Inject
   lateinit var repository: WidgetModelRepository

   override fun onDeleted(context: Context, appWidgetIds: IntArray) {
       super.onDeleted(context, appWidgetIds)
       repository.cleanupWidgetModels(context)
   }

}
  1. Jalankan kembali aplikasi. Anda akan melihat bahwa baris model dihapus di App inspector jika widget dihapus dari layar utama.

5. Menambahkan UI Kontak dan mengupdate saat pesan baru tiba

Anda telah memasuki bagian akhir codelab ini. Untuk bagian ini, Anda menerapkan UI kontak akhir untuk widget dan memperbaruinya jika ada pesan yang belum terbaca untuk kontak tersebut.

  1. Tinjau class WidgetModelRepository Anda dalam paket model.

Di sinilah Anda memiliki metode praktis updateUnreadMessagesForContact; metode ini memperbarui widget yang terkait dengan ID kontak.

//Don't add this code.
fun updateUnreadMessagesForContact(contactId: Long, unread: Boolean) {
   coroutineScope.launch {
       widgetModelDao.modelsForContact(contactId).filterNotNull().forEach { model ->
           widgetModelDao.update(
             WidgetModel(model.widgetId, model.contactId, model.displayName, model.photo, unread)
           )
           SociaLiteAppWidget().updateAll(appContext)
       }
   }
}

Metode ini memiliki dua parameter: contactId, tID kontak yang sedang diperbarui dan unread, Boolean status pesan yang belum dibaca. Metode ini menggunakan WidgetModelDao, untuk menemukan semua model widget yang menampilkan kontak ini dan memperbarui model dengan status baca yang baru. Lalu, fungsi ini memanggil metode SociaLiteAppWidget().updateAll yang disediakan Glance untuk memperbarui semua widget di layar utama pengguna.

Sekarang setelah Anda memahami cara widget dan statusnya diperbarui, Anda dapat membuat UI kontak, mengirim pesan, dan melihatnya diperbarui. Untuk melakukannya, perbarui SociaLiteAppWidget dengan FavoriteContact composable di tata letak widget Anda. Dalam tata letak ini, Anda juga memeriksa apakah Anda harus menampilkan No new messages atau New Messages!.

  1. Tinjau file FavoriteContact.kt dalam paket com.google.android.samples.socialite.widget.ui.
//Don't add this code.
@Composable
fun FavoriteContact(model: WidgetModel, onClick: Action) {
   Column(
       modifier = GlanceModifier.fillMaxSize().clickable(onClick)
           .background(GlanceTheme.colors.widgetBackground).appWidgetBackground()
           .padding(bottom = 8.dp),
       verticalAlignment = Alignment.Vertical.Bottom,
       horizontalAlignment = Alignment.Horizontal.CenterHorizontally,
   ) {
       Image(
           modifier = GlanceModifier.fillMaxWidth().wrapContentHeight().defaultWeight()
               .cornerRadius(16.dp),
           provider = ImageProvider(model.photo.toUri()),
           contentScale = ContentScale.Crop,
           contentDescription = model.displayName,
       )
       Column(
           modifier = GlanceModifier.fillMaxWidth().wrapContentHeight().padding(top = 4.dp),
           verticalAlignment = Alignment.Vertical.Bottom,
           horizontalAlignment = Alignment.Horizontal.CenterHorizontally,
       ) {
           Text(
               text = model.displayName,
               style = TextStyle(
                   fontWeight = FontWeight.Bold,
                   fontSize = 24.sp,
                   color = (GlanceTheme.colors.onSurface),
               ),
           )

           Text(
               text = if (model.unreadMessages) "New Message!" else "No messages",
               style = TextStyle(
                   fontWeight = FontWeight.Bold,
                   fontSize = 16.sp,
                   color = (GlanceTheme.colors.onSurface),
               ),
           )
       }
   }
}
  1. Ganti Text("Hello World") dalam composable Content SociaLiteAppWidget dengan panggilan ke composable FavoriteContact.

Composable ini akan mengambil WidgetModel dan Action yang dibuat oleh actionStartActivity fungsi Glance.

  1. Tambahkan panggilan ke blok when sebelum ZeroState jika modelnya bukan WidgetModel.
when (model) {
  is WidgetModel -> FavoriteContact(model = model, onClick = actionStartActivity(
     Intent(LocalContext.current.applicationContext, MainActivity::class.java)
         .setAction(Intent.ACTION_VIEW)
         .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
         .setData("https://socialite.google.com/chat/${model.contactId}".toUri()))
  )
  else -> ZeroState(widgetId)
}
  1. Jika Android Studio tidak otomatis menambah paket ini, lakukan impor paket tersebut secara manual:
import com.google.android.samples.socialite.widget.ui.FavoriteContact
import androidx.glance.appwidget.action.actionStartActivity
import android.content.Intent
import com.google.android.samples.socialite.MainActivity
import androidx.core.net.toUri
  1. Jalankan aplikasi Anda.
  2. Pilih kontak favorit, kirim pesan, dan segera keluar dari aplikasi sebelum mereka merespons. Saat respons tiba, status widget akan berubah.
  3. Klik widget untuk membuka chat dan melihat bahwa status diperbarui lagi saat Anda keluar ke layar utama.

Di Layar Utama Android yang menampilkan widget Halo Dunia dengan tema terang

6. Selamat

Anda sudah berhasil menyelesaikan codelab dan mempelajari cara menulis widget menggunakan Glance! Anda akan merasa nyaman membuat widget cantik yang terlihat bagus di banyak layar utama, menangani input pengguna, dan memperbarui dirinya sendiri.

Untuk mendapatkan kode solusi main, ikuti langkah-langkah berikut:

  1. Jika Anda sudah mendownload SociaLite, jalankan perintah ini:
git checkout main
  1. Jika Anda belum mendownload SociaLite, download kode lagi untuk melihat cabang main:
git clone git@github.com:android/socialite.git

Pelajari lebih lanjut