jjsos_autosos_flutter/lib/service/background_service.dart

108 lines
3.2 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import 'dart:async';
import 'dart:io';
import 'package:autosos_flutter/service/heartbeat_service.dart';
import 'package:autosos_flutter/service/location_service.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_background_service/flutter_background_service.dart';
/// 后台保活服务(对应 Android JjSosLongService
///
/// 启动后会在原生层持有一个前台服务Foreground Service
/// 即使 App 被系统回收isolate 仍可继续执行心跳与位置上报。
class BackgroundService {
static final BackgroundService instance = BackgroundService._();
BackgroundService._();
static const String _notificationChannelId = 'autosos_bg_channel';
static const int _notificationId = 888;
final _service = FlutterBackgroundService();
/// 是否正在运行
Future<bool> isRunning() => _service.isRunning();
/// 初始化(在 main() 里调用一次)
Future<void> init() async {
if (!Platform.isAndroid && !Platform.isIOS) return;
await _service.configure(
androidConfiguration: AndroidConfiguration(
onStart: _onStart,
isForegroundMode: true,
autoStart: true,
autoStartOnBoot: true,
foregroundServiceNotificationId: _notificationId,
initialNotificationTitle: '啾啾救援',
initialNotificationContent: '正在保持在线...',
notificationChannelId: _notificationChannelId,
foregroundServiceTypes: const [
AndroidForegroundType.location,
AndroidForegroundType.dataSync,
],
),
iosConfiguration: IosConfiguration(
autoStart: true,
onForeground: _onStart,
onBackground: _onIosBackground,
),
);
}
/// 启动后台服务
Future<void> start() async {
final running = await _service.isRunning();
if (!running) {
await _service.startService();
}
}
/// 停止后台服务
Future<void> stop() async {
_service.invoke('stopService');
}
/// Android 入口(独立 isolate
@pragma('vm:entry-point')
static void _onStart(ServiceInstance service) async {
if (service is AndroidServiceInstance) {
service.on('setAsForeground').listen((event) {
service.setAsForegroundService();
});
service.on('setAsBackground').listen((event) {
service.setAsBackgroundService();
});
service.on('stopService').listen((event) async {
await service.stopSelf();
});
}
// 启动位置采集
try {
LocationService.instance.init();
LocationService.instance.start();
} catch (e) {
debugPrint('BG location start failed: $e');
}
// 启动心跳
HeartbeatService.instance.start();
// 持续保活:每 30 秒检查一次
Timer.periodic(const Duration(seconds: 30), (timer) async {
if (!HeartbeatService.instance.running) {
HeartbeatService.instance.start();
}
});
debugPrint('Background service started');
}
/// iOS 后台入口(必须尽快返回)
@pragma('vm:entry-point')
static bool _onIosBackground(ServiceInstance service) {
// iOS 不允许常驻后台任务,只能在限时窗口内上报
return true;
}
}