You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android桌面Widget中fillInIntent无法传递数据问题排查

问题

桌面Widget中的ListView点击列表项时,无法获取fillInIntent传入的数据,始终拿到默认值0。已为每个列表项设置fillInIntent,并配置了触发Widget广播接收器的PendingIntent模板,尝试添加FILL_IN_COMPONENT标识也无效。

代码如下:

class WidgetProvider : HomeWidgetProvider() {
    override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray, widgetData: SharedPreferences) {

        appWidgetIds.forEach { widgetId ->
            val views = RemoteViews(context.packageName, R.layout.widget_layout).apply {

                val todosStr  = widgetData.getString("todos", "null")
                val todos = ArrayList<HashMap<String, Any>>()
                val todosRemoteView = RemoteViews.RemoteCollectionItems.Builder()
                if(todosStr != "null"){
                    val jObj = JSONObject(todosStr)
                    val jsonArry = jObj.getJSONArray("todos")
                    for (i in 0 until jsonArry.length()) {
                        val todo = HashMap<String, Any>()
                        val obj = jsonArry.getJSONObject(i)
                        todo["id"] = obj.getInt("id")
                        todos.add(todo)

                        val view = RemoteViews(context.packageName, R.layout.each_todo).apply {
                            setTextViewText(R.id.each_todo_container_text, todo["taskName"].toString())

                            val fillInIntent = Intent().apply {
                                Bundle().also { extras ->
                                    extras.putInt("todo_id", todo["id"].toString().toInt())//this isn't working for some reason
                                    putExtras(extras)
                                }
                            }
                            Log.d("debugging",  "id received is ${todo["id"].toString()}" )
                            setOnClickFillInIntent(R.id.each_todo_container_text, fillInIntent)
                        }

                        todosRemoteView.addItem(todo["id"].toString().toInt().toLong(), view)
                    }
                }

                setRemoteAdapter(
                        R.id.todos_list,
                        todosRemoteView
                    .build()
                )

                val pendingIntentx: PendingIntent = Intent(
                        context,
                        WidgetProvider::class.java
                ).run {
                    PendingIntent.getBroadcast(context, 0, this, PendingIntent.FLAG_IMMUTABLE or Intent.FILL_IN_COMPONENT)
                }
                setPendingIntentTemplate(R.id.todos_list, pendingIntentx)
            }

            appWidgetManager.updateAppWidget(widgetId, views)
    }

    }

    override fun onReceive(context: Context?, intent: Intent?) {
        val viewIndex: Int = intent!!.getIntExtra("todo_id", 0)
        Log.d("debugging", "an item is clicked $viewIndex")
        //the default value gets used, which means that the receiver isn't receiving the intent data
        
        super.onReceive(context, intent)
    }
}
解决方案

问题根源

  1. 错误的填充标识:使用Intent.FILL_IN_COMPONENT是错误的,该标识用于填充组件信息(如目标类),但你需要填充的是额外数据(Extras),应该替换为Intent.FILL_IN_EXTRAS。
  2. fillInIntent绑定到子View:将fillInIntent绑定到了TextView子控件上,导致点击时数据无法正确合并到模板Intent中,应该绑定到列表项的根布局。
  3. PendingIntent复用冲突:使用固定的requestCode(0)可能导致不同Widget实例的PendingIntent复用,引发数据异常。

修改后的代码

class WidgetProvider : HomeWidgetProvider() {
    override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray, widgetData: SharedPreferences) {
        appWidgetIds.forEach { widgetId ->
            val views = RemoteViews(context.packageName, R.layout.widget_layout).apply {
                val todosStr = widgetData.getString("todos", "null")
                val todosRemoteView = RemoteViews.RemoteCollectionItems.Builder()
                
                if (todosStr != "null") {
                    val jObj = JSONObject(todosStr)
                    val jsonArry = jObj.getJSONArray("todos")
                    
                    for (i in 0 until jsonArry.length()) {
                        val obj = jsonArry.getJSONObject(i)
                        val todoId = obj.getInt("id")
                        val taskName = obj.getString("taskName") // 修复taskName未赋值的问题
                        
                        val view = RemoteViews(context.packageName, R.layout.each_todo).apply {
                            setTextViewText(R.id.each_todo_container_text, taskName)
                            
                            // 简化fillInIntent的创建
                            val fillInIntent = Intent().apply {
                                putExtra("todo_id", todoId)
                            }
                            Log.d("debugging", "设置的id是 $todoId")
                            
                            // 绑定到列表项的根布局(需确保each_todo.xml的根布局有id:each_todo_root)
                            setOnClickFillInIntent(R.id.each_todo_root, fillInIntent)
                        }
                        
                        todosRemoteView.addItem(todoId.toLong(), view)
                    }
                }
                
                setRemoteAdapter(R.id.todos_list, todosRemoteView.build())
                
                // 创建正确的PendingIntent模板
                val templateIntent = Intent(context, WidgetProvider::class.java)
                val pendingIntentx = PendingIntent.getBroadcast(
                    context,
                    widgetId, // 用widgetId作为requestCode,避免复用冲突
                    templateIntent,
                    PendingIntent.FLAG_IMMUTABLE or Intent.FILL_IN_EXTRAS
                )
                setPendingIntentTemplate(R.id.todos_list, pendingIntentx)
            }
            
            appWidgetManager.updateAppWidget(widgetId, views)
        }
    }

    override fun onReceive(context: Context?, intent: Intent?) {
        val todoId = intent?.getIntExtra("todo_id", 0) ?: 0
        Log.d("debugging", "点击的项id是 $todoId")
        
        super.onReceive(context, intent)
    }
}

额外注意事项

  • 确保each_todo.xml的根布局添加唯一id(如android:id="@+id/each_todo_root"),否则无法绑定fillInIntent到根布局。
  • 修复了原代码中taskName未赋值的问题,避免空指针异常。
  • 使用widgetId作为PendingIntent的requestCode,确保每个Widget实例的模板Intent独立,避免复用导致的数据错误。

内容的提问来源于stack exchange,提问作者Pro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 19:40:29