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

桌面Widget中ListView项点击无法传递taskId问题求助

Android Widget列表项点击传递ID修复方案

问题原因

你的代码无法获取传递的taskId,核心问题是PendingIntent使用了FLAG_IMMUTABLE标记,该标记会阻止系统将fillInIntent中的额外数据合并到模板Intent中,导致接收端无法读取到传递的值。此外,未通过Intent Action区分自定义点击事件,可能会和Widget默认事件混淆。

修复步骤

  1. 替换PendingIntent的标记:使用FLAG_UPDATE_CURRENT(确保更新Intent内容)结合FLAG_MUTABLE(适配Android 12+,允许修改Intent),让系统能正确合并fillInIntent的额外数据。
  2. 添加自定义Action:为模板Intent设置唯一Action,便于在onReceive中区分自定义点击事件。
  3. 简化fillInIntent写法:直接使用putExtra传递数据,无需额外Bundle包装。

修改后的完整代码

import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.widget.RemoteViews
import home.widget.HomeWidgetProvider
import home.widget.HomeWidgetManager

class WidgetProvider : HomeWidgetProvider() {

    // 自定义点击事件Action,确保唯一
    private const val ACTION_TASK_CLICK = "com.your.package.ACTION_TASK_CLICK"

    override fun onUpdate(
        context: Context,
        appWidgetManager: HomeWidgetManager,
        appWidgetIds: IntArray,
        widgetData: android.content.SharedPreferences
    ) {
        Log.d("debugging", "widget loaded")

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

                val todosRemoteView = RemoteViews.RemoteCollectionItems.Builder()

                val view = RemoteViews(context.packageName, R.layout.each_todo).apply {
                    setTextViewText(R.id.each_todo_container_text, "test")
                    setCompoundButtonChecked(R.id.each_todo_container_checkbox, false)

                    // 简化fillInIntent,直接传递taskId
                    val fillInIntent = Intent().apply {
                        putExtra("taskId", 4242)
                    }
                    setOnCheckedChangeResponse(
                        R.id.each_todo_container_checkbox,
                        RemoteViews.RemoteResponse.fromFillInIntent(fillInIntent)
                    )
                    setOnClickFillInIntent(R.id.each_todo_container_text, fillInIntent)
                }

                todosRemoteView.addItem(69696969, view)
                setRemoteAdapter(
                    R.id.todos_list,
                    todosRemoteView.build()
                )

                // 创建带自定义Action的PendingIntent,替换原标记
                val pendingIntentx: PendingIntent = Intent(context, WidgetProvider::class.java).apply {
                    action = ACTION_TASK_CLICK
                }.run {
                    val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
                    } else {
                        PendingIntent.FLAG_UPDATE_CURRENT
                    }
                    PendingIntent.getBroadcast(context, 0, this, flags)
                }
                setPendingIntentTemplate(R.id.todos_list, pendingIntentx)
            }

            appWidgetManager.updateAppWidget(widgetId, views)
        }
    }

    override fun onReceive(context: Context?, intent: Intent?) {
        // 先处理自定义点击事件
        intent?.takeIf { it.action == ACTION_TASK_CLICK }?.let {
            val taskId = it.getIntExtra("taskId", 0)
            Log.d("debugging", "an item is clicked, taskId: $taskId")
        }
        // 再调用父类方法处理Widget默认逻辑
        super.onReceive(context, intent)
    }
}

额外说明

  • 替换com.your.package为你实际的应用包名,避免Action冲突。
  • 若你需要动态传递不同条目的taskId,只需在创建每个列表项的fillInIntent时,将4242替换为对应条目的真实ID即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 16:50:27