Support core status check and force restart Optimize proxies page and access page Update flutter and pub dependencies Optimize more details
118 lines
3.0 KiB
Dart
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;
|