diff --git a/packages/stream_chat_v1/android/app/src/main/AndroidManifest.xml b/packages/stream_chat_v1/android/app/src/main/AndroidManifest.xml index 6f96e79..6763066 100644 --- a/packages/stream_chat_v1/android/app/src/main/AndroidManifest.xml +++ b/packages/stream_chat_v1/android/app/src/main/AndroidManifest.xml @@ -30,6 +30,14 @@ android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme" /> + @@ -45,7 +53,7 @@ android:name="flutterEmbedding" android:value="2" /> - _onFirebaseBackgroundMessage(RemoteMessage message) async { + // initialize Firebase await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); final data = message.data; + // ensure that Push Notification was sent by Stream. + if (data['sender'] != 'stream.chat') { + return; + } + // ensure that Push Notification relates to a new message event. if (data['type'] != 'message.new') { return; } + // read existing user info. String? apiKey, userId, token; if (!kIsWeb) { const secureStorage = FlutterSecureStorage(); @@ -45,16 +59,21 @@ Future _onFirebaseBackgroundMessage(RemoteMessage message) async { } final client = buildStreamChatClient(apiKey ?? kDefaultStreamApiKey); final persistenceClient = StreamChatPersistenceClient(); + + // initialize persistence with current user await persistenceClient.connect(userId); + // initialize client with current user await client.connectUser( User(id: userId), token, + // do not open WS connection connectWebSocket: false, ); final messageId = data['id']; final cid = data['cid']; + // pre-cache the new message using client and persistence. final response = await client.getMessage(messageId); await persistenceClient.updateMessages(cid, [response.message]); } @@ -133,29 +152,42 @@ class _StreamChatSampleAppState extends State .map((it) => it?.id) .distinct() .listen((userId) async { + // User logged in if (userId != null) { + // Requests notification permission. await FirebaseMessaging.instance.requestPermission(); + // Sets callback for background messages (it's not called on iOS) FirebaseMessaging.onBackgroundMessage(_onFirebaseBackgroundMessage); + // Sets callback for the notification click event. firebaseSubscriptions.add(FirebaseMessaging.onMessageOpenedApp .listen(_onFirebaseMessageOpenedApp(client))); + // Sets callback for the token refresh event. firebaseSubscriptions.add(FirebaseMessaging.instance.onTokenRefresh .listen(_onFirebaseTokenRefresh(client))); + final token = await FirebaseMessaging.instance.getToken(); if (token != null) { + // add Token to Stream await client.addDevice(token, PushProvider.firebase); } - } else { + } + // User logged out + else { firebaseSubscriptions.cancelAll(); final token = await FirebaseMessaging.instance.getToken(); if (token != null) { + // remove token from Stream await client.removeDevice(token); } } }); } + /// Constructs callback for notification click event. OnRemoteMessage _onFirebaseMessageOpenedApp(StreamChatClient client) { return (message) async { + // This callback is getting invoked when the user clicks + // on the notification in case if notification was shown by OS. final channelType = (message.data['channel_type'] as String?) ?? ''; final channelId = (message.data['channel_id'] as String?) ?? ''; final channelCid = (message.data['cid'] as String?) ?? ''; @@ -167,6 +199,7 @@ class _StreamChatSampleAppState extends State ); await channel.watch(); } + // Navigates to Channel page, which is associated with the notification. GoRouter.of(_navigatorKey.currentContext!).pushNamed( Routes.CHANNEL_PAGE.name, params: Routes.CHANNEL_PAGE.params(channel), @@ -174,10 +207,12 @@ class _StreamChatSampleAppState extends State }; } + /// Constructs callback for notification refresh event. Future Function(String) _onFirebaseTokenRefresh( StreamChatClient client, ) { return (token) async { + // This callback is getting invoked when the token got refreshed. await client.addDevice(token, PushProvider.firebase); }; } diff --git a/packages/stream_chat_v1/pubspec.yaml b/packages/stream_chat_v1/pubspec.yaml index 2ced1e0..8a924d8 100644 --- a/packages/stream_chat_v1/pubspec.yaml +++ b/packages/stream_chat_v1/pubspec.yaml @@ -12,20 +12,11 @@ dependencies: flutter: sdk: flutter stream_chat_flutter: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_flutter + path: ../../../stream-chat-flutter/packages/stream_chat_flutter stream_chat_persistence: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_persistence + path: ../../../stream-chat-flutter/packages/stream_chat_persistence stream_chat_localizations: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_localizations + path: ../../../stream-chat-flutter/packages/stream_chat_localizations flutter_local_notifications: ^9.0.0 flutter_svg: ^2.0.4 flutter_secure_storage: ^6.0.0 @@ -46,20 +37,11 @@ dev_dependencies: dependency_overrides: stream_chat: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat + path: ../../../stream-chat-flutter/packages/stream_chat stream_chat_flutter_core: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_flutter_core + path: ../../../stream-chat-flutter/packages/stream_chat_flutter_core stream_chat_flutter: - git: - url: https://github.com/GetStream/stream-chat-flutter.git - ref: develop - path: packages/stream_chat_flutter + path: ../../../stream-chat-flutter/packages/stream_chat_flutter flutter: uses-material-design: true @@ -78,4 +60,4 @@ flutter_icons: windows: generate: true macos: - generate: true + generate: true \ No newline at end of file