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

Flutter home_widget组件interactiveCallback触发失败问题求助

home_widget 包 interactiveCallback 不触发问题

使用home_widget包时,点击Widget的刷新图标后,无法触发Flutter中的backgroundCallback方法更新数据,但Widget常规更新功能正常。以下是相关代码:

AndroidManifest.xml

<receiver
    android:name=".MyAppHomeWidget"
    android:exported="true">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>

    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/my_home_widget_info" />
</receiver>


<!-- Used for Background Work -->
<receiver
    android:name="es.antonborri.home_widget.HomeWidgetBackgroundReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="es.antonborri.home_widget.action.BACKGROUND" />
    </intent-filter>
</receiver>
<service
    android:name="es.antonborri.home_widget.HomeWidgetBackgroundService"
    android:exported="true"
    android:permission="android.permission.BIND_JOB_SERVICE" />

Kotlin 代码(MyAppHomeWidget.kt)

class MyAppHomeWidget : HomeWidgetProvider() {
    override fun onReceive(context: Context?, intent: Intent?) {
        super.onReceive(context, intent)
    }

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

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

                // Open App on Widget Click
                val openAppOnClickIntent =
                    HomeWidgetLaunchIntent.getActivity(context, MainActivity::class.java)
                setOnClickPendingIntent(R.id.widget_container, openAppOnClickIntent)

                // 触发Dart后台代码的刷新事件
                val refreshDataIntent =
                    HomeWidgetBackgroundIntent.getBroadcast(
                        context, Uri.parse("myHomeWidget://updateLocationAndForecast")
                    )
                setOnClickPendingIntent(R.id.refreshDataIcon, refreshDataIntent)

                // 更新Widget数据
                setTextViewText(
                    R.id.widgetLocation,
                    widgetData.getString("widgetLocation", "Somewhere")
                )
                setTextViewText(
                    R.id.widgetWeatherCondition,
                    widgetData.getString("widgetWeatherCondition", "Unknown")
                )

                setTextViewText(
                    R.id.widgetTemperature,
                    widgetData.getString("widgetTemperature", "N/A")
                )
                setTextViewText(R.id.widgetHumidity, widgetData.getString("widgetHumidity", "N/A"))
                setTextViewText(R.id.widgetRainProb, widgetData.getString("widgetRainProb", "N/A"))
                setTextViewText(R.id.widgetWind, widgetData.getString("widgetWind", "N/A"))

                setTextViewText(
                    R.id.widgetLastUpdateDate,
                    widgetData.getString("widgetLastUpdateDate", "N/A") ?: "No Title Set"
                )
            }

            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }

    override fun onEnabled(context: Context) {
        // 第一个Widget创建时的逻辑
    }

    override fun onDisabled(context: Context) {
        // 最后一个Widget被禁用时的逻辑
    }
}

Dart 代码(HomeWidgetController)

class HomeWidgetController {
  static const String _classname = 'HomeWidgetController';

  /// 接收Widget发起的后台工作回调
  @pragma("vm:entry-point")
  static Future<void> backgroundCallback(Uri? data) async {
    AppLogger.info(_classname, 'App Widget call with URI: $data');
    if (data?.host == 'updateLocationAndForecast') {
      // 这里写数据更新逻辑
    }
  }

  static Future<void> initialize() async {
    HomeWidget.setAppGroupId(GlobalVar.widgetGroupId);
    await HomeWidget.registerInteractivityCallback(backgroundCallback);
  }
}

main 方法中的初始化调用

WidgetsFlutterBinding.ensureInitialized();
await HomeWidgetController.initialize();

排查与解决建议

  1. 确认@pragma注解有效性:backgroundCallback上的@pragma("vm:entry-point")不能写错,Release模式下Flutter编译器会移除没有该注解的入口方法,这是回调不触发的常见原因。
  2. 验证URI匹配逻辑:可以在backgroundCallback中打印完整URI,确认传递的Uri是否与预期一致,避免因URI解析问题导致分支不执行。
  3. 检查混淆规则(Release模式):如果是Release包出现问题,需在ProGuard/R8规则中添加以下配置,防止相关类和方法被混淆:
    -keep class es.antonborri.home_widget.** { *; }
    -keepclassmembers class * {
        @pragma("vm:entry-point") <methods>;
    }
    
  4. 确认控件可点击性:确保R.id.refreshDataIcon对应的控件(如ImageView)设置了android:clickable="true",否则点击事件无法触发。
  5. 验证回调注册状态:在initialize方法中添加日志,确认HomeWidget.registerInteractivityCallback执行成功,没有抛出异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 05:54:52