@loyalytics/swan-react-native-sdk 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +55 -0
- package/README.md +67 -0
- package/docs/IOS_NOTIFICATION_EXTENSION_SETUP.md +335 -0
- package/ios/README.md +64 -0
- package/ios/SwanNotificationServiceExtension/Info.plist +31 -0
- package/ios/SwanNotificationServiceExtension/NotificationService.swift +337 -0
- package/ios/SwanNotificationServiceExtension/SwanNotificationServiceExtension.entitlements +10 -0
- package/lib/commonjs/components/FooterView.js +125 -0
- package/lib/commonjs/components/FooterView.js.map +1 -0
- package/lib/commonjs/components/FullScreenView.js +172 -0
- package/lib/commonjs/components/FullScreenView.js.map +1 -0
- package/lib/commonjs/components/HeaderView.js +205 -0
- package/lib/commonjs/components/HeaderView.js.map +1 -0
- package/lib/commonjs/components/PopUpView.js +186 -0
- package/lib/commonjs/components/PopUpView.js.map +1 -0
- package/lib/commonjs/config/BatchConfig.js +53 -0
- package/lib/commonjs/config/BatchConfig.js.map +1 -0
- package/lib/commonjs/constants/ApiUrls.js +56 -0
- package/lib/commonjs/constants/ApiUrls.js.map +1 -0
- package/lib/commonjs/core/EventQueueManager.js +345 -0
- package/lib/commonjs/core/EventQueueManager.js.map +1 -0
- package/lib/commonjs/core/FlushManager.js +245 -0
- package/lib/commonjs/core/FlushManager.js.map +1 -0
- package/lib/commonjs/core/NetworkMonitor.js +97 -0
- package/lib/commonjs/core/NetworkMonitor.js.map +1 -0
- package/lib/commonjs/index.js +3506 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/providers/FirebasePushProvider.js +130 -0
- package/lib/commonjs/providers/FirebasePushProvider.js.map +1 -0
- package/lib/commonjs/providers/NullPushProvider.js +59 -0
- package/lib/commonjs/providers/NullPushProvider.js.map +1 -0
- package/lib/commonjs/providers/PushNotificationProvider.js +30 -0
- package/lib/commonjs/providers/PushNotificationProvider.js.map +1 -0
- package/lib/commonjs/services/DeviceRegistrationService.js +248 -0
- package/lib/commonjs/services/DeviceRegistrationService.js.map +1 -0
- package/lib/commonjs/services/PushTokenService.js +284 -0
- package/lib/commonjs/services/PushTokenService.js.map +1 -0
- package/lib/commonjs/state/AuthStateMachine.js +161 -0
- package/lib/commonjs/state/AuthStateMachine.js.map +1 -0
- package/lib/commonjs/state/DeviceStateMachine.js +104 -0
- package/lib/commonjs/state/DeviceStateMachine.js.map +1 -0
- package/lib/commonjs/state/PushStateMachine.js +129 -0
- package/lib/commonjs/state/PushStateMachine.js.map +1 -0
- package/lib/commonjs/types/EventQueue.js +50 -0
- package/lib/commonjs/types/EventQueue.js.map +1 -0
- package/lib/commonjs/types/SDK.js +2 -0
- package/lib/commonjs/types/SDK.js.map +1 -0
- package/lib/commonjs/utils/FirebaseNotificationManager.js +492 -0
- package/lib/commonjs/utils/FirebaseNotificationManager.js.map +1 -0
- package/lib/commonjs/utils/Logger.js +56 -0
- package/lib/commonjs/utils/Logger.js.map +1 -0
- package/lib/commonjs/utils/SharedCredentialsManager.js +146 -0
- package/lib/commonjs/utils/SharedCredentialsManager.js.map +1 -0
- package/lib/commonjs/version.js +12 -0
- package/lib/commonjs/version.js.map +1 -0
- package/lib/module/components/FooterView.js +121 -0
- package/lib/module/components/FooterView.js.map +1 -0
- package/lib/module/components/FullScreenView.js +167 -0
- package/lib/module/components/FullScreenView.js.map +1 -0
- package/lib/module/components/HeaderView.js +199 -0
- package/lib/module/components/HeaderView.js.map +1 -0
- package/lib/module/components/PopUpView.js +181 -0
- package/lib/module/components/PopUpView.js.map +1 -0
- package/lib/module/config/BatchConfig.js +49 -0
- package/lib/module/config/BatchConfig.js.map +1 -0
- package/lib/module/constants/ApiUrls.js +52 -0
- package/lib/module/constants/ApiUrls.js.map +1 -0
- package/lib/module/core/EventQueueManager.js +340 -0
- package/lib/module/core/EventQueueManager.js.map +1 -0
- package/lib/module/core/FlushManager.js +240 -0
- package/lib/module/core/FlushManager.js.map +1 -0
- package/lib/module/core/NetworkMonitor.js +92 -0
- package/lib/module/core/NetworkMonitor.js.map +1 -0
- package/lib/module/index.js +3494 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/providers/FirebasePushProvider.js +124 -0
- package/lib/module/providers/FirebasePushProvider.js.map +1 -0
- package/lib/module/providers/NullPushProvider.js +53 -0
- package/lib/module/providers/NullPushProvider.js.map +1 -0
- package/lib/module/providers/PushNotificationProvider.js +26 -0
- package/lib/module/providers/PushNotificationProvider.js.map +1 -0
- package/lib/module/services/DeviceRegistrationService.js +243 -0
- package/lib/module/services/DeviceRegistrationService.js.map +1 -0
- package/lib/module/services/PushTokenService.js +278 -0
- package/lib/module/services/PushTokenService.js.map +1 -0
- package/lib/module/state/AuthStateMachine.js +155 -0
- package/lib/module/state/AuthStateMachine.js.map +1 -0
- package/lib/module/state/DeviceStateMachine.js +98 -0
- package/lib/module/state/DeviceStateMachine.js.map +1 -0
- package/lib/module/state/PushStateMachine.js +123 -0
- package/lib/module/state/PushStateMachine.js.map +1 -0
- package/lib/module/types/EventQueue.js +46 -0
- package/lib/module/types/EventQueue.js.map +1 -0
- package/lib/module/types/SDK.js +2 -0
- package/lib/module/types/SDK.js.map +1 -0
- package/lib/module/utils/FirebaseNotificationManager.js +486 -0
- package/lib/module/utils/FirebaseNotificationManager.js.map +1 -0
- package/lib/module/utils/Logger.js +52 -0
- package/lib/module/utils/Logger.js.map +1 -0
- package/lib/module/utils/SharedCredentialsManager.js +140 -0
- package/lib/module/utils/SharedCredentialsManager.js.map +1 -0
- package/lib/module/version.js +8 -0
- package/lib/module/version.js.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/components/FooterView.d.ts +3 -0
- package/lib/typescript/commonjs/src/components/FooterView.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/components/FullScreenView.d.ts +3 -0
- package/lib/typescript/commonjs/src/components/FullScreenView.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/components/HeaderView.d.ts +3 -0
- package/lib/typescript/commonjs/src/components/HeaderView.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/components/PopUpView.d.ts +3 -0
- package/lib/typescript/commonjs/src/components/PopUpView.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/config/BatchConfig.d.ts +7 -0
- package/lib/typescript/commonjs/src/config/BatchConfig.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/constants/ApiUrls.d.ts +56 -0
- package/lib/typescript/commonjs/src/constants/ApiUrls.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/core/EventQueueManager.d.ts +63 -0
- package/lib/typescript/commonjs/src/core/EventQueueManager.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/core/FlushManager.d.ts +63 -0
- package/lib/typescript/commonjs/src/core/FlushManager.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/core/NetworkMonitor.d.ts +38 -0
- package/lib/typescript/commonjs/src/core/NetworkMonitor.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +663 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/providers/FirebasePushProvider.d.ts +28 -0
- package/lib/typescript/commonjs/src/providers/FirebasePushProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/providers/NullPushProvider.d.ts +25 -0
- package/lib/typescript/commonjs/src/providers/NullPushProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/providers/PushNotificationProvider.d.ts +105 -0
- package/lib/typescript/commonjs/src/providers/PushNotificationProvider.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/services/DeviceRegistrationService.d.ts +60 -0
- package/lib/typescript/commonjs/src/services/DeviceRegistrationService.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/services/PushTokenService.d.ts +82 -0
- package/lib/typescript/commonjs/src/services/PushTokenService.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/state/AuthStateMachine.d.ts +61 -0
- package/lib/typescript/commonjs/src/state/AuthStateMachine.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/state/DeviceStateMachine.d.ts +51 -0
- package/lib/typescript/commonjs/src/state/DeviceStateMachine.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/state/PushStateMachine.d.ts +61 -0
- package/lib/typescript/commonjs/src/state/PushStateMachine.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/types/EventQueue.d.ts +85 -0
- package/lib/typescript/commonjs/src/types/EventQueue.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/types/SDK.d.ts +54 -0
- package/lib/typescript/commonjs/src/types/SDK.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/utils/FirebaseNotificationManager.d.ts +169 -0
- package/lib/typescript/commonjs/src/utils/FirebaseNotificationManager.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/utils/Logger.d.ts +32 -0
- package/lib/typescript/commonjs/src/utils/Logger.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/utils/SharedCredentialsManager.d.ts +54 -0
- package/lib/typescript/commonjs/src/utils/SharedCredentialsManager.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/version.d.ts +2 -0
- package/lib/typescript/commonjs/src/version.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/src/components/FooterView.d.ts +3 -0
- package/lib/typescript/module/src/components/FooterView.d.ts.map +1 -0
- package/lib/typescript/module/src/components/FullScreenView.d.ts +3 -0
- package/lib/typescript/module/src/components/FullScreenView.d.ts.map +1 -0
- package/lib/typescript/module/src/components/HeaderView.d.ts +3 -0
- package/lib/typescript/module/src/components/HeaderView.d.ts.map +1 -0
- package/lib/typescript/module/src/components/PopUpView.d.ts +3 -0
- package/lib/typescript/module/src/components/PopUpView.d.ts.map +1 -0
- package/lib/typescript/module/src/config/BatchConfig.d.ts +7 -0
- package/lib/typescript/module/src/config/BatchConfig.d.ts.map +1 -0
- package/lib/typescript/module/src/constants/ApiUrls.d.ts +56 -0
- package/lib/typescript/module/src/constants/ApiUrls.d.ts.map +1 -0
- package/lib/typescript/module/src/core/EventQueueManager.d.ts +63 -0
- package/lib/typescript/module/src/core/EventQueueManager.d.ts.map +1 -0
- package/lib/typescript/module/src/core/FlushManager.d.ts +63 -0
- package/lib/typescript/module/src/core/FlushManager.d.ts.map +1 -0
- package/lib/typescript/module/src/core/NetworkMonitor.d.ts +38 -0
- package/lib/typescript/module/src/core/NetworkMonitor.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +663 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -0
- package/lib/typescript/module/src/providers/FirebasePushProvider.d.ts +28 -0
- package/lib/typescript/module/src/providers/FirebasePushProvider.d.ts.map +1 -0
- package/lib/typescript/module/src/providers/NullPushProvider.d.ts +25 -0
- package/lib/typescript/module/src/providers/NullPushProvider.d.ts.map +1 -0
- package/lib/typescript/module/src/providers/PushNotificationProvider.d.ts +105 -0
- package/lib/typescript/module/src/providers/PushNotificationProvider.d.ts.map +1 -0
- package/lib/typescript/module/src/services/DeviceRegistrationService.d.ts +60 -0
- package/lib/typescript/module/src/services/DeviceRegistrationService.d.ts.map +1 -0
- package/lib/typescript/module/src/services/PushTokenService.d.ts +82 -0
- package/lib/typescript/module/src/services/PushTokenService.d.ts.map +1 -0
- package/lib/typescript/module/src/state/AuthStateMachine.d.ts +61 -0
- package/lib/typescript/module/src/state/AuthStateMachine.d.ts.map +1 -0
- package/lib/typescript/module/src/state/DeviceStateMachine.d.ts +51 -0
- package/lib/typescript/module/src/state/DeviceStateMachine.d.ts.map +1 -0
- package/lib/typescript/module/src/state/PushStateMachine.d.ts +61 -0
- package/lib/typescript/module/src/state/PushStateMachine.d.ts.map +1 -0
- package/lib/typescript/module/src/types/EventQueue.d.ts +85 -0
- package/lib/typescript/module/src/types/EventQueue.d.ts.map +1 -0
- package/lib/typescript/module/src/types/SDK.d.ts +54 -0
- package/lib/typescript/module/src/types/SDK.d.ts.map +1 -0
- package/lib/typescript/module/src/utils/FirebaseNotificationManager.d.ts +169 -0
- package/lib/typescript/module/src/utils/FirebaseNotificationManager.d.ts.map +1 -0
- package/lib/typescript/module/src/utils/Logger.d.ts +32 -0
- package/lib/typescript/module/src/utils/Logger.d.ts.map +1 -0
- package/lib/typescript/module/src/utils/SharedCredentialsManager.d.ts +54 -0
- package/lib/typescript/module/src/utils/SharedCredentialsManager.d.ts.map +1 -0
- package/lib/typescript/module/src/version.d.ts +2 -0
- package/lib/typescript/module/src/version.d.ts.map +1 -0
- package/package.json +230 -0
- package/scripts/generate-version.js +25 -0
- package/scripts/setup-ios-extension.js +275 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
PROPRIETARY SOFTWARE LICENSE
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Loyalytics. All Rights Reserved.
|
|
4
|
+
|
|
5
|
+
NOTICE: This software and its source code are proprietary and confidential
|
|
6
|
+
information of Loyalytics ("Proprietary Information").
|
|
7
|
+
|
|
8
|
+
This software is provided to you under a commercial license agreement with
|
|
9
|
+
Loyalytics. You may not use this software except in compliance with the terms
|
|
10
|
+
of such commercial license agreement.
|
|
11
|
+
|
|
12
|
+
RESTRICTIONS:
|
|
13
|
+
|
|
14
|
+
1. You may NOT redistribute, sublicense, sell, or otherwise transfer this
|
|
15
|
+
software or any portion thereof to any third party.
|
|
16
|
+
|
|
17
|
+
2. You may NOT modify, adapt, translate, reverse engineer, decompile,
|
|
18
|
+
disassemble, or create derivative works based on this software.
|
|
19
|
+
|
|
20
|
+
3. You may NOT remove or alter any copyright, trademark, or other proprietary
|
|
21
|
+
notice from this software.
|
|
22
|
+
|
|
23
|
+
4. You may NOT use this software for any purpose other than as expressly
|
|
24
|
+
authorized in your commercial license agreement with Loyalytics.
|
|
25
|
+
|
|
26
|
+
5. The software is licensed, not sold. Loyalytics retains all right, title,
|
|
27
|
+
and interest in and to the software, including all intellectual property
|
|
28
|
+
rights therein.
|
|
29
|
+
|
|
30
|
+
AUTHORIZED USE:
|
|
31
|
+
|
|
32
|
+
This software may only be used by authorized customers of Loyalytics who have
|
|
33
|
+
entered into a valid commercial license agreement. Use of this software
|
|
34
|
+
constitutes acceptance of the terms and conditions set forth in such
|
|
35
|
+
agreement.
|
|
36
|
+
|
|
37
|
+
To obtain a commercial license or for more information, please contact:
|
|
38
|
+
Email: support@loyalytics.ai
|
|
39
|
+
Website: https://www.loyalytics.ai/
|
|
40
|
+
|
|
41
|
+
DISCLAIMER:
|
|
42
|
+
|
|
43
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
44
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
45
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
46
|
+
LOYALYTICS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
47
|
+
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
48
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
49
|
+
|
|
50
|
+
GOVERNING LAW:
|
|
51
|
+
|
|
52
|
+
This license shall be governed by and construed in accordance with the laws
|
|
53
|
+
of India, without regard to its conflict of law provisions.
|
|
54
|
+
|
|
55
|
+
For licensing inquiries, contact: support@loyalytics.ai
|
package/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Swan React Native SDK
|
|
2
|
+
|
|
3
|
+
> **⚠️ PROPRIETARY SOFTWARE:** This SDK is proprietary software owned by Loyalytics.
|
|
4
|
+
> It requires a valid commercial license for use. See [LICENSE](./LICENSE) for terms.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
**Note:** This package is available via npm for authorized customers only. Installation requires a valid commercial license agreement with Loyalytics.
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
npm install @loyalytics/swan-react-native-sdk
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Or using yarn:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
yarn add @loyalytics/swan-react-native-sdk
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
import SwanSDK from '@loyalytics/swan-react-native-sdk';
|
|
24
|
+
|
|
25
|
+
// Initialize SDK
|
|
26
|
+
const sdk = SwanSDK.getInstance('YOUR_APP_ID', {
|
|
27
|
+
isProduction: false,
|
|
28
|
+
pushNotifications: {
|
|
29
|
+
enabled: true,
|
|
30
|
+
autoRequestPermission: true,
|
|
31
|
+
},
|
|
32
|
+
isProduction: true,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Track events
|
|
36
|
+
sdk.productViewed({ productId: '123' });
|
|
37
|
+
|
|
38
|
+
// Listen for SDK events
|
|
39
|
+
sdk.on('initialized', () => {
|
|
40
|
+
console.log('SDK initialized!');
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## iOS Notification Extension
|
|
45
|
+
|
|
46
|
+
To support Rich Media (Images) and Delivery Tracking (even when the app is killed), you must set up a **Notification Service Extension**.
|
|
47
|
+
|
|
48
|
+
We provide an automated tool and a guide to help you set this up.
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
node ./node_modules/@loyalytics/swan-react-native-sdk/scripts/setup-ios-extension.js
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## License
|
|
55
|
+
|
|
56
|
+
This software is proprietary and confidential. Unauthorized copying, modification,
|
|
57
|
+
distribution, or use of this software is strictly prohibited.
|
|
58
|
+
|
|
59
|
+
Copyright © 2025 Loyalytics. All Rights Reserved.
|
|
60
|
+
|
|
61
|
+
For licensing inquiries, contact: support@loyalytics.ai
|
|
62
|
+
|
|
63
|
+
See the [LICENSE](./LICENSE) file for full terms.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
# iOS Notification Service Extension Setup
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Swan SDK's Notification Service Extension enables:
|
|
6
|
+
- ✅ **Delivery tracking** when app is killed or in background
|
|
7
|
+
- ✅ **Rich media support** (images in notifications)
|
|
8
|
+
- ✅ **Reliable ACKs** even when app is not running
|
|
9
|
+
|
|
10
|
+
This extension is **required for iOS** to track push notification delivery in all app states.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Why is this needed?
|
|
15
|
+
|
|
16
|
+
### The iOS Limitation
|
|
17
|
+
|
|
18
|
+
On iOS, when your app is in background or killed state and receives a push notification with a visible alert, React Native's `setBackgroundMessageHandler` **is NOT called**. This is fundamental iOS behavior, not a bug.
|
|
19
|
+
|
|
20
|
+
**What this means:**
|
|
21
|
+
- ❌ No delivery tracking when app is killed
|
|
22
|
+
- ❌ No custom notification display logic in background
|
|
23
|
+
- ❌ No image processing without extension
|
|
24
|
+
|
|
25
|
+
### The Solution: Notification Service Extension
|
|
26
|
+
|
|
27
|
+
A Notification Service Extension is a separate iOS app extension that:
|
|
28
|
+
- ✅ Runs in a **separate process** from your main app
|
|
29
|
+
- ✅ Intercepts **all incoming notifications** before they're displayed
|
|
30
|
+
- ✅ Has **30 seconds** to process the notification
|
|
31
|
+
- ✅ Can send delivery ACKs, download images, and modify content
|
|
32
|
+
|
|
33
|
+
**Industry standard:** Firebase, OneSignal, CleverTap, Airship all use this approach.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
### Step 1: Install Dependencies
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install react-native-shared-group-preferences
|
|
43
|
+
cd ios && pod install && cd ..
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Why needed:** Share credentials between app and extension.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
### Step 2: Configure in Xcode
|
|
51
|
+
|
|
52
|
+
#### 2.1 Add Extension Target
|
|
53
|
+
|
|
54
|
+
1. Open `ios/*.xcworkspace` in Xcode
|
|
55
|
+
2. Go to **File → New → Target**
|
|
56
|
+
3. Choose **"Notification Service Extension"**
|
|
57
|
+
4. **Product Name:** `SwanNotificationServiceExtension`
|
|
58
|
+
5. **Language:** Swift
|
|
59
|
+
6. Click **Finish**
|
|
60
|
+
7. When prompted "Activate scheme?", click **Cancel**
|
|
61
|
+
|
|
62
|
+
#### 2.2 Configure App Groups
|
|
63
|
+
|
|
64
|
+
**App Groups** allow the main app and extension to share credentials.
|
|
65
|
+
|
|
66
|
+
##### Main App Target
|
|
67
|
+
|
|
68
|
+
1. Select your **main app target** (e.g., `YourApp`)
|
|
69
|
+
2. Go to **"Signing & Capabilities"** tab
|
|
70
|
+
3. Click **"+ Capability"**
|
|
71
|
+
4. Search for and add **"App Groups"**
|
|
72
|
+
5. Click **"+"** under App Groups
|
|
73
|
+
6. Enter: `group.swan.sdk.notifications`
|
|
74
|
+
7. Click **OK**
|
|
75
|
+
|
|
76
|
+
##### Extension Target
|
|
77
|
+
|
|
78
|
+
1. Select **SwanNotificationServiceExtension** target
|
|
79
|
+
2. Go to **"Signing & Capabilities"** tab
|
|
80
|
+
3. Click **"+ Capability"**
|
|
81
|
+
4. Search for and add **"App Groups"**
|
|
82
|
+
5. Click **"+"** under App Groups
|
|
83
|
+
6. Enter: `group.swan.sdk.notifications` (**MUST match main app!**)
|
|
84
|
+
7. Click **OK**
|
|
85
|
+
|
|
86
|
+
**⚠️ IMPORTANT:** Both targets must have the **exact same** App Group ID.
|
|
87
|
+
|
|
88
|
+
#### 2.3 Verify Bundle Identifier
|
|
89
|
+
|
|
90
|
+
1. Select **SwanNotificationServiceExtension** target
|
|
91
|
+
2. Go to **"General"** tab
|
|
92
|
+
3. Check **Bundle Identifier**: Should be `com.yourcompany.app.SwanNotificationServiceExtension`
|
|
93
|
+
4. Make sure it's a **child** of your main app's bundle ID
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
### Step 3: Run Setup Script
|
|
98
|
+
|
|
99
|
+
Now that the extension target is created, run the setup script to copy the Swan implementation files. This will overwrite the default files created by Xcode.
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
node node_modules/swan-react-native-sdk/scripts/setup-ios-extension.js
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**What it does:**
|
|
106
|
+
- Copies extension files to `ios/SwanNotificationServiceExtension/`
|
|
107
|
+
- Validates dependencies
|
|
108
|
+
- Ensures the correct implementation is in place
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### Step 4: Testing
|
|
113
|
+
|
|
114
|
+
### Build and Archive
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# Clean build
|
|
118
|
+
cd ios
|
|
119
|
+
rm -rf build
|
|
120
|
+
xcodebuild clean -workspace YourApp.xcworkspace -scheme YourApp
|
|
121
|
+
|
|
122
|
+
# Build
|
|
123
|
+
xcodebuild -workspace YourApp.xcworkspace -scheme YourApp -configuration Release
|
|
124
|
+
|
|
125
|
+
# Archive (for TestFlight or Ad Hoc)
|
|
126
|
+
xcodebuild -workspace YourApp.xcworkspace -scheme YourApp -configuration Release archive
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Test on Real Device
|
|
130
|
+
|
|
131
|
+
**IMPORTANT:** Push notifications don't work on iOS Simulator!
|
|
132
|
+
|
|
133
|
+
1. Archive your app (Product → Archive in Xcode)
|
|
134
|
+
2. Export to device or upload to TestFlight
|
|
135
|
+
3. Install on a real iOS device
|
|
136
|
+
4. Send a test notification
|
|
137
|
+
5. Check Xcode **Device Console** for logs
|
|
138
|
+
|
|
139
|
+
### Expected Logs
|
|
140
|
+
|
|
141
|
+
When extension receives a notification:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
[SwanSDK Extension] Notification Service Extension triggered
|
|
145
|
+
[SwanSDK Extension] Request identifier: 1234567890
|
|
146
|
+
[SwanSDK Extension] UserInfo: {...}
|
|
147
|
+
[SwanSDK Extension] Found messageId in gcm.message_id: 0:1234567890
|
|
148
|
+
[SwanSDK Extension] Sending delivery ACK for messageId: 0:1234567890
|
|
149
|
+
[SwanSDK Extension] Credentials loaded - appId: YOUR_APP_ID
|
|
150
|
+
[SwanSDK Extension] ACK payload: {...}
|
|
151
|
+
[SwanSDK Extension] ACK response status: 200
|
|
152
|
+
[SwanSDK Extension] ✅ Delivery ACK sent successfully
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
If image is present:
|
|
156
|
+
```
|
|
157
|
+
[SwanSDK Extension] Downloading notification image: https://example.com/image.png
|
|
158
|
+
[SwanSDK Extension] ✅ Image downloaded successfully
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### View Logs on Real Device
|
|
162
|
+
|
|
163
|
+
**Option 1: Xcode Device Console**
|
|
164
|
+
1. Connect device via USB
|
|
165
|
+
2. Xcode → Window → Devices and Simulators
|
|
166
|
+
3. Select your device
|
|
167
|
+
4. Click **"Open Console"**
|
|
168
|
+
5. Filter by "SwanSDK Extension"
|
|
169
|
+
|
|
170
|
+
**Option 2: Console.app (macOS)**
|
|
171
|
+
1. Open Console app on Mac
|
|
172
|
+
2. Select your connected device
|
|
173
|
+
3. Search for "SwanSDK Extension"
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Troubleshooting
|
|
178
|
+
|
|
179
|
+
### Extension logs don't appear
|
|
180
|
+
|
|
181
|
+
**Symptom:** No `[SwanSDK Extension]` logs when notification arrives
|
|
182
|
+
|
|
183
|
+
**Possible causes:**
|
|
184
|
+
|
|
185
|
+
1. **Missing mutable-content: 1**
|
|
186
|
+
- Check FCM payload includes `mutable-content: 1` in APNS
|
|
187
|
+
- Without it, iOS won't trigger the extension
|
|
188
|
+
|
|
189
|
+
2. **App Groups not configured**
|
|
190
|
+
- Verify both targets have "App Groups" capability
|
|
191
|
+
- Verify App Group ID is `group.swan.sdk.notifications` in BOTH targets
|
|
192
|
+
- IDs must match exactly (no typos!)
|
|
193
|
+
|
|
194
|
+
3. **Extension not included in build**
|
|
195
|
+
- In Xcode, go to Product → Scheme → Edit Scheme
|
|
196
|
+
- Check that SwanNotificationServiceExtension is included
|
|
197
|
+
|
|
198
|
+
4. **Testing on simulator**
|
|
199
|
+
- Push notifications don't work on iOS Simulator
|
|
200
|
+
- Test on a real device
|
|
201
|
+
|
|
202
|
+
### Extension runs but no ACK sent
|
|
203
|
+
|
|
204
|
+
**Symptom:** See extension logs but backend doesn't receive ACK
|
|
205
|
+
|
|
206
|
+
**Possible causes:**
|
|
207
|
+
|
|
208
|
+
1. **Credentials not saved to App Group**
|
|
209
|
+
- Ensure SDK is initialized: `SwanSDK.init({ appId: '...' })`
|
|
210
|
+
- Credentials are saved automatically on init
|
|
211
|
+
- Check logs for: `[SharedCredentials] ✅ Credentials saved to iOS App Group`
|
|
212
|
+
|
|
213
|
+
2. **App Group ID mismatch**
|
|
214
|
+
- Extension uses `group.swan.sdk.notifications` by default
|
|
215
|
+
- If you changed it, update `NotificationService.swift` line 143
|
|
216
|
+
|
|
217
|
+
3. **Network issue**
|
|
218
|
+
- Extension has only 30 seconds to complete
|
|
219
|
+
- Check device has internet connection
|
|
220
|
+
|
|
221
|
+
### Images not appearing
|
|
222
|
+
|
|
223
|
+
**Symptom:** Notification arrives but image doesn't display
|
|
224
|
+
|
|
225
|
+
**Possible causes:**
|
|
226
|
+
|
|
227
|
+
1. **Image URL invalid**
|
|
228
|
+
- Check image URL is accessible (try in browser)
|
|
229
|
+
- Must be HTTPS (HTTP won't work)
|
|
230
|
+
|
|
231
|
+
2. **Image format unsupported**
|
|
232
|
+
- Supported: JPEG, PNG, GIF
|
|
233
|
+
- Max size: 10MB (iOS limit)
|
|
234
|
+
|
|
235
|
+
3. **mutable-content missing**
|
|
236
|
+
- Extension won't run without `mutable-content: 1`
|
|
237
|
+
|
|
238
|
+
### Build errors
|
|
239
|
+
|
|
240
|
+
**Error:** `No such module 'UserNotifications'`
|
|
241
|
+
- Solution: Make sure deployment target is iOS 10.0+
|
|
242
|
+
|
|
243
|
+
**Error:** `Use of undeclared type 'UNNotificationServiceExtension'`
|
|
244
|
+
- Solution: Verify extension target is set to iOS 10.0+ deployment target
|
|
245
|
+
|
|
246
|
+
**Error:** `Could not find or use auto-linked library 'swiftFoundation'`
|
|
247
|
+
- Solution: Add `use_frameworks!` to Podfile
|
|
248
|
+
|
|
249
|
+
**Error:** `CocoaPods Error: Unable to find compatibility version string for object version '70'`
|
|
250
|
+
- Solution: In Xcode, select your Project (blue icon) → Build Settings (or Info) → Project Format. Change it to **Xcode 16.0-compatible** or later.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Customization
|
|
255
|
+
|
|
256
|
+
### Custom App Group ID
|
|
257
|
+
|
|
258
|
+
If you want to use a different App Group ID:
|
|
259
|
+
|
|
260
|
+
1. **In Xcode:** Update App Groups in both targets to use your custom ID (e.g., `group.com.yourcompany.app`)
|
|
261
|
+
|
|
262
|
+
2. **In SDK:** Configure before calling `SwanSDK.init()`:
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
import { SharedCredentialsManager } from 'swan-react-native-sdk';
|
|
266
|
+
|
|
267
|
+
// Set custom App Group ID BEFORE SDK init
|
|
268
|
+
SharedCredentialsManager.setAppGroupId('group.com.yourcompany.app');
|
|
269
|
+
|
|
270
|
+
// Then initialize SDK
|
|
271
|
+
await SwanSDK.init({ appId: 'YOUR_APP_ID' });
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
3. **In Extension:** Update `NotificationService.swift`:
|
|
275
|
+
|
|
276
|
+
```swift
|
|
277
|
+
let appGroupId = "group.com.yourcompany.app"
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
## FAQs
|
|
283
|
+
|
|
284
|
+
### Q: Do I need to modify the extension code?
|
|
285
|
+
|
|
286
|
+
**A:** No. The extension works out of the box. Only modify if you need custom App Group ID.
|
|
287
|
+
|
|
288
|
+
### Q: Will this increase my app size?
|
|
289
|
+
|
|
290
|
+
**A:** Minimally. The extension adds ~50KB to your IPA.
|
|
291
|
+
|
|
292
|
+
### Q: Does this affect app performance?
|
|
293
|
+
|
|
294
|
+
**A:** No. The extension runs in a separate process and only when notifications arrive.
|
|
295
|
+
|
|
296
|
+
### Q: Can I test without archiving?
|
|
297
|
+
|
|
298
|
+
**A:** Yes, but you must run on a real device. Push doesn't work on simulator.
|
|
299
|
+
|
|
300
|
+
### Q: What if I already have a Notification Service Extension?
|
|
301
|
+
|
|
302
|
+
**A:** You'll need to merge Swan's code into your existing extension. The key parts are:
|
|
303
|
+
1. Reading credentials from App Group
|
|
304
|
+
2. Sending delivery ACK
|
|
305
|
+
3. Downloading images
|
|
306
|
+
|
|
307
|
+
### Q: Do I need this for Android?
|
|
308
|
+
|
|
309
|
+
**A:** No. Android data-only push notifications work without an extension. This is iOS-only.
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## Support
|
|
314
|
+
|
|
315
|
+
If you encounter issues:
|
|
316
|
+
|
|
317
|
+
1. Check logs in Xcode Device Console
|
|
318
|
+
2. Verify all steps in this guide
|
|
319
|
+
3. Test with the provided FCM payload example
|
|
320
|
+
4. Check that App Group IDs match in both targets
|
|
321
|
+
|
|
322
|
+
For detailed debugging, enable verbose logging:
|
|
323
|
+
- Main app: `SwanSDK.setLoggingEnabled(true)`
|
|
324
|
+
- Extension: Logs are always enabled, check Device Console
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Summary
|
|
329
|
+
|
|
330
|
+
✅ **Install:** `npm install react-native-shared-group-preferences`
|
|
331
|
+
✅ **Xcode:** Add extension target + configure App Groups
|
|
332
|
+
✅ **Run:** `node node_modules/swan-react-native-sdk/scripts/setup-ios-extension.js`
|
|
333
|
+
✅ **Test:** Archive and test on real device
|
|
334
|
+
|
|
335
|
+
That's it! Your iOS notifications now have reliable delivery tracking and rich media support. 🎉
|
package/ios/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Swan SDK - iOS Notification Service Extension
|
|
2
|
+
|
|
3
|
+
This directory contains the Notification Service Extension for iOS, which enables:
|
|
4
|
+
- ✅ Delivery tracking when app is killed or backgrounded
|
|
5
|
+
- ✅ Rich media support (images in notifications)
|
|
6
|
+
- ✅ Reliable ACKs in all app states
|
|
7
|
+
|
|
8
|
+
## Quick Setup
|
|
9
|
+
|
|
10
|
+
### Step 1: Run Setup Script
|
|
11
|
+
|
|
12
|
+
From your React Native project root:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
node node_modules/swan-react-native-sdk/scripts/setup-ios-extension.js
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
This will:
|
|
19
|
+
- Copy extension files to your `ios/` directory
|
|
20
|
+
- Validate dependencies
|
|
21
|
+
- Show setup instructions
|
|
22
|
+
|
|
23
|
+
### Step 2: Configure in Xcode
|
|
24
|
+
|
|
25
|
+
Follow the instructions shown by the setup script to:
|
|
26
|
+
1. Add extension target to Xcode
|
|
27
|
+
2. Configure App Groups
|
|
28
|
+
3. Replace auto-generated files
|
|
29
|
+
|
|
30
|
+
### Step 3: Update FCM Payload
|
|
31
|
+
|
|
32
|
+
Ensure your backend includes `mutable-content: 1` in APNS:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{
|
|
36
|
+
"apns": {
|
|
37
|
+
"payload": {
|
|
38
|
+
"aps": {
|
|
39
|
+
"alert": { "title": "...", "body": "..." },
|
|
40
|
+
"mutable-content": 1
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Full Documentation
|
|
48
|
+
|
|
49
|
+
See complete setup guide: [docs/IOS_NOTIFICATION_EXTENSION_SETUP.md](../docs/IOS_NOTIFICATION_EXTENSION_SETUP.md)
|
|
50
|
+
|
|
51
|
+
## Files
|
|
52
|
+
|
|
53
|
+
- **SwanNotificationServiceExtension/** - Extension source code
|
|
54
|
+
- `NotificationService.swift` - Main extension logic
|
|
55
|
+
- `Info.plist` - Extension configuration
|
|
56
|
+
- `SwanNotificationServiceExtension.entitlements` - App Group permissions
|
|
57
|
+
|
|
58
|
+
## Support
|
|
59
|
+
|
|
60
|
+
For issues or questions:
|
|
61
|
+
1. Check the full documentation
|
|
62
|
+
2. Verify App Groups are configured correctly
|
|
63
|
+
3. Test on a real device (not simulator)
|
|
64
|
+
4. Check Xcode Device Console for logs
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>CFBundleDevelopmentRegion</key>
|
|
6
|
+
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
|
7
|
+
<key>CFBundleDisplayName</key>
|
|
8
|
+
<string>SwanNotificationServiceExtension</string>
|
|
9
|
+
<key>CFBundleExecutable</key>
|
|
10
|
+
<string>$(EXECUTABLE_NAME)</string>
|
|
11
|
+
<key>CFBundleIdentifier</key>
|
|
12
|
+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
13
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
|
14
|
+
<string>6.0</string>
|
|
15
|
+
<key>CFBundleName</key>
|
|
16
|
+
<string>$(PRODUCT_NAME)</string>
|
|
17
|
+
<key>CFBundlePackageType</key>
|
|
18
|
+
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
|
19
|
+
<key>CFBundleShortVersionString</key>
|
|
20
|
+
<string>1.0</string>
|
|
21
|
+
<key>CFBundleVersion</key>
|
|
22
|
+
<string>1</string>
|
|
23
|
+
<key>NSExtension</key>
|
|
24
|
+
<dict>
|
|
25
|
+
<key>NSExtensionPointIdentifier</key>
|
|
26
|
+
<string>com.apple.usernotifications.service</string>
|
|
27
|
+
<key>NSExtensionPrincipalClass</key>
|
|
28
|
+
<string>$(PRODUCT_MODULE_NAME).NotificationService</string>
|
|
29
|
+
</dict>
|
|
30
|
+
</dict>
|
|
31
|
+
</plist>
|