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.
184 lines
5.4 KiB
184 lines
5.4 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 {
|
|
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.min,
|
|
playSound: false,
|
|
enableVibration: false,
|
|
showBadge: false,
|
|
),
|
|
);
|
|
}
|
|
|
|
await _requestPermissionIfNeeded();
|
|
|
|
// 在初始化完成后显示前台服务通知
|
|
if (Platform.isAndroid) {
|
|
await showForegroundNotification();
|
|
}
|
|
}
|
|
|
|
Future<void> showForegroundNotification() async {
|
|
if (_notificationActive) return;
|
|
|
|
// 在显示通知前确保有权限
|
|
await _requestPermissionIfNeeded();
|
|
|
|
final androidDetails = AndroidNotificationDetails(
|
|
'foreground_service',
|
|
'Foreground Service',
|
|
channelDescription: 'Used for the foreground service notification',
|
|
importance: Importance.min,
|
|
priority: Priority.min,
|
|
ongoing: true,
|
|
autoCancel: false,
|
|
showWhen: false,
|
|
enableVibration: false,
|
|
playSound: false,
|
|
icon: '@mipmap/ic_launcher',
|
|
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;
|
|
}
|
|
|
|
Future<void> cancelNotification() async {
|
|
if (!_notificationActive) return;
|
|
await _flutterLocalNotificationsPlugin?.cancel(0);
|
|
_notificationActive = false;
|
|
}
|
|
|
|
Future<void> _requestPermissionIfNeeded() async {
|
|
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');
|
|
}
|
|
return;
|
|
}
|
|
|
|
// For other platforms, use permission_handler as before
|
|
if (await Permission.notification.status != PermissionStatus.granted) {
|
|
await Permission.notification.request();
|
|
}
|
|
}
|
|
|
|
Future<void> showNotification({
|
|
required String title,
|
|
required String body,
|
|
}) async {
|
|
if (_flutterLocalNotificationsPlugin == null) return;
|
|
|
|
const androidDetails = AndroidNotificationDetails(
|
|
'chat_channel',
|
|
'聊天消息',
|
|
channelDescription: '接收新的聊天消息',
|
|
importance: Importance.high,
|
|
priority: Priority.high,
|
|
);
|
|
|
|
const iosDetails = DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
);
|
|
|
|
const notificationDetails = NotificationDetails(
|
|
android: androidDetails,
|
|
iOS: iosDetails,
|
|
);
|
|
|
|
await _flutterLocalNotificationsPlugin?.show(
|
|
0,
|
|
title,
|
|
body,
|
|
notificationDetails,
|
|
);
|
|
}
|
|
}
|