🔔

🔔StreamNotifierでpush通知を受け取る

2024/02/04に公開

読んでほしい人

  • riverod generatorの知識がある人
  • riverpod2.0でFCM使ってみるのに、興味がある人
  • FirebaseのFCMを使ったことある人

補足情報

Androidの実機で動作検証してます。iOSには今回対応しておりません🙅
もしやるならこのコードが必要ですね。Apple Developerアカウントも必要です。
https://firebase.flutter.dev/docs/messaging/usage

FirebaseMessaging messaging = FirebaseMessaging.instance;

NotificationSettings settings = await messaging.requestPermission(
  alert: true,
  announcement: false,
  badge: true,
  carPlay: false,
  criticalAlert: false,
  provisional: false,
  sound: true,
);

print('User granted permission: ${settings.authorizationStatus}');

記事の内容

Firebase FCMを使って、Androidの端末に通知のタイトル(title)と通知のテキスト(body)を送信してみようと思います。遅延があるみたいで、2回ぐらい実行したり少し待ったら通知が端末に来ました???

fcm tokenが必要なので、logを出すコードを書いておいてください。printでもloggerでも良いです。

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:hooks_example/fcm_example/fcm_stream_view.dart';
import 'package:hooks_example/firebase_options.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  // fcm tokenを取得
  final fcmToken = await FirebaseMessaging.instance.getToken();
  // fcm tokenを表示
  debugPrint('🐈fcm token: $fcmToken');
  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const FcmStreamView(),
    );
  }
}

リアルタイムに取得しないと通知をViewに表示できないので、StreamNotifierを使います。通知をView側に表示するには、画面を更新してあげる必要があります。昔だとStateNotifierでやるみたいです。

実験用のコードなのでよくはないかも?

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'fcm_stream_notifier.g.dart';


class FcmStreamNotifier extends _$FcmStreamNotifier {

  // Stream<List<RemoteMessage>>のデータ型を返す
  
  Stream<List<RemoteMessage>> build() {
    // listという空のリストを作成
    var list = <RemoteMessage>[];
    // FirebaseMessaging.onMessage.mapでメッセージを受け取る
    return FirebaseMessaging.onMessage.map((message) {
      // listにFirebaseMessaging.onMessage.mapで受け取ったメッセージを追加
      list.add(message);
      // onDisposeでlistをクリア
       ref.onDispose(() {
        list.clear();
       });
      return list;
    });
  }
}

View側のコードは、通知が来るたびにリアルタイムに、内容を表示します。titleが通知のタイトル。bodyが通知のテキストの内容です。このコードも実験用なので、微妙ですね。

import 'package:flutter/material.dart';
import 'package:hooks_example/fcm_example/fcm_stream_notifier.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';

class FcmStreamView extends HookConsumerWidget {
  const FcmStreamView({super.key});
  
  Widget build(BuildContext context, WidgetRef ref) {
    final asyncValue = ref.watch(fcmStreamNotifierProvider);
    return Scaffold(
      appBar: AppBar(
        title: const Text('FCM Stream Riverpod🐈'),
      ),
      body: Center(
        child: asyncValue.when(
          data: (messages) {
            return ListView.builder(
              itemCount: messages.length,// mstの数だけリストを作成
              itemBuilder: (context, index) {
                final message = messages[index];
                return ListTile(
                  title: Text('Message data: ${message.notification!.title}'),// タイトルを表示
                  subtitle: message.notification != null
                      ? Text(
                          'Notification title: ${message.notification!.body}')// テキストの内容
                      : null,
                );
              },
            );
          },
          loading: () => const CircularProgressIndicator(),
          error: (error, stackTrace) => Text('Error: $error'),
        ),
      ),
    );
  }
}

ビルドしたら、logが出るので、tokenをコピーしてください。

こんな感じで、コンソールにtokenをコピペして設定して送信してみてください。

こんな感じですね。

最後に

今回は、riverpodで状態管理をして通知のテストをやってみました。スクラップに色々試行錯誤した記録もまとめているので、ご興味あれば見てください。

参考にした情報:
https://firebase.google.com/docs/cloud-messaging/flutter/client?hl=ja

zennのスクラップ:
https://zenn.dev/joo_hashi/scraps/42e95c9e92720b

Discussion