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

Flutter技术问题:如何获取桌面组件数字按键的点击值

问题描述

我正在自定义使用home_widget包,尝试构建带有数字按键的桌面组件。目前通过以下代码实现,但无法获取数字按键的点击值,请问遗漏了什么?该如何实现?


WidgetProvider.kt 代码

override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray, widgetData: SharedPreferences) {
        appWidgetIds.forEach { widgetId ->
            val views = RemoteViews(context.packageName, R.layout.widget_layout).apply {

                // 点击组件打开App
                val pendingIntent = HomeWidgetLaunchIntent.getActivity(context,
                    MainActivity::class.java)
                setOnClickPendingIntent(R.id.widget_root, pendingIntent)

                val counter = widgetData.getString("_number", "")
                Log.i("onMethodCall", "onMethodCall: $counter")
                print("onMethodCall: $counter")
                var counterText = "$counter"

                setTextViewText(R.id.tv_counter, counterText)
                val pendingIntent2 = HomeWidgetLaunchIntent.getActivity(context,
                    MainActivity::class.java)
                setOnClickPendingIntent(R.id.bt_update, pendingIntent2)

                val backgroundIntent = HomeWidgetBackgroundIntent.getBroadcast(context, Uri.parse("myAppWidget://onNumberBtnClick"))
                setOnClickPendingIntent(R.id.bt_one, backgroundIntent)
            }
            appWidgetManager.updateAppWidget(widgetId, views)
        }
    }

广播函数代码

fun getBroadcast(context: Context, uri: Uri? = null): PendingIntent {
        val intent = Intent(context, HomeWidgetBackgroundReceiver::class.java)
        intent.data = uri
        intent.action = HOME_WIDGET_BACKGROUND_ACTION

        var flags = PendingIntent.FLAG_UPDATE_CURRENT
        if (Build.VERSION.SDK_INT >= 23) {
            flags = flags or PendingIntent.FLAG_IMMUTABLE
        }

        return PendingIntent.getBroadcast(context, 0, intent, flags)
    }

HomeWidgetPlugin类中设置SharedPreference的代码

"onNumberBtnClick" -> {
                if (call.hasArgument("id") && call.hasArgument("data")) {
                    Log.i("onMethodCallHere", "onMethodCallHere: ")
                    print("onMethodCallHere")
                    val id = call.argument<String>("id")
                    val data = call.argument<Any>("data")
                    val prefs = context.getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE).edit()
                    if(data != null) {
                        when (data) {
                            is Boolean -> prefs.putBoolean(id, data)
                            is Float -> prefs.putFloat(id, data)
                            is String -> prefs.putString(id, data)
                            is Double -> prefs.putLong(id, java.lang.Double.doubleToRawLongBits(data))
                            is Int -> prefs.putInt(id, data)
                            else -> result.error("-10", "Invalid Type ${data!!::class.java.simpleName}. Supported types are Boolean, Float, String, Double, Long", IllegalArgumentException())
                        }
                    } else {
                        prefs.remove(id);
                    }
                    result.success(prefs.commit())
                }else {
                    result.error("-1", "InvalidArguments saveWidgetData must be called with id and data", IllegalArgumentException())
                }
            }

main.dart中用workmanager处理回调的代码

Future<void> backgroundCallback(Uri? uri) async {
  if (uri?.host == 'onNumberBtnClick') {
    await HomeWidget.getWidgetData<String>('_number', defaultValue: "1").then((value) {
      print("num:$value");
    });
    await HomeWidget.saveWidgetData<String>('_number', "13");
    await HomeWidget.updateWidget(name: 'AppWidgetProvider', iOSName: 'AppWidgetProvider');
  }
}

解决方案

你当前的核心问题是所有数字按键的广播Intent未携带唯一标识,导致无法区分具体是哪个按键被点击。按以下步骤修改即可实现需求:

  1. 给每个数字按键的Intent添加参数
    在WidgetProvider.kt中,为每个数字按键创建广播Intent时,通过Uri携带对应数字值:
// 数字1按键
val oneIntent = HomeWidgetBackgroundIntent.getBroadcast(context, Uri.parse("myAppWidget://onNumberBtnClick?num=1"))
setOnClickPendingIntent(R.id.bt_one, oneIntent)

// 数字2按键同理
val twoIntent = HomeWidgetBackgroundIntent.getBroadcast(context, Uri.parse("myAppWidget://onNumberBtnClick?num=2"))
setOnClickPendingIntent(R.id.bt_two, twoIntent)

// 其余数字按键按此格式添加
  1. 在Dart回调中解析点击的数字
    修改main.dart的backgroundCallback,从Uri中提取点击的数字,再更新存储的内容(支持累加或替换逻辑):
Future<void> backgroundCallback(Uri? uri) async {
  if (uri?.host == 'onNumberBtnClick') {
    // 从Uri参数中获取点击的数字
    final clickedNum = uri?.queryParameters['num'];
    if (clickedNum != null) {
      // 读取当前存储的数字,拼接新点击的数字(若要替换则直接用clickedNum即可)
      final currentNum = await HomeWidget.getWidgetData<String>('_number', defaultValue: "");
      final newNum = currentNum + clickedNum;
      await HomeWidget.saveWidgetData<String>('_number', newNum);
      await HomeWidget.updateWidget(name: 'AppWidgetProvider', iOSName: 'AppWidgetProvider');
    }
  }
}
  1. 删除多余的HomeWidgetPlugin代码
    你自定义的onNumberBtnClick分支完全多余,home_widget包已自带saveWidgetData方法,直接删除该分支即可,避免逻辑冲突。

  2. 检查广播接收器注册
    确保AndroidManifest.xml中已正确注册HomeWidgetBackgroundReceiver,保证广播事件能被正常接收。

完成上述修改后,即可获取每个数字按键的点击值,并更新桌面组件的显示内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:00:55