import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_installations/firebase_installations.dart';
import 'package:flutter_udid/flutter_udid.dart';
import 'package:todoList_flutter/api/interceptor.dart';
import 'firebase_options.dart';
import 'dart:developer' as developer;
import 'dart:io';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:firebase_in_app_messaging/firebase_in_app_messaging.dart';
import 'package:flutter/services.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in_dartio/google_sign_in_dartio.dart';
import 'package:flutter/foundation.dart';
import 'package:get_it/get_it.dart';
import 'package:timezone/data/latest_all.dart' as tz;
import 'package:timezone/timezone.dart' as tz;
import 'local_notifications.dart';
// import 'interceptor.dart';

GetIt locator = GetIt.instance;
final ApiClient apiClient = locator<ApiClient>();

@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  // If you're going to use other Firebase services in the background, such as Firestore,
  // make sure you call `initializeApp` before using other Firebase services.
  print("后台通知");
  print("Handling a background message: ${message.messageId}");
  print("title: ${message.notification?.title}");
  print("body: ${message.notification?.body}");
  print("payload: ${message.data}");
}

/// Requires that a Firebase local emulator is running locally.
/// See https://firebase.flutter.dev/docs/auth/start/#optional-prototype-and-test-with-firebase-local-emulator-suite
bool shouldUseFirebaseEmulator = false;

class FirebaseServers {
  late final FirebaseApp app;
  late final FirebaseAuth auth;
  late final FirebaseInAppMessaging fiam;
  late final FlutterLocalNotificationsPlugin localNoti;
  FirebaseServers();
  Future<dynamic> initializeFirebase() async {
    app = await Firebase.initializeApp(
      options: DefaultFirebaseOptions.currentPlatform,
    );
    // 在这里添加其他的初始化逻辑
    auth = await setupFirebaseAuth(app);
    fiam = await setupInAppMessaging();
    // 初始化本地通知
    localNoti = await setupLocalNotifications();

    return {
      'app': app,
      'auth': auth,
      'fiam': fiam,
      'localNoti': localNoti,
    };
  }

  Future<String> getNotificationToken() async {
    final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
    String? token = await _firebaseMessaging.getToken();
    // 后台运行通知回调
    FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
    // 前台运行通知监听
    FirebaseMessaging.onMessage.listen(handleMessage);
    // 监听 后台运行时通过系统信息条打开应用
    FirebaseMessaging.onMessageOpenedApp.listen(onMessageOpenedApp);
    // 如需在每次令牌更新时获得通知
    FirebaseMessaging.instance.onTokenRefresh.listen((fcmToken) {
      // TODO: If necessary send token to application server.
      print("FCM Token${fcmToken}");
      // 每当生成新令牌时,都会触发此回调。
    }).onError((err) {
      print('FCM Token Error: $err');
      // Error getting token.
    });

    return token!;
  }

  Future<String> getFirebaseInstallationId() async {
    String installationId;

    try {
      installationId =
          await FirebaseInstallations.id ?? 'Unknown installation id';
    } on PlatformException {
      installationId = 'Failed to get installation id.';
    }
    return installationId;
  }

  Future<FirebaseAuth> setupFirebaseAuth(FirebaseApp app) async {
    FirebaseAuth auth;
    auth = FirebaseAuth.instanceFor(app: app);

    if (shouldUseFirebaseEmulator) {
      await auth.useAuthEmulator('localhost', 9099);
    }
    if (!kIsWeb && Platform.isWindows) {
      //   await GoogleSignInDart.register(
      // clientId: DefaultFirebaseOptions.currentPlatform.,
      //   );
    }
    FirebaseAuth.instance.authStateChanges().listen((User? user) {
      if (user == null) {
        print('User is currently signed out!');
      } else {
        print('User is signed in!');
      }
    });
    return auth;
  }

  Future<FirebaseInAppMessaging> setupInAppMessaging() async {
    FirebaseInAppMessaging fiam = await FirebaseInAppMessaging.instance;
    // fiam.setMessagesSuppressed(false);
    // fiam.setAutoDisplayDefaultInAppMessage(true);
    await fiam.setAutomaticDataCollectionEnabled(true);

    print('In-App Messaging setup completed');
    return fiam;
  }

  Future<FlutterLocalNotificationsPlugin> setupLocalNotifications() async {
    // 初始化服务
    FlutterLocalNotificationsPlugin localNoti =
        await LocalNotificationsService().initialize();

    developer.log('Local Notifications setup completed');

    return localNoti;
  }

  void logEvent(String eventName, Map<String, dynamic> parameters) {
    FirebaseAnalytics analytics = FirebaseAnalytics.instance;
    analytics.logEvent(name: eventName, parameters: parameters);
  }

