如何使用来自 Activity 的数据更新小部件?

Posted

技术标签:

【中文标题】如何使用来自 Activity 的数据更新小部件?【英文标题】:How to update widget with data from Activity? 【发布时间】:2020-03-09 04:05:12 【问题描述】:

我想每秒用我的Activity 中的数据更新小部件。我有带有计时器的 Item,它通过 onBind 方法向它发送有效负载进行更新。每次它会更新数据并将新的(字符串、日期、颜色资源)发送到有效负载时,我想用这些数据更新现有的 Widget。随着计时器的进行,我应该每秒更新一次。 (每秒发送有效载荷)这可能吗?因为我可以将我的数据添加到 extras 并将 Intent 发送到AppWidgetProvider,但是我不知道如何使用发送到onReceive 的新数据来更新 Widget 中的视图。在 onUpdate 函数中尝试了此代码。我在 xml 中为小部件提供程序设置的每 1000 毫秒调用一次 - android:updatePeriodMillis="1000"。正在发生的事情是我的主屏幕上带有 Problem loading widget 文本的灰色框。日志中没有出现崩溃或错误。

RecyclerView 项:

private fun updateWidgetTimer(text: String, color: Int)
        val int = Intent(a, WidgetProvider::class.java)
        int.apply 
            putExtra(WidgetProvider.REM_TIME, text)
            putExtra(WidgetProvider.REM_TIME_COLOR, color)
            action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
        
    

AppWidgetProvider:

   private var time: String = ""
   private var color: Int = R.color.colorGreen
   override fun onUpdate(
        context: Context?,
        appWidgetManager: AppWidgetManager?,
        appWidgetIds: IntArray?
    ) 
        val remoteViews = RemoteViews(context?.packageName, R.layout.widget_custom_layout)
        remoteViews.setTextViewText(R.id.timer, time)
        context?.let 
            remoteViews.setTextColor(R.id.timer, ContextCompat.getColor(context, color))
        
    

    override fun onReceive(context: Context?, intent: Intent?) 
            super.onReceive(context, intent)

            val extras = intent?.extras

            extras?.let  
                time = extras.getString(REM_TIME)?:""
                color = extras.getInt(REM_TIME_COLOR)
            

        

更新: 有效负载已成功发送到 onReceive,但在调用 onUpdate 时,我的任何小部件都没有更新为新数据。

我更新的 onUpdate 函数示例:

override fun onUpdate(
        context: Context?,
        appWidgetManager: AppWidgetManager?,
        appWidgetIds: IntArray?
    ) 

        context?.let 
            val currWidgetInstanceName = ComponentName(context, WidgetProvider::class.java)
            val widgetManager = AppWidgetManager.getInstance(context)

            val widgetIds = widgetManager.getAppWidgetIds(currWidgetInstanceName)

            widgetIds?.forEach wId->
                val remoteViews = RemoteViews(context.packageName, R.layout.widget_layout)
                remoteViews.apply 
                    //set info title
                    setTextViewText(R.id.title, title)

                    //set subtitle
                    setTextViewText(R.id.subT, subt)

                    //set info
                    setTextViewText(R.id.info, info)

                    //set rem timer
                    setTextViewText(R.id.outTimer, remTime)
                    setTextColor(R.id.outTimer, ContextCompat.getColor(context, remTimeColor))
                

                widgetManager?.updateAppWidget(currWidgetInstanceName, remoteViews)
            

        
    

【问题讨论】:

你可以试试workmanager。参考是:* googleadservices.com/pagead/… 其他链接是:developer.android.com/topic/libraries/architecture/… 尝试过警报管理器,但仍然显示加载小部件文本时出现问题 报警管理器太老了。试试工作管理器吧。 仍然无法调用 onUpdate 函数。 onReceive 被称为经理正在调用它,但 onUpdate 仅在我第一次在主屏幕上创建小部件时被调用 【参考方案1】:

来自https://developer.android.com/reference/android/appwidget/AppWidgetProviderInfo

注意:使用 updatePeriodMillis 请求的更新将不会发送 每 30 分钟一次以上。

如果你想要频繁更新,你应该使用

AlarmManager

使用服务并更新小部件,例如:

Intent intent = new Intent(context, WidgetUpdateService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pending);
alarm.setRepeating(AlarmManager.ELAPSED_REALTIME,
    SystemClock.elapsedRealtime(), 1000, pendingIntent);

【讨论】:

它在 setRepeating 的 1000 上说它将被强制到 60000ms【参考方案2】:

AppWidgetProvider.onUpdateAppWidgetProvider.onReceive 调用。在onReceive 方法结束时调用super.onReceive(context, intent)。数据将在调用onUpdate 之前更新。

override fun onReceive(context: Context?, intent: Intent?) 
    val extras = intent?.extras

    extras?.let  
        time = extras.getString(REM_TIME)?:""
        color = extras.getInt(REM_TIME_COLOR)
    

    super.onReceive(context, intent)

【讨论】:

以上是关于如何使用来自 Activity 的数据更新小部件?的主要内容,如果未能解决你的问题,请参考以下文章

当 Android 中的 Activity 内容更改时,小部件不更新

如何在android中单击按钮时更新小部件的视图?

从 Activity 手动更改小部件状态

Android API指南之应用程序窗口小部件

iOS14 小部件可以请求主应用程序更新其数据吗?

如何使用来自小部件的不同附加功能打开相同的活动