在 Flutter 混合开发中,Android 原生层通知 Dart 界面更新状态,主要通过 MethodChannel 的 invokeMethod 从原生调用 Dart,或者使用 EventChannel 建立持续的数据流。
方案一:MethodChannel 单向通知(简单场景)
Android 原生层调用 Dart
kotlin
// MainActivity.kt 或 Service.kt
import io.flutter.plugin.common.MethodChannel
class MainActivity : FlutterActivity() {
private lateinit var channel: MethodChannel
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "flutter_launcher")
// Dart 调用原生的处理器
channel.setMethodCallHandler { call, result ->
when (call.method) {
"getSystemInfo" -> result.success(getSystemInfo())
else -> result.notImplemented()
}
}
}
/**
* 主动通知 Dart 更新(例如:电池变化、应用安装/卸载)
*/
fun notifyDart(event: String, data: Map<String, Any>) {
// 在主线程调用
runOnUiThread {
channel.invokeMethod(event, data)
}
}
/**
* 示例:电池变化时通知 Dart
*/
fun onBatteryChanged(level: Int) {
notifyDart("onBatteryChanged", mapOf("level" to level))
}
/**
* 示例:应用安装/卸载时通知 Dart
*/
fun onAppChanged(action: String, packageName: String) {
notifyDart("onAppChanged", mapOf(
"action" to action, // "installed" | "uninstalled" | "updated"
"package" to packageName
))
}
}
Dart 层接收通知
dart
// lib/services/desktop_service.dart
import 'dart:async';
import 'package:flutter/services.dart';
class DesktopService {
static const MethodChannel _channel = MethodChannel('flutter_launcher');
// 状态流控制器
static final _batteryController = StreamController<int>.broadcast();
static final _appChangeController = StreamController<Map<String, dynamic>>.broadcast();
// 公开的数据流
static Stream<int> get batteryStream => _batteryController.stream;
static Stream<Map<String, dynamic>> get appChangeStream => _appChangeController.stream;
static void init() {
// 设置方法调用处理器,接收原生通知
_channel.setMethodCallHandler(_handleMethodCall);
}
static Future<<dynamic> _handleMethodCall(MethodCall call) async {
switch (call.method) {
case 'onBatteryChanged':
final level = call.arguments['level'] as int?;
if (level != null) {
_batteryController.add(level);
}
return null;
case 'onAppChanged':
final data = call.arguments as Map<<dynamic, dynamic>;
_appChangeController.add({
'action': data['action'],
'package': data['package'],
});
return null;
case 'onTimeTick':
// 每分钟通知
return null;
case 'onWifiChanged':
final enabled = call.arguments['enabled'] as bool?;
// 通知WiFi状态变化
return null;
default:
return null;
}
}
// 主动调用原生方法
static Future<Map<String, dynamic>> getSystemInfo() async {
final result = await _channel.invokeMethod('getSystemInfo');
return _toStringMap(result);
}
static Future<void> launchApp(String package) async {
await _channel.invokeMethod('launchApp', {'package': package});
}
static Map<String, dynamic> _toStringMap(dynamic data) {
if (data == null) return {};
final map = data as Map<<dynamic, dynamic>;
return map.map((k, v) => MapEntry(k.toString(), v));
}
static void dispose() {
_batteryController.close();
_appChangeController.close();
}
}
UI 层监听状态变化
dart
// lib/widgets/status_bar.dart
import 'package:flutter/material.dart';
import '../services/desktop_service.dart';
class StatusBar extends StatefulWidget {
const StatusBar({super.key});
@override
State<<StatusBar> createState() => _StatusBarState();
}
class _StatusBarState extends State<<StatusBar> {
int _battery = 100;
bool _wifi = false;
String _time = '';
@override
void initState() {
super.initState();
// 初始化服务
DesktopService.init();
// 监听电池变化(来自原生通知)
DesktopService.batteryStream.listen((level) {
setState(() => _battery = level);
});
// 定时刷新时间
Stream.periodic(const Duration(seconds: 1)).listen((_) {
setState(() {
_time = '${DateTime.now().hour.toString().padLeft(2, '0')}:'
'${DateTime.now().minute.toString().padLeft(2, '0')}';
});
});
// 初始加载
_loadSystemInfo();
}
Future<void> _loadSystemInfo() async {
final info = await DesktopService.getSystemInfo();
setState(() {
_battery = info['battery'] ?? 100;
_wifi = info['wifi'] ?? false;
});
}
@override
Widget build(BuildContext context) {
return Container(
height: 36,
color: Colors.black.withOpacity(0.6),
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Row(
children: [
Text(_time, style: const TextStyle(color: Colors.white)),
const Spacer(),
Icon(_wifi ? Icons.wifi : Icons.wifi_off, color: Colors.white, size: 18),
const SizedBox(width: 8),
Text('$_battery%', style: const TextStyle(color: Colors.white)),
],
),
);
}
}
方案二:EventChannel 持续数据流(适合高频数据)
Android 原生层
kotlin
// service/SystemEventChannel.kt
package com.example.flutter_launcher.service
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.EventChannel.EventSink
class SystemEventChannel : EventChannel.StreamHandler {
private var eventSink: EventSink? = null
override fun onListen(arguments: Any?, events: EventSink?) {
eventSink = events
startListening()
}
override fun onCancel(arguments: Any?) {
eventSink = null
stopListening()
}
/**
* 发送事件到 Dart
*/
fun sendEvent(event: String, data: Any) {
eventSink?.success(mapOf(
"event" to event,
"data" to data
))
}
private fun startListening() {
// 注册系统监听器(电池、WiFi、时间等)
}
private fun stopListening() {
// 注销监听器
}
}
Dart 层
dart
// lib/services/event_service.dart
import 'dart:async';
import 'package:flutter/services.dart';
class EventService {
static const EventChannel _eventChannel = EventChannel('flutter_launcher/events');
static Stream<Map<String, dynamic>>? _eventStream;
static Stream<Map<String, dynamic>> get eventStream {
_eventStream ??= _eventChannel
.receiveBroadcastStream()
.map((event) {
final map = event as Map<<dynamic, dynamic>;
return {
'event': map['event'],
'data': map['data'],
};
});
return _eventStream!;
}
}
方案三:BroadcastReceiver + 通知(系统事件)
Android 原生层监听系统广播
kotlin
// receiver/SystemEventReceiver.kt
package com.example.flutter_launcher.receiver
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
class SystemEventReceiver(
private val onEvent: (String, Map<String, Any>) -> Unit
) : BroadcastReceiver() {
fun register(context: Context) {
val filter = IntentFilter().apply {
addAction(Intent.ACTION_BATTERY_CHANGED)
addAction(Intent.ACTION_TIME_TICK)
addAction(Intent.ACTION_TIME_CHANGED)
addAction(Intent.ACTION_PACKAGE_ADDED)
addAction(Intent.ACTION_PACKAGE_REMOVED)
addAction(Intent.ACTION_PACKAGE_REPLACED)
addAction("android.net.wifi.STATE_CHANGE")
}
context.registerReceiver(this, filter)
}
fun unregister(context: Context) {
context.unregisterReceiver(this)
}
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
Intent.ACTION_BATTERY_CHANGED -> {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
val scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
val percent = (level * 100 / scale).coerceIn(0, 100)
onEvent("battery", mapOf("level" to percent))
}
Intent.ACTION_TIME_TICK, Intent.ACTION_TIME_CHANGED -> {
onEvent("time", mapOf("time" to System.currentTimeMillis()))
}
Intent.ACTION_PACKAGE_ADDED -> {
val packageName = intent.data?.schemeSpecificPart ?: ""
onEvent("app_added", mapOf("package" to packageName))
}
Intent.ACTION_PACKAGE_REMOVED -> {
val packageName = intent.data?.schemeSpecificPart ?: ""
onEvent("app_removed", mapOf("package" to packageName))
}
"android.net.wifi.STATE_CHANGE" -> {
val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as android.net.wifi.WifiManager
onEvent("wifi", mapOf("enabled" to wifiManager.isWifiEnabled))
}
}
}
}
在 Service 或 Activity 中使用
kotlin
class MainActivity : FlutterActivity() {
private lateinit var eventReceiver: SystemEventReceiver
private lateinit var channel: MethodChannel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
channel = MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, "flutter_launcher")
// 初始化广播接收器
eventReceiver = SystemEventReceiver { event, data ->
// 通知 Dart
runOnUiThread {
channel.invokeMethod("onSystemEvent", mapOf(
"event" to event,
"data" to data
))
}
}
eventReceiver.register(this)
}
override fun onDestroy() {
eventReceiver.unregister(this)
super.onDestroy()
}
}
完整状态更新流程图
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Android 系统 │ │ Android 原生层 │ │ Flutter Dart │
│ │ │ │ │ │
│ 电池变化 │────→│ BroadcastReceiver│────→│ MethodChannel │
│ 时间变化 │ │ 或 Service 监听 │ │ setMethodCallHandler
│ 应用安装/卸载 │ │ │ │ │
│ WiFi状态变化 │ │ │ │ StreamController
│ │ │ │ │ 通知 UI 更新 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
↑
│ 主动查询
┌────┴────┐
│ invokeMethod
│ getSystemInfo
└─────────┘
推荐用法总结
| 场景 | 方案 | 代码示例 |
|---|---|---|
| 单次状态查询 | MethodChannel 双向 | invokeMethod('getSystemInfo') |
| 状态变化通知 | MethodChannel + Stream | invokeMethod('onBatteryChanged') → StreamController |
| 高频数据流 | EventChannel | 电池实时变化、传感器数据 |
| 系统广播事件 | BroadcastReceiver + MethodChannel | 应用安装卸载、时间变化 |