如何从Flutter代码向Android原生代码发送数据更新Android Widget
实现Flutter向Android Widget定时传数据并更新的方案
1. 搭建Flutter与Android的通信通道
在Flutter侧通过MethodChannel建立和原生的通信,用于主动发送数据:
import 'package:flutter/services.dart'; final MethodChannel _widgetUpdateChannel = MethodChannel('com.yourpackage/widget_updater'); // 封装发送数据到原生的方法 Future<void> sendWidgetData(Map<String, dynamic> data) async { try { await _widgetUpdateChannel.invokeMethod('update_widget', data); } on PlatformException catch (e) { print('数据发送失败: ${e.message}'); } }
在Android的MainActivity中注册该通道,接收Flutter传来的数据并触发Widget更新:
class MainActivity : FlutterActivity() { private val CHANNEL = "com.yourpackage/widget_updater" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> if (call.method == "update_widget") { // 解析Flutter传来的数据 val widgetData = call.arguments as HashMap<String, Any> // 执行Widget更新逻辑 updateAppWidget(widgetData) result.success(null) } else { result.notImplemented() } } } private fun updateAppWidget(data: HashMap<String, Any>) { val appWidgetManager = AppWidgetManager.getInstance(this) val componentName = ComponentName(this, YourWidgetProvider::class.java) val widgetIds = appWidgetManager.getAppWidgetIds(componentName) // 将数据存入SharedPreferences,供Widget Provider读取 val prefs = getSharedPreferences("WidgetDataStore", Context.MODE_PRIVATE) with(prefs.edit()) { data.forEach { (key, value) -> when (value) { is String -> putString(key, value) is Int -> putInt(key, value) is Float -> putFloat(key, value) // 根据业务需求扩展数据类型 } } apply() } // 触发Widget刷新 YourWidgetProvider.refreshWidgets(this, appWidgetManager, widgetIds) } }
2. 实现Android AppWidgetProvider
创建Widget Provider类,负责读取存储的数据并更新Widget UI:
class YourWidgetProvider : AppWidgetProvider() { companion object { fun refreshWidgets(context: Context, manager: AppWidgetManager, widgetIds: IntArray) { widgetIds.forEach { id -> val views = RemoteViews(context.packageName, R.layout.your_widget_layout) // 从SharedPreferences读取数据 val prefs = context.getSharedPreferences("WidgetDataStore", Context.MODE_PRIVATE) val displayContent = prefs.getString("content", "默认内容") views.setTextViewText(R.id.widget_content_tv, displayContent) // 执行更新 manager.updateAppWidget(id, views) } } } override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { refreshWidgets(context, appWidgetManager, appWidgetIds) } }
同时在AndroidManifest.xml中注册Widget:
<receiver android:name=".YourWidgetProvider"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_info" /> </receiver>
3. Flutter侧定时触发数据发送
使用dart:async的Timer.periodic实现每30分钟主动发送数据:
import 'dart:async'; Timer? _widgetUpdateTimer; void startWidgetUpdateTask() { // 立即发送一次初始数据 sendWidgetData({"content": "更新时间: ${DateTime.now().toLocal()}"}); // 每30分钟触发一次 _widgetUpdateTimer = Timer.periodic(const Duration(minutes: 30), (timer) { sendWidgetData({"content": "更新时间: ${DateTime.now().toLocal()}"}); }); } // 在页面销毁时取消定时器 @override void dispose() { _widgetUpdateTimer?.cancel(); super.dispose(); }
关键注意事项
- 若Flutter应用处于后台,系统可能暂停定时器,此时可结合Android的
WorkManager实现更可靠的定时逻辑,让原生主动请求Flutter数据。 - 数据传递时需严格匹配类型,避免序列化异常。
- 确保Widget布局文件
your_widget_layout.xml中存在对应ID的控件(如示例中的R.id.widget_content_tv)。
内容的提问来源于stack exchange,提问作者thinkcode
相关产品推荐
相关产品推荐

