Flutter Push通知

FlutterでのPush通知が結構面倒だったのでまとめておきます
FCMの基本準備と設定は他の記事を参考にしてください
## 特徴
##### iOS
APNsとFCMTokenのマッピングを行う

##### Android
フォアグラウンドの時にはFCMをLocalMessageに変換して表示する

## iOS準備
Signing&Capabilities でこの設定を入れる
![スクリーンショット 2022-11-06 12.03.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566476/0f336759-ce5d-fc06-8da0-1ff8f073e0d9.png)


## コード
``` swift: AppDelegate.swift
import UIKit
import Flutter
import Firebase

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
    
  override func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    print("APNs token retrieved: \(deviceToken)")

    //　メソッド実装入れ替えをしない場合、APNs発行のデバイストークンとFCM発行デバイストークンを明示的にマッピングする必要があります。
     Messaging.messaging().apnsToken = deviceToken
  }
}

```

``` dart: Dartファイル
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
    FlutterLocalNotificationsPlugin();

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final messaging = FirebaseMessaging.instance;
    messaging.getInitialMessage().then((message) {
    // 通知タップでアプリ起動したちときの処理
    });
　　　　　　　　// 通知の許可をとる
    messaging.requestPermission(
      alert: true,
      announcement: true,
      badge: true,
      carPlay: true,
      criticalAlert: false,
      provisional: false,
      sound: true,
    );
    FirebaseMessaging.onMessageOpenedApp.listen((message) {
　　　　　　　　　　　　// アプリがバックグラウンドの時に通知タップでアプリを開いた時の処理
    });

    if (Platform.isAndroid) {
      var androidSetting = const AndroidInitializationSettings('@mipmap/ic_launcher');
      final settings = InitializationSettings(android: androidSetting);
      flutterLocalNotificationsPlugin.initialize(
        settings,
        onDidReceiveNotificationResponse: (res) {
　　　　　　　　　　　　　　　　    // ローカル通知を受け取った時の処理
        },
      );
      flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
          AndroidFlutterLocalNotificationsPlugin>()
          ?.requestPermission();
      FirebaseMessaging.onMessage.listen((RemoteMessage message) {
        RemoteNotification? notification = message.notification;
        AndroidNotification? android = message.notification?.android;
        if (notification != null && android != null) {
          // フォアグラウンドで通知を受け取った場合、通知を作成してLocal通知に変換する
          flutterLocalNotificationsPlugin.show(
            notification.hashCode,
            notification.title,
            notification.body,
            const NotificationDetails(
              // 通知channelを設定する
              android: AndroidNotificationDetails(
                'Like_Channel', // channelId
                'Channel_Name', // channelName
                importance: Importance.max,
                priority: Priority.high,
                icon: 'launch_background',
              ),
            ),
            payload: "parameter",
          );
        }
      });
    } else {
      // iOS用　フォアグラウンドでPush通知の表示させる
      messaging.setForegroundNotificationPresentationOptions(
        alert: true,
        badge: true,
        sound: true,
      );
    }
 
    // トークンを取得してからWidgetを表示する
    return MaterialApp(
      home: FutureBuilder(
        future: FirebaseMessaging.instance.getToken(),
        builder: (_, AsyncSnapshot<String?> snapshot) {
          if (!snapshot.hasData) {
            return const Center(child: CircularProgressIndicator());
          }
          print("token");
          print(snapshot.data ?? "");
          return Container();
        },
      ),
    );
  }
}

```