我在我的Android应用的主屏幕小部件中有一个列表视图。我使用一个名为home widget的flutter插件来实现Kotlin和dart代码之间的通信。列表视图的每个项目中都有两个元素:复选框和文本。当复选框被单击时,我想执行HomeWidgetBackgroundIntent.getBroadcast方法来触发dart代码中的后台回调(这会在数据库中进行一些更改),当单击文本时,我想使用HomeWidgetLaunchIntent.getActivity方法来打开具有特定URI的应用程序。这两种方法都是挂起的意图。问题是android没有'我不允许你为一个列表项目添加不同的挂起意图。他们希望开发人员为单个项目使用fillInIntent,然后设置公共的挂起意图模板。我应该如何检测哪个元素被点击(复选框或文本)并为这两种情况设置不同的未决意图模板?我也想过让未决意图模板触发小部件的接收者,然后调用home_这里的widget插件方法(基于fillInIntent中的数据集)。但是由于这些方法是挂起的intent,我如何在这里触发挂起的intent(通常挂起的intent在点击事件时触发,但不可能在onReceive方法中触发它们)?
关于我的小部件的代码:
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray, widgetData: SharedPreferences) {
Log.d("debugging", "widget loaded")
val sharedPref: SharedPreferences = context.getSharedPreferences(
"ApplicationListener", Context.MODE_PRIVATE)
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")
todo["taskName"] = obj.getString("taskName")
todos.add(todo)
val view = RemoteViews(context.packageName, R.layout.each_todo).apply {
setTextViewText(R.id.each_todo_container_text, todo["taskName"].toString())
setCompoundButtonChecked(R.id.each_todo_container_checkbox, todo["finished"].toString().toBoolean())
//i want to have a separate pending intent for the text view and the check box
val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast(context,
Uri.parse("myAppWidget://todo_checked/${todo["id"].toString()}"))
setOnCheckedChangeResponse(
R.id.each_todo_container_checkbox,
RemoteViews.RemoteResponse.fromPendingIntent(backgroundIntent)
)
//this pending intent doesn't get triggered
val fillInIntent = Intent().apply {
Bundle().also { extras ->
extras.putInt(EXTRA_ITEM, todo["id"].toString().toInt())
putExtras(extras)
}
}
setOnClickFillInIntent(R.id.each_todo_container_text, fillInIntent)
}
todosRemoteView.addItem(todo["id"].toString().toInt().toLong(), view)
}
}
setRemoteAdapter(
R.id.todos_list,
todosRemoteView
.build()
)
val editTodoIntent = HomeWidgetLaunchIntent.getActivity(
context,
MainActivity::class.java,
Uri.parse("http://edit_todo/$timeType"))
setPendingIntentTemplate(R.id.todos_list, editTodoIntent)
//how to set two different pending intent templates here for the text view and checkbox?
}
appWidgetManager.updateAppWidget(widgetId, views)
}
}
override fun onReceive(context: Context?, intent: Intent?) {
val viewIndex: Int = intent!!.getIntExtra(EXTRA_ITEM, 0)
Log.d("debugging", "an item is clicked $viewIndex")
//i can make the pending intent template of the list view trigger this onReceive function and I can use the data inside intent(set by fillInIntent) to find out which element of the two was clicked
//but how can I trigger the pending intent here?
super.onReceive(context, intent)
}
}
1条答案
按热度按时间mbjcgjjk1#
请随意阅读这个android示例,以便更好地理解我在这里写的内容。我将解释你在阅读网站后可能会知道的东西(也许你已经阅读过了)。
首先,您不需要通过HomeWidgetLaunchIntent.getActivity创建setPendingIntentTemplate的Intent,您需要通过以下方式创建它的PendingIntent:
IMO你应该使用RemoteViewsService.RemoteViewsFactory作为适配器,并使用setOnClickFillInIntent来设置你必须覆盖的getViewAt函数中的行中的每个元素,这是我在android示例中发现的方法,更容易理解。你可以在android示例中找到更多信息,仔细阅读所有文档。forgetVewAt应该有这样的内容:
也许你可以在你的RemoteViews.RemoteCollectionItems.Builder中调用两个setOnClickFillInIntent,我认为你应该可以,但我更喜欢使用RemoteViewsService.RemoteViewsFactory来遵循android示例。
在android示例中,它们不运行应用,但您可以在onReceive函数中运行您的应用(现在这里您使用HomeWidgetLaunchIntent.getActivity并使用send()运行它):
如果我遗漏了什么,请随时询问。我试图调整我必须匹配您所需要的代码。