@@ -27,25 +27,25 @@ class OneSignalPushNotificationClient implements IPushNotificationClient {
2727 final Logger _log;
2828
2929 @override
30- Future <void > sendNotification ({
30+ Future <PushNotificationResult > sendNotification ({
3131 required String deviceToken,
3232 required PushNotificationPayload payload,
33- }) async {
33+ }) {
3434 // For consistency, delegate to the bulk sending method with a single token.
35- await sendBulkNotifications (
35+ return sendBulkNotifications (
3636 deviceTokens: [deviceToken],
3737 payload: payload,
3838 );
3939 }
4040
4141 @override
42- Future <void > sendBulkNotifications ({
42+ Future <PushNotificationResult > sendBulkNotifications ({
4343 required List <String > deviceTokens,
4444 required PushNotificationPayload payload,
4545 }) async {
4646 if (deviceTokens.isEmpty) {
4747 _log.info ('No device tokens provided for OneSignal bulk send. Aborting.' );
48- return ;
48+ return const PushNotificationResult () ;
4949 }
5050
5151 _log.info (
@@ -55,6 +55,9 @@ class OneSignalPushNotificationClient implements IPushNotificationClient {
5555
5656 // OneSignal has a limit of 2000 player_ids per API request.
5757 const batchSize = 2000 ;
58+ final allSentTokens = < String > [];
59+ final allFailedTokens = < String > [];
60+
5861 for (var i = 0 ; i < deviceTokens.length; i += batchSize) {
5962 final batch = deviceTokens.sublist (
6063 i,
@@ -63,15 +66,26 @@ class OneSignalPushNotificationClient implements IPushNotificationClient {
6366 : i + batchSize,
6467 );
6568
66- await _sendBatch (
69+ final batchResult = await _sendBatch (
6770 deviceTokens: batch,
6871 payload: payload,
6972 );
73+
74+ allSentTokens.addAll (batchResult.sentTokens);
75+ allFailedTokens.addAll (batchResult.failedTokens);
7076 }
77+
78+ return PushNotificationResult (
79+ sentTokens: allSentTokens,
80+ failedTokens: allFailedTokens,
81+ );
7182 }
7283
7384 /// Sends a single batch of notifications to the OneSignal API.
74- Future <void > _sendBatch ({
85+ ///
86+ /// This method processes the API response to distinguish between successful
87+ /// and failed sends, returning a [PushNotificationResult] .
88+ Future <PushNotificationResult > _sendBatch ({
7589 required List <String > deviceTokens,
7690 required PushNotificationPayload payload,
7791 }) async {
@@ -95,17 +109,49 @@ class OneSignalPushNotificationClient implements IPushNotificationClient {
95109 );
96110
97111 try {
98- await _httpClient.post <void >(url, data: requestBody);
112+ // The OneSignal API returns a JSON object with details about the send,
113+ // including errors for invalid player IDs.
114+ final response = await _httpClient.post <Map <String , dynamic >>(
115+ url,
116+ data: requestBody,
117+ );
118+
119+ final sentTokens = < String > {...deviceTokens};
120+ final failedTokens = < String > {};
121+
122+ // Check for errors in the response body.
123+ if (response.containsKey ('errors' ) && response['errors' ] != null ) {
124+ final errors = response['errors' ];
125+ if (errors is Map && errors.containsKey ('invalid_player_ids' )) {
126+ final invalidIds = List <String >.from (
127+ errors['invalid_player_ids' ] as List ,
128+ );
129+ if (invalidIds.isNotEmpty) {
130+ _log.info (
131+ 'OneSignal reported ${invalidIds .length } invalid player IDs. '
132+ 'These will be marked as failed.' ,
133+ );
134+ failedTokens.addAll (invalidIds);
135+ sentTokens.removeAll (invalidIds);
136+ }
137+ }
138+ }
139+
99140 _log.info (
100- 'Successfully sent OneSignal batch of ${deviceTokens .length } '
101- 'notifications for app ID "$appId ".' ,
141+ 'OneSignal batch complete. Success: ${sentTokens .length }, '
142+ 'Failed: ${failedTokens .length }.' ,
143+ );
144+ return PushNotificationResult (
145+ sentTokens: sentTokens.toList (),
146+ failedTokens: failedTokens.toList (),
102147 );
103148 } on HttpException catch (e) {
104149 _log.severe (
105150 'HTTP error sending OneSignal batch notification: ${e .message }' ,
106151 e,
107152 );
108- rethrow ;
153+ // If the entire request fails, all tokens in this batch are considered failed.
154+ return PushNotificationResult (failedTokens: deviceTokens);
109155 } catch (e, s) {
110156 _log.severe (
111157 'Unexpected error sending OneSignal batch notification.' ,
0 commit comments