You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

224 lines
6.9 KiB

import 'dart:io';
import 'package:get/get.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:permission_handler/permission_handler.dart';
import '../providers/agent_provider.dart';
import 'package:flutter/foundation.dart';
class NotificationService extends GetxService {
static NotificationService get to => Get.find();
FlutterLocalNotificationsPlugin? _flutterLocalNotificationsPlugin;
bool _notificationActive = false;
bool _isRequestingPermission = false;
String get _defaultAgentName {
final agent = AgentProvider.getAgentById('personal_assistant');
return agent?.name ?? 'Deep Voice';
}
Future<void> init() async {
try {
if (Platform.isIOS || Platform.isAndroid || Platform.isMacOS) {
_flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
// 使用应用图标作为通知图标
const initializationSettingsAndroid = AndroidInitializationSettings('mipmap/ic_launcher');
final initializationSettingsDarwin = DarwinInitializationSettings(
requestSoundPermission: false,
requestBadgePermission: false,
requestAlertPermission: false,
);
final initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
iOS: initializationSettingsDarwin,
macOS: initializationSettingsDarwin,
);
await _flutterLocalNotificationsPlugin?.initialize(
initializationSettings,
onDidReceiveNotificationResponse: (details) {
if (Get.currentRoute != '/chat') {
Get.toNamed('/chat');
}
},
);
}
// 创建通知渠道 - 使用高重要性确保通知在后台可见
if (Platform.isAndroid) {
await _flutterLocalNotificationsPlugin?.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()?.createNotificationChannel(
const AndroidNotificationChannel(
'foreground_service',
'Foreground Service',
description: 'Used for the foreground service notification',
importance: Importance.high, // 提高重要性
playSound: false,
enableVibration: false,
showBadge: true,
),
);
}
// 请求权限,但避免重复请求
await _requestPermissionIfNeeded();
// 在初始化完成后显示前台服务通知
if (Platform.isAndroid) {
await showForegroundNotification();
}
// Add macOS-specific code for status bar icon
if (Platform.isMacOS) {
await showMacOSStatusBarIcon();
}
} catch (e) {
print('通知服务初始化失败: $e');
}
}
Future<void> showForegroundNotification() async {
if (_notificationActive) return;
try {
final androidDetails = AndroidNotificationDetails(
'foreground_service',
'Foreground Service',
channelDescription: 'Used for the foreground service notification',
importance: Importance.high, // 提高重要性
priority: Priority.high, // 提高优先级
ongoing: true,
autoCancel: false,
showWhen: false,
enableVibration: false,
playSound: false,
icon: 'mipmap/ic_launcher', // 使用应用图标
visibility: NotificationVisibility.public,
category: AndroidNotificationCategory.service,
actions: [
const AndroidNotificationAction(
'chat',
'开始对话',
showsUserInterface: true,
),
],
);
const iosDetails = DarwinNotificationDetails(
presentAlert: false,
presentBadge: false,
presentSound: false,
interruptionLevel: InterruptionLevel.passive,
);
final notificationDetails = NotificationDetails(
android: androidDetails,
iOS: iosDetails,
);
await _flutterLocalNotificationsPlugin?.show(
0,
_defaultAgentName,
'点击开始对话',
notificationDetails,
);
_notificationActive = true;
} catch (e) {
print('显示前台服务通知失败: $e');
}
}
Future<void> cancelNotification() async {
if (!_notificationActive) return;
try {
await _flutterLocalNotificationsPlugin?.cancel(0);
_notificationActive = false;
} catch (e) {
print('取消通知失败: $e');
}
}
Future<void> _requestPermissionIfNeeded() async {
// 避免重复请求权限
if (_isRequestingPermission) {
print('已有权限请求正在进行中,跳过此次请求');
return;
}
_isRequestingPermission = true;
try {
if (Platform.isMacOS) {
// On macOS, we don't need to request notification permissions through permission_handler
// Instead, we'll use the flutter_local_notifications plugin directly
final bool? granted = await _flutterLocalNotificationsPlugin
?.resolvePlatformSpecificImplementation<MacOSFlutterLocalNotificationsPlugin>()
?.requestPermissions(
alert: true,
badge: true,
sound: true,
);
if (granted != true) {
debugPrint('MacOS Notifications: Permission request was denied');
}
} else if (Platform.isAndroid || Platform.isIOS) {
// 检查权限状态,避免不必要的请求
final status = await Permission.notification.status;
if (status != PermissionStatus.granted) {
await Permission.notification.request();
}
}
} catch (e) {
print('请求通知权限失败: $e');
} finally {
_isRequestingPermission = false;
}
}
Future<void> showNotification({
required String title,
required String body,
}) async {
if (_flutterLocalNotificationsPlugin == null) return;
try {
const androidDetails = AndroidNotificationDetails(
'chat_channel',
'聊天消息',
channelDescription: '接收新的聊天消息',
importance: Importance.high,
priority: Priority.high,
icon: 'mipmap/ic_launcher', // 使用应用图标
);
const iosDetails = DarwinNotificationDetails(
presentAlert: true,
presentBadge: true,
presentSound: true,
);
const notificationDetails = NotificationDetails(
android: androidDetails,
iOS: iosDetails,
);
await _flutterLocalNotificationsPlugin?.show(
0,
title,
body,
notificationDetails,
);
} catch (e) {
print('显示通知失败: $e');
}
}
Future<void> showMacOSStatusBarIcon() async {
// Implementation using platform channel to communicate with native macOS code
}
}