Files
MWClash/lib/plugins/service.dart
chen08209 a949b26dec Add android separates the core process
Support core status check and force restart

Optimize proxies page and access page

Update flutter and pub dependencies
2025-09-07 01:23:17 +08:00

118 lines
3.0 KiB
Dart

import 'dart:async';
import 'dart:convert';
import 'dart:isolate';
import 'package:fl_clash/common/constant.dart';
import 'package:fl_clash/common/system.dart';
import 'package:fl_clash/models/common.dart';
import 'package:fl_clash/models/core.dart';
import 'package:fl_clash/state.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
abstract mixin class ServiceListener {
void onServiceEvent(CoreEvent event) {}
void onServiceCrash(String message) {}
}
class Service {
static Service? _instance;
late MethodChannel methodChannel;
ReceivePort? receiver;
final ObserverList<ServiceListener> _listeners =
ObserverList<ServiceListener>();
factory Service() {
_instance ??= Service._internal();
return _instance!;
}
Service._internal() {
methodChannel = const MethodChannel('$packageName/service');
methodChannel.setMethodCallHandler((call) async {
switch (call.method) {
case 'getVpnOptions':
return handleGetVpnOptions();
case 'event':
final data = call.arguments as String? ?? '';
final result = ActionResult.fromJson(json.decode(data));
for (final listener in _listeners) {
listener.onServiceEvent(CoreEvent.fromJson(result.data));
}
break;
case 'crash':
final message = call.arguments as String? ?? '';
for (final listener in _listeners) {
listener.onServiceCrash(message);
}
break;
default:
throw MissingPluginException();
}
});
}
Future<ActionResult?> invokeAction(Action action) async {
final data = await methodChannel.invokeMethod<String>(
'invokeAction',
json.encode(action),
);
if (data == null) {
return null;
}
return ActionResult.fromJson(json.decode(data));
}
String handleGetVpnOptions() {
return json.encode(globalState.getVpnOptions());
}
Future<bool> start() async {
return await methodChannel.invokeMethod<bool>('start') ?? false;
}
Future<bool> stop() async {
return await methodChannel.invokeMethod<bool>('stop') ?? false;
}
Future<String> syncAndroidState(AndroidState state) async {
return await methodChannel.invokeMethod<String>(
'syncState',
json.encode(state),
) ??
'';
}
Future<String> init() async {
return await methodChannel.invokeMethod<String>('init') ?? '';
}
Future<bool> shutdown() async {
return await methodChannel.invokeMethod<bool>('shutdown') ?? true;
}
Future<DateTime?> getRunTime() async {
final ms = await methodChannel.invokeMethod<int>('getRunTime') ?? 0;
if (ms == 0) {
return null;
}
return DateTime.fromMillisecondsSinceEpoch(ms);
}
bool get hasListeners {
return _listeners.isNotEmpty;
}
void addListener(ServiceListener listener) {
_listeners.add(listener);
}
void removeListener(ServiceListener listener) {
_listeners.remove(listener);
}
}
Service? get service => system.isAndroid ? Service() : null;