0

I have created an Android Widget using Jetpack Glance, I need to update it using CoroutineWorker so I am using WorkManager for it, here is the sample code

class MyWidget : GlanceAppWidget() {

    companion object {
        val KEY_TOPIC = stringPreferencesKey("topic")
        val KEY_QUOTE = stringPreferencesKey("quote")
    }

    override val sizeMode = SizeMode.Exact

   // override var stateDefinition: GlanceStateDefinition<*> = PreferencesGlanceStateDefinition

    override suspend fun provideGlance(context: Context, id: GlanceId) {

        provideContent {

            val displayText = currentState(KEY_QUOTE) ?: "Quote not found"
            val topic = currentState(KEY_TOPIC) ?: ""

            GlanceTheme {
                Scaffold(
                    titleBar = {
                        TitleBar(startIcon = ImageProvider(R.mipmap.ic_launcher), title = "Hello")
                    }, backgroundColor = GlanceTheme.colors.widgetBackground
                ) {
                    Column(
                        modifier = GlanceModifier.background(color = Color.Red)
                            .padding(30.dp)
                    ) {
                        Text(
                            text = "Display Text is $displayText && Topic is $topic",
                            style = TextStyle(
                                color = ColorProvider(
                                    color = Color(0xFF000000)
                                ),
                                fontSize = 12.sp,
                                fontWeight = FontWeight.Medium
                            ),
                            modifier = GlanceModifier.clickable {
                                actionStartActivity(activity = MainActivity::class.java)
                            }
                        )

                        Button(
                            "Start Activity", onClick = actionStartActivity<MainActivity>(),
                            style = TextStyle(
                                color = ColorProvider(
                                    color = Color(0x00FF0000)
                                ),
                                fontSize = 12.sp,
                                fontWeight = FontWeight.Medium
                            ),
                        )
                    }
                }


            }
        }
    }


    override fun onCompositionError(
        context: Context,
        glanceId: GlanceId,
        appWidgetId: Int,
        throwable: Throwable
    ) {
        super.onCompositionError(context, glanceId, appWidgetId, throwable)
        val remoteView = RemoteViews(context.packageName, R.layout.custom_error_layout)
        Log.i("errorMessageis", "${throwable.message} ${throwable.localizedMessage}")
        remoteView.setTextViewText(
            R.id.textview,
            "${throwable.message} ${throwable.localizedMessage}"
        )
        AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId, remoteView)
    }


}


@HiltWorker
class CustomWorker @AssistedInject constructor(
    @Assisted val context: Context,
    @Assisted workerParameters: WorkerParameters,
) : CoroutineWorker(context, workerParameters) {

    override suspend fun doWork(): Result {

        CoroutineScope(Dispatchers.IO).launch {
            val currentTimeMillis = System.currentTimeMillis()
            val date = Date(currentTimeMillis)
            val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
            val formattedDate = sdf.format(date)

            val glanceIds =
                GlanceAppWidgetManager(context).getGlanceIds(MyWidget::class.java)
            glanceIds.forEach { id ->
                updateAppWidgetState(context, id) { prefs ->
                    prefs[KEY_QUOTE] = currentTimeMillis.toString()
                    prefs[KEY_TOPIC] = formattedDate
                }
                MyWidget().update(context, id)
            }
        }
        return Result.success()
    }
}

Now when I try to create widget from my installed android app, it just shows the loading screen which is created from android:initialLayout="@layout/glance_default_loading_layout"

Here is the complete source code I don't see any error messages as such

2 Answers 2

2
+200

I tried to run the app and it got stuck in an endless loop of starting workers when you create a widget. Apparently it was caused by the way you create WorkerFactory or rather that it should be HiltWorkerFactory. Refactoring MyApplication seemingly fixed it:

@HiltAndroidApp
class MyApplication : Application(), Configuration.Provider {

    @Inject
    lateinit var workerFactory: HiltWorkerFactory

    override val workManagerConfiguration: Configuration by lazy {
        Configuration.Builder()
            .setMinimumLoggingLevel(Log.DEBUG)
            .setWorkerFactory(workerFactory)
            .build()
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

According to the accepted answer in Android Jetpack Glance 1.0.0 : problems updating widget

It could not be updating due to Glance recomposing when calling the .update. You will need to provide a GlanceStateDefinition to return the updated version.

1 Comment

but my above code works if I update prefs[KEY_QUOTE] & prefs[KEY_TOPIC] on button click and remove CustomWorker

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.