如何从配置/主活动更新 Compose Glance 小部件的 AppWidget 状态?



我的最新想法是使用

updateAppWidgetState(context = context, definition = PreferencesGlanceStateDefinition, glanceId = glanceId) {
// ...
}

GlanceWidget().update(context = context, glanceId = glanceId)

但我无法访问 glanceId。

问题的背景是,我想将 uid 添加到 AppWidgetState 中,如以下问题中所述:如何获取 Compose Glance 小部件的 AppWidgetId?

如何获取 glanceId(例如,从我在配置活动中有权访问的 appWidgetId 中)或者我还能如何实现这一点?

几个月后,我终于解决了自己的问题。随着一个月前发布的版本 1.0.0-alpha04,有了新的getGlanceIdBy方法。

从现有 appWidgetId 或从配置活动中获取 GlanceId 的新方法 (Icb70c, b/230391946)

我的代码现在如下所示:

// Try block because getGlanceIdBy throws IllegalArgumentException if no GlanceId is found for this appWidgetId.
try {
val glanceAppWidgetManager = GlanceAppWidgetManager(context)
val glanceId: GlanceId = glanceAppWidgetManager.getGlanceIdBy(appWidgetId)
updateAppWidgetState(context = context, glanceId = glanceId) {
it[intPreferencesKey("uid")] = uid
}
val glanceAppWidget: GlanceAppWidget = GlanceWidget()
glanceAppWidget.update(context, glanceId)
} catch (e: IllegalArgumentException) {
Log.d(TAG, "No GlanceId found for this appWidgetId.")
}

我们正在研究这个问题。目前最好的选择是使用 getGlanceIds(..) 方法使用GlanceAppWidgetManager检索与GlanceAppWidget关联的最后一个GlanceId

这确实不理想,但目前它应该有效。

我正在获取这段代码的id。也许它对你有用。

val glanceId =
GlanceAppWidgetManager(context).getGlanceIds(YourAppWidget::class.java).firstOrNull()

理想情况下,您将一些信息附加到状态,以便您不需要GlanceId即可识别状态。您可以在渲染应用程序小部件时生成特定于应用程序的唯一 ID(如果您希望每个小组件不同),也可以依赖某些配置(在这种情况下,具有相同配置的所有小组件都将以相同的方式处理)。

完成此操作后,您可以使用现有GlanceAppWidget.updateIf更新具有给定状态的应用程序微件。

如果你想要更多的组合行为(如你所建议的:更新状态,然后更新应用程序小部件),你可以检查GlanceAppWidget.updateIf的实现(它实际上是4行长,只使用公共方法)并使其适应你的确切需求。

如果你试图在你的 GlanceAppWidget 类中获取 GlanceId,你可以使用

val glanceId = LocalGlanceId.current 
//You can use this only in @Composable annoted methods. You can get id in composable method

如果你试图让 GlanceId 外部或其他类,你可以使用

val glanceId = GlanceAppWidgetManager(context).getGlanceIds(BasicGlanceWidget::class.java).last() 
//getGlanceIds is a suspend func so don't forget to use coroutine

从任何有Context的地方更新您的小部件:

fun updateWidgets(context: Context) {
val widgetProvider = YourGlanceWidgetReceiver::class.java
val comp = ComponentName(context, widgetProvider)
val ids = AppWidgetManager.getInstance(context)
.getAppWidgetIds(comp)
val intent = Intent(context, widgetProvider).apply {
this.action = AppWidgetManager
.ACTION_APPWIDGET_UPDATE
this.putExtra(
AppWidgetManager.EXTRA_APPWIDGET_IDS,
ids
)
}
context.sendBroadcast(intent)
}

这将调用您GlanceWidgetReceiver中的update(),而又会调用您GlanceAppWidgetContent()

最新更新