  void onMessageOpenedApp(RemoteMessage message) {
    print("打开通知");
    print("Handling a background message: ${message.messageId}");
    print("title: ${message.notification?.title}");
    print("body: ${message.notification?.body}");
    print("payload: ${message.data}");
  }

  void handleMessage(RemoteMessage? message) {
    // 如果消息不是空的话
    if (message == null) return;
    // 用户点击通知, 进入特定该页面
    // Get.toNamed("/home", arguments: message);
    print("前台通知");
    print("title: ${message.notification?.title}");
    print("body: ${message.notification?.body}");
    print("payload: ${message.data}");

    if (localNoti == null) {
      print('Local Notifications Plugin is not initialized');
      return;
    }

    // 显示通知
    LocalNotificationsService().showNotification(
      title: message.notification?.title ?? '',
      body: message.notification?.body ?? '',
      payload: message.data.toString(),
    );
  }
}

Future setupFirebase() async {
  FirebaseServers firebaseServers = FirebaseServers();
  final firebaseResult =
      await firebaseServers.initializeFirebase(); // 在 setupFirebase() 中进行初始化
  // 从返回的 Map 中提取值
  final FirebaseApp firebaseApp = firebaseResult['app'];
  final FirebaseAuth firebaseAuth = firebaseResult['auth'];
  final FirebaseInAppMessaging firebaseInAppMessaging = firebaseResult['fiam'];
  String? token = await firebaseServers.getNotificationToken();
  String? installationId = await firebaseServers.getFirebaseInstallationId();
  //   当token  获取到之后,通过调用接口将token 传递给后端
  String udid = await FlutterUdid.consistentUdid;
  developer.log(udid, name: '设备唯一标识符 - UDID');
  developer.log(token, name: '${Platform.operatingSystem} messaging - Token');
  developer.log(installationId, name: 'Firebase Installation ID');
  dynamic requestData = await apiClient.post('/firebase/token', data: {
    'device_id': udid,
    'token_type': 'messaging', // 'messaging' or 'analytics
    'token_value': token,
  });
  developer.log(requestData.toString(), name: 'Firebase Token');

//
  locator.registerLazySingleton(() => firebaseApp);
  locator.registerLazySingleton(() => firebaseAuth);
  locator.registerLazySingleton(() => firebaseInAppMessaging);

  return firebaseServers;
}

完整代码如上:

  1. 首先你要根据firebase入门文档进行操作.
  2. 在任意目录下创建firebase_servers.dart
  3. 将上面完整代码粘贴到firebase_servers.dart
  4. main.dart中引用import 'firebase_servers.dart';
  5. main.dart中使用它
import 'package:todoList_flutter/api/locator.dart';
import 'package:todoList_flutter/app.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:todoList_flutter/simple_bloc_observer.dart';
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'dart:async';
import 'dart:developer' as developer;
import 'package:timezone/data/latest_all.dart' as tz;
import 'package:timezone/timezone.dart' as tz;

import 'firebase_servers.dart';
import 'android_system.dart';
import 'setup_request_permission.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  tz.initializeTimeZones();

  Bloc.observer = const SimpleBlocObserver();

  await setupRequestPermissions();

  await setupLocator();

  // 在这里使用-----
  await setupFirebase();

  runApp(const App());

//   runZonedGuarded(() {}, (dynamic error, dynamic stack) {
//     developer.log("Something went wrong!", error: error, stackTrace: stack);
//   });

  await setupInitAndroidSystem();
}

前台通知是使用flutter_local_notifications 这个插件实现的, 然后对这个插件也进行了封装.

代码如下:

import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/data/latest_all.dart' as tz;
import 'package:timezone/timezone.dart' as tz;

class LocalNotificationsService {
  int id = 0;
  LocalNotificationsService._();

  static final _instance = LocalNotificationsService._();

  factory LocalNotificationsService() => _instance;

  FlutterLocalNotificationsPlugin? _flutterLocalNotificationsPlugin;

  Future selectNotification(String? payload) async {
    // 处理通知点击事件
    if (payload != null) {
      debugPrint('notification payload: ' + payload);
    }
  }

