diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 620d5a3d..20a2d876 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,38 +1,40 @@
-
-
+
+
+
+
+ android:label="天使动漫"
+ android:name="${applicationName}"
+ android:usesCleartextTraffic="true"
+ android:icon="@mipmap/ic_launcher">
+ android:name=".MainActivity"
+ android:exported="true"
+ android:launchMode="singleTop"
+ android:theme="@style/Theme.TsdmClient.Launcher"
+ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
+ android:hardwareAccelerated="true"
+ android:windowSoftInputMode="adjustResize">
-
-
+
+
+ android:name="flutterEmbedding"
+ android:value="2" />
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 33d6d24a..09f1d8ed 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -45,5 +45,10 @@
UIApplicationSupportsIndirectInputEvents
+ UIBackgroundModes
+
+ fetch
+ processing
+
diff --git a/lib/features/settings/provider/settings_provider.dart b/lib/features/settings/provider/settings_provider.dart
new file mode 100644
index 00000000..48fa729b
--- /dev/null
+++ b/lib/features/settings/provider/settings_provider.dart
@@ -0,0 +1,30 @@
+// lib/features/settings/provider/settings_provider.dart
+import 'package:flutter/foundation.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+import '../../../services/background_service.dart';
+
+class SettingsProvider with ChangeNotifier {
+ bool _backgroundKeepAlive = false;
+
+ bool get backgroundKeepAlive => _backgroundKeepAlive;
+
+ Future setBackgroundKeepAlive(bool value) async {
+ _backgroundKeepAlive = value;
+ final prefs = await SharedPreferences.getInstance();
+ await prefs.setBool('background_keep_alive', value);
+ notifyListeners();
+
+ // 根据开关状态启动或停止后台任务
+ if (value) {
+ await BackgroundService.startBackgroundTask();
+ } else {
+ await BackgroundService.stopBackgroundTask();
+ }
+ }
+
+ Future loadBackgroundKeepAlive() async {
+ final prefs = await SharedPreferences.getInstance();
+ _backgroundKeepAlive = prefs.getBool('background_keep_alive') ?? false;
+ notifyListeners();
+ }
+}
diff --git a/lib/features/settings/view/settings_page.dart b/lib/features/settings/view/settings_page.dart
index 1b986283..96a277ba 100644
--- a/lib/features/settings/view/settings_page.dart
+++ b/lib/features/settings/view/settings_page.dart
@@ -46,6 +46,8 @@ import 'package:tsdm_client/widgets/section_switch_list_tile.dart';
import 'package:tsdm_client/widgets/section_title_text.dart';
import 'package:tsdm_client/widgets/shutdown.dart';
import 'package:tsdm_client/widgets/tips.dart';
+import 'package:provider/provider.dart';
+import '../provider/settings_provider.dart';
/// Settings page of the app.
class SettingsPage extends StatefulWidget {
@@ -865,3 +867,48 @@ class _SettingsPageState extends State {
);
}
}
+
+Widget build(BuildContext context) {
+ return CupertinoPageScaffold(
+ navigationBar: CupertinoNavigationBar(
+ middle: Text('设置'),
+ ),
+ child: SafeArea(
+ child: ListView(
+ children: [
+ // ... 其他现有设置项 ...
+
+ // === 添加后台常驻开关 ===
+ CupertinoFormSection.insetGrouped(
+ header: Text('行为'),
+ children: [
+ CupertinoFormRow(
+ prefix: Container(
+ width: 24, // 留空图标位置
+ ),
+ helper: Text('开启后,应用在后台时会尝试保持活动状态以执行任务'),
+ child: Row(
+ children: [
+ Expanded(
+ child: Text('后台常驻'),
+ ),
+ Consumer(
+ builder: (context, settings, child) {
+ return CupertinoSwitch(
+ value: settings.backgroundKeepAlive,
+ onChanged: (bool value) {
+ settings.setBackgroundKeepAlive(value);
+ },
+ );
+ },
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ );
+}
diff --git a/lib/main.dart b/lib/main.dart
index aebda4a0..148896f1 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -13,6 +13,7 @@ import 'package:tsdm_client/features/local_notice/callback.dart';
import 'package:tsdm_client/features/settings/repositories/settings_repository.dart';
import 'package:tsdm_client/i18n/strings.g.dart';
import 'package:tsdm_client/instance.dart';
+import 'package:tsdm_client/services/background_service.dart';
import 'package:tsdm_client/shared/providers/providers.dart';
import 'package:tsdm_client/shared/providers/proxy_provider/proxy_provider.dart';
import 'package:tsdm_client/utils/platform.dart';
@@ -31,6 +32,18 @@ Future _boot(List args) async {
talker.debug('------------------- start app -------------------');
await initProviders();
+ // 初始化后台服务
+ await BackgroundService.initialize();
+
+ // 获取设置仓库并检查后台常驻设置
+ final settingsRepo = getIt.get();
+ final backgroundKeepAliveEnabled = settingsRepo.currentSettings.backgroundKeepAlive ?? false;
+
+ // 如果设置中启用了后台常驻,则启动后台任务
+ if (backgroundKeepAliveEnabled) {
+ await BackgroundService.startBackgroundTask();
+ }
+
final settings = getIt.get().currentSettings;
final settingsLocale = settings.locale;
diff --git a/lib/services/background_service.dart b/lib/services/background_service.dart
new file mode 100644
index 00000000..84edcd06
--- /dev/null
+++ b/lib/services/background_service.dart
@@ -0,0 +1,53 @@
+import 'package:workmanager/workmanager.dart';
+
+@pragma('vm:entry-point')
+void callbackDispatcher() {
+ Workmanager().executeTask((task, inputData) {
+ print("BackgroundTask: TSDM Client is running in background!");
+ return Future.value(true);
+ });
+}
+
+class BackgroundService {
+ static Future initialize() async {
+ try {
+ await Workmanager().initialize(
+ callbackDispatcher,
+ isInDebugMode: false,
+ );
+ print("BackgroundService: Initialized successfully");
+ } catch (e) {
+ print("BackgroundService: Initialization failed - $e");
+ rethrow;
+ }
+ }
+
+ static Future startBackgroundTask() async {
+ try {
+ await Workmanager().registerPeriodicTask(
+ "tsdmBackgroundTask",
+ "tsdmBackgroundTask",
+ frequency: Duration(minutes: 15),
+ initialDelay: Duration(seconds: 10),
+ constraints: Constraints(
+ networkType: NetworkType.connected,
+ ),
+ existingWorkPolicy: ExistingWorkPolicy.replace,
+ );
+ print("BackgroundService: Background task started successfully");
+ } catch (e) {
+ print("BackgroundService: Failed to start background task - $e");
+ rethrow;
+ }
+ }
+
+ static Future stopBackgroundTask() async {
+ try {
+ await Workmanager().cancelByUniqueName("tsdmBackgroundTask");
+ print("BackgroundService: Background task stopped successfully");
+ } catch (e) {
+ print("BackgroundService: Failed to stop background task - $e");
+ rethrow;
+ }
+ }
+}