kotlin
147 lines · 2 tabs
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.
Related snips
kotlin
package com.example.myapp
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
Dependency injection with Hilt
kotlin
android
hilt
by Alex Chen
3 tabs
kotlin
package com.example.myapp.ui
import androidx.lifecycle.*
import kotlinx.coroutines.launch
class UserViewModel(
LiveData transformations and mediators
kotlin
android
livedata
by Alex Chen
1 tab
kotlin
package com.example.myapp.utils
import android.os.Build
import android.os.StrictMode
import android.os.Trace
import timber.log.Timber
Performance optimization and profiling
kotlin
android
performance
by Alex Chen
2 tabs
kotlin
package com.example.myapp.data.repository
import com.example.myapp.data.local.PostDao
import com.example.myapp.data.local.PostEntity
import com.example.myapp.data.remote.ApiService
import com.example.myapp.models.Post
Unit testing with JUnit and MockK
kotlin
android
testing
by Alex Chen
2 tabs
kotlin
package com.example.myapp.utils
import android.app.NotificationChannel
import android.app.NotificationChannelGroup
import android.app.NotificationManager
import android.app.PendingIntent
Notification channels and categories
kotlin
android
notifications
by Alex Chen
1 tab
kotlin
package com.example.myapp.data.remote
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
Retrofit for REST API networking
kotlin
android
retrofit
by Alex Chen
2 tabs
Share this code
Here's the card — post it anywhere.