App widgets for home screen
Alex Chen
Jan 2026
2 tabs
package com.example.myapp.widget
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.widget.RemoteViews
import com.example.myapp.R
import com.example.myapp.ui.MainActivity
class PostsWidget : AppWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
appWidgetIds.forEach { appWidgetId ->
updateAppWidget(context, appWidgetManager, appWidgetId)
}
}
override fun onEnabled(context: Context) {
// First widget added - perform initial setup
}
override fun onDisabled(context: Context) {
// Last widget removed - cleanup
}
companion object {
fun updateAppWidget(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int
) {
// Create an Intent to launch MainActivity
val pendingIntent: PendingIntent = Intent(context, MainActivity::class.java)
.let { intent ->
PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_IMMUTABLE
)
}
// Create refresh intent
val refreshIntent = Intent(context, PostsWidget::class.java).apply {
action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, intArrayOf(appWidgetId))
}
val refreshPendingIntent = PendingIntent.getBroadcast(
context,
0,
refreshIntent,
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)
val views = RemoteViews(context.packageName, R.layout.widget_posts).apply {
setOnClickPendingIntent(R.id.widget_container, pendingIntent)
setOnClickPendingIntent(R.id.refresh_button, refreshPendingIntent)
// Set collection adapter for list
val listIntent = Intent(context, PostsWidgetService::class.java).apply {
putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
}
setRemoteAdapter(R.id.widget_list, listIntent)
// Set empty view
setEmptyView(R.id.widget_list, R.id.empty_view)
}
appWidgetManager.updateAppWidget(appWidgetId, views)
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.widget_list)
}
}
}
package com.example.myapp.widget
import android.content.Context
import android.content.Intent
import android.widget.RemoteViews
import android.widget.RemoteViewsService
import com.example.myapp.R
import com.example.myapp.data.repository.PostRepository
class PostsWidgetService : RemoteViewsService() {
override fun onGetViewFactory(intent: Intent): RemoteViewsFactory {
return PostsRemoteViewsFactory(this.applicationContext)
}
}
class PostsRemoteViewsFactory(
private val context: Context
) : RemoteViewsService.RemoteViewsFactory {
private var posts: List<Post> = emptyList()
override fun onCreate() {
// Setup
}
override fun onDataSetChanged() {
// Fetch data - this runs on UI thread but can be synchronous
// In real app, fetch from repository
posts = getDummyPosts()
}
override fun onDestroy() {
posts = emptyList()
}
override fun getCount(): Int = posts.size
override fun getViewAt(position: Int): RemoteViews {
val post = posts[position]
return RemoteViews(context.packageName, R.layout.widget_post_item).apply {
setTextViewText(R.id.post_title, post.title)
setTextViewText(R.id.post_author, post.author)
// Set click intent
val fillInIntent = Intent().apply {
putExtra("post_id", post.id)
}
setOnClickFillInIntent(R.id.post_item, fillInIntent)
}
}
override fun getLoadingView(): RemoteViews? = null
override fun getViewTypeCount(): Int = 1
override fun getItemId(position: Int): Long = posts[position].id.toLong()
override fun hasStableIds(): Boolean = true
private fun getDummyPosts(): List<Post> {
return listOf(
Post(1, "Post 1", "Body", "Author 1", 0L),
Post(2, "Post 2", "Body", "Author 2", 0L)
)
}
}
2 files · kotlin
Explain with highlit
App Widgets display app content on the home screen. I extend AppWidgetProvider, a BroadcastReceiver subclass handling widget lifecycle. onUpdate() refreshes widget UI, onEnabled() initializes on first widget added, onDisabled() cleans up when last removed. RemoteViews builds UI since widgets run in launcher process—limited to specific layouts and views. AppWidgetManager updates widgets with updateAppWidget(). Configuration activities customize widgets before placement. Pending intents enable click handling. Collections use RemoteViewsService for ListView or GridView. Widgets update via alarms, broadcasts, or WorkManager. They provide glanceable information and quick actions without opening the app.