  Future<FlutterLocalNotificationsPlugin> initialize() async {
    // 初始化插件
    _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();

    // 配置插件
    // 配置Android初始化设置
    const AndroidInitializationSettings androidInitializationSettings =
        AndroidInitializationSettings('icon_notification');
    // 配置iOS和macOS的初始化设置
    const DarwinInitializationSettings darwinInitializationSettings =
        DarwinInitializationSettings();
    // 配置Linux的初始化设置
    const LinuxInitializationSettings linuxInitializationSettings =
        LinuxInitializationSettings(defaultActionName: 'default_action');
    // 配置所有平台的初始化设置
    const InitializationSettings initializationSettings =
        InitializationSettings(
      android: androidInitializationSettings,
      iOS: darwinInitializationSettings,
      macOS: darwinInitializationSettings,
      linux: linuxInitializationSettings,
    );

    // 使用配置初始化插件
    await _flutterLocalNotificationsPlugin!.initialize(
      initializationSettings,
      onDidReceiveNotificationResponse: (NotificationResponse response) {
        // 处理通知点击事件
        debugPrint('notification payload: ' + response.payload!);
      },
    );

    return _flutterLocalNotificationsPlugin!;
  }

  Future<void> showNotification({
    required String title,
    required String body,
    String? payload,
  }) async {
    id += 1;
    // 显示通知
    // 创建Android通知的详细设置
    const AndroidNotificationDetails androidNotificationDetails =
        AndroidNotificationDetails('your channel id', 'your channel name',
            channelDescription: 'your channel description', // 频道的描述。
            importance: Importance.max, // 通知的重要性。
            priority: Priority.high, // 通知的优先级。
            ticker: 'ticker'); // 通知的提示文本。

    // 创建通知渠道
    // const AndroidNotificationChannel channel = AndroidNotificationChannel(
    //   'my_notification_channel', // id
    //   'My Notifications', // title
    //   //   'This channel is used for my notifications.', // description
    //   importance: Importance.max,
    // );
    // 创建通知的详细设置
    const NotificationDetails notificationDetails =
        NotificationDetails(android: androidNotificationDetails); // 创建通知
    // 显示通知
    await _flutterLocalNotificationsPlugin!.show(
      id, // 通知的 ID。
      title, // 通知的标题。
      body, // 通知的内容。
      notificationDetails, // 通知的详细设置。
      payload: payload, // 通知的数据。
    );
  }

  Future<void> scheduleNotification({
    required String title,
    required String body,
    required tz.TZDateTime scheduledDate,
  }) async {
    // 安排通知
    // 定义本地通知的Android通知详细信息。
    const AndroidNotificationDetails androidNotificationDetails =
        AndroidNotificationDetails('your channel id', 'your channel name',
            channelDescription: 'your channel description',
            importance: Importance.max,
            priority: Priority.high,
            ticker: 'ticker');

    // 定义本地通知的详细信息。
    const NotificationDetails notificationDetails =
        NotificationDetails(android: androidNotificationDetails);

    // 使用Flutter Local Notifications插件安排本地通知。
    await _flutterLocalNotificationsPlugin!.zonedSchedule(
      0, // 通知的ID。
      title, // 通知的标题。
      body, // 通知的正文。
      scheduledDate, // 应安排通知的日期和时间。
      notificationDetails, // 通知的详细信息。
      androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle, // 安排模式。
      uiLocalNotificationDateInterpretation:
          UILocalNotificationDateInterpretation.absoluteTime, // 日期解释。
    );
  }

  // 在这里添加更多不同类型的通知方法
  // 例如:showImageNotification、showProgressNotification、showGroupNotification、addActionButtons等等
}



// // 安排通知
//     final tz.TZDateTime scheduledDate =
//         tz.TZDateTime.now(tz.local).add(Duration(seconds: 5));
//     LocalNotificationsService().scheduleNotification(
//       title: '安排通知标题',
//       body: '安排通知内容',
//       scheduledDate: scheduledDate,
//     );

还有就是 想实现通知 你需要请求app的通知权限.

请求通知权限可以使用permission_handler插件,也一样 对这个插件进行封装.

import 'package:permission_handler/permission_handler.dart';

Future requestPermissions() async {
  // Request notification permission
  PermissionStatus notificationStatus = await Permission.notification.request();

  // Request other permissions
  PermissionStatus cameraStatus = await Permission.camera.request();
  PermissionStatus locationStatus = await Permission.location.request();

  // Check the permission statuses
  if (notificationStatus.isGranted) {
    print('Notification permission granted');
  } else {
    print('Notification permission denied');
  }

  if (cameraStatus.isGranted) {
    print('Camera permission granted');
  } else {
    print('Camera permission denied');
  }

  if (locationStatus.isGranted) {
    print('Location permission granted');
  } else {
    print('Location permission denied');
  }
}

Future setupRequestPermissions() async {
  await requestPermissions();
}

这个封装就很基础了,没有使用很复杂的东西.

最后修改:2024 年 05 月 23 日
如果觉得我的文章对你有用,请随意赞赏