awesome_notifications_helper.dart 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. import 'package:awesome_notifications/awesome_notifications.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:get/get.dart';
  4. import '../app/routes/app_pages.dart';
  5. import 'log/logger.dart';
  6. class AwesomeNotificationsHelper {
  7. // prevent making instance
  8. AwesomeNotificationsHelper._();
  9. static const String TAG = 'AwesomeNotificationsHelper';
  10. // Notification lib
  11. static AwesomeNotifications awesomeNotifications = AwesomeNotifications();
  12. // 标记是否已经请求过权限
  13. static bool _hasRequestedPermission = false;
  14. /// initialize local notifications service, create channels and groups
  15. /// setup notifications button actions handlers
  16. static init() async {
  17. try {
  18. // 初始化通知渠道和组
  19. await _initNotification();
  20. // 设置监听
  21. listenToActionButtons();
  22. // 检查权限但不立即请求
  23. await checkNotificationPermission();
  24. } catch (e) {
  25. log(TAG, 'Notification initialization failed: $e');
  26. }
  27. }
  28. /// 检查通知权限状态
  29. static Future<bool> checkNotificationPermission() async {
  30. return await awesomeNotifications.isNotificationAllowed();
  31. }
  32. /// 打开通知权限设置
  33. static Future<void> showNotificationConfigPage() async {
  34. return await awesomeNotifications.showNotificationConfigPage();
  35. }
  36. /// 请求通知权限(可以被Firebase或其他组件调用)
  37. static Future<bool> requestNotificationPermission() async {
  38. // 如果已经请求过权限,先检查当前状态
  39. if (_hasRequestedPermission) {
  40. final isAllowed = await checkNotificationPermission();
  41. if (isAllowed) return true;
  42. }
  43. // 请求权限
  44. final isAllowed = await awesomeNotifications
  45. .requestPermissionToSendNotifications();
  46. // 标记已请求过权限
  47. _hasRequestedPermission = true;
  48. return isAllowed;
  49. }
  50. /// when user click on notification or click on button on the notification
  51. static listenToActionButtons() {
  52. // Only after at least the action method is set, the notification events are delivered
  53. awesomeNotifications.setListeners(
  54. onActionReceivedMethod: NotificationController.onActionReceivedMethod,
  55. onNotificationCreatedMethod:
  56. NotificationController.onNotificationCreatedMethod,
  57. onNotificationDisplayedMethod:
  58. NotificationController.onNotificationDisplayedMethod,
  59. onDismissActionReceivedMethod:
  60. NotificationController.onDismissActionReceivedMethod,
  61. );
  62. }
  63. ///init notifications channels
  64. static _initNotification() async {
  65. await awesomeNotifications.initialize(
  66. 'resource://mipmap/launcher_icon', // 添加小图标资源路径,
  67. [
  68. NotificationChannel(
  69. channelGroupKey: NotificationChannels.generalChannelGroupKey,
  70. channelKey: NotificationChannels.generalChannelKey,
  71. channelName: NotificationChannels.generalChannelName,
  72. groupKey: NotificationChannels.generalGroupKey,
  73. channelDescription: NotificationChannels.generalChannelDescription,
  74. defaultColor: Colors.green,
  75. ledColor: Colors.white,
  76. channelShowBadge: true,
  77. playSound: true,
  78. importance: NotificationImportance.Max,
  79. ),
  80. NotificationChannel(
  81. channelGroupKey: NotificationChannels.chatChannelGroupKey,
  82. channelKey: NotificationChannels.chatChannelKey,
  83. channelName: NotificationChannels.chatChannelName,
  84. groupKey: NotificationChannels.chatGroupKey,
  85. channelDescription: NotificationChannels.chatChannelDescription,
  86. defaultColor: Colors.green,
  87. ledColor: Colors.white,
  88. channelShowBadge: true,
  89. playSound: true,
  90. importance: NotificationImportance.Max,
  91. ),
  92. ],
  93. channelGroups: [
  94. NotificationChannelGroup(
  95. channelGroupKey: NotificationChannels.generalChannelGroupKey,
  96. channelGroupName: NotificationChannels.generalChannelGroupName,
  97. ),
  98. NotificationChannelGroup(
  99. channelGroupKey: NotificationChannels.chatChannelGroupKey,
  100. channelGroupName: NotificationChannels.chatChannelGroupName,
  101. ),
  102. ],
  103. );
  104. }
  105. //display notification for user with sound
  106. static Future<bool> showNotification({
  107. required String title,
  108. required String body,
  109. required int id,
  110. String? channelKey,
  111. String? groupKey,
  112. NotificationLayout? notificationLayout,
  113. String? summary,
  114. List<NotificationActionButton>? actionButtons,
  115. Map<String, String>? payload,
  116. String? largeIcon,
  117. }) async {
  118. try {
  119. final isAllowed = await checkNotificationPermission();
  120. if (!isAllowed) {
  121. final requested = await requestNotificationPermission();
  122. if (!requested) return false;
  123. }
  124. await awesomeNotifications.createNotification(
  125. content: NotificationContent(
  126. id: id,
  127. title: title,
  128. body: body,
  129. groupKey: groupKey ?? NotificationChannels.generalGroupKey,
  130. channelKey: channelKey ?? NotificationChannels.generalChannelKey,
  131. showWhen: true,
  132. payload: payload,
  133. notificationLayout: notificationLayout ?? NotificationLayout.Default,
  134. autoDismissible: true,
  135. summary: summary,
  136. largeIcon: largeIcon,
  137. ),
  138. actionButtons: actionButtons,
  139. );
  140. return true;
  141. } catch (e) {
  142. log(TAG, 'Sending notification failed: $e');
  143. return false;
  144. }
  145. }
  146. }
  147. class NotificationController {
  148. /// Use this method to detect when a new notification or a schedule is created
  149. @pragma("vm:entry-point")
  150. static Future<void> onNotificationCreatedMethod(
  151. ReceivedNotification receivedNotification,
  152. ) async {
  153. // Your code goes here
  154. }
  155. /// Use this method to detect every time that a new notification is displayed
  156. @pragma("vm:entry-point")
  157. static Future<void> onNotificationDisplayedMethod(
  158. ReceivedNotification receivedNotification,
  159. ) async {
  160. // Your code goes here
  161. }
  162. /// Use this method to detect if the user dismissed a notification
  163. @pragma("vm:entry-point")
  164. static Future<void> onDismissActionReceivedMethod(
  165. ReceivedAction receivedAction,
  166. ) async {
  167. // Your code goes here
  168. }
  169. /// Use this method to detect when the user taps on a notification or action button
  170. @pragma("vm:entry-point")
  171. static Future<void> onActionReceivedMethod(
  172. ReceivedAction receivedAction,
  173. ) async {
  174. try {
  175. final payload = receivedAction.payload;
  176. if (payload != null) {
  177. final route = payload['route'];
  178. if (route != null) {
  179. Get.key.currentState?.pushNamed(route);
  180. } else {
  181. Get.key.currentState?.pushNamed(Routes.HOME);
  182. }
  183. }
  184. } catch (e) {
  185. log(
  186. "onActionReceivedMethod",
  187. 'Handling notification click event failed: $e',
  188. );
  189. }
  190. }
  191. }
  192. class NotificationChannels {
  193. // chat channel (for messages only)
  194. static String get chatChannelKey => "chat_channel";
  195. static String get chatChannelName => "Chat Notifications";
  196. static String get chatGroupKey => "chat_group_key";
  197. static String get chatChannelGroupKey => "chat_channel_group";
  198. static String get chatChannelGroupName => "Chat Notifications";
  199. static String get chatChannelDescription =>
  200. "Receive chat and message notifications";
  201. // general channel (for all other notifications)
  202. static String get generalChannelKey => "general_channel";
  203. static String get generalGroupKey => "general_group_key";
  204. static String get generalChannelGroupKey => "general_channel_group";
  205. static String get generalChannelGroupName => "General Notifications";
  206. static String get generalChannelName => "General Notifications";
  207. static String get generalChannelDescription =>
  208. "Receive general app notifications";
  209. }