react-native-mapp-plugin 1.4.2 → 2.0.0
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/BREAKING_CHANGES.md +126 -0
- package/CHANGELOG.md +25 -0
- package/MIGRATION_2.0.md +100 -0
- package/Mapp.js +7 -8
- package/README.md +148 -75
- package/RNMappPlugin.podspec +10 -4
- package/android/build.gradle +137 -7
- package/android/gradle.properties +0 -2
- package/android/settings.gradle +5 -6
- package/android/src/main/AndroidManifest.xml +8 -1
- package/android/src/main/java/com/reactlibrary/MappEngagementDispatcher.java +102 -0
- package/android/src/main/java/com/reactlibrary/MappPushHelper.java +126 -0
- package/android/src/main/java/com/reactlibrary/MessageService.java +3 -23
- package/android/src/main/java/com/reactlibrary/RNMappPluginModule.java +94 -28
- package/app.plugin.js +4 -0
- package/ios/RNMappEventEmmiter.m +21 -2
- package/ios/RNMappPluginModule.h +20 -1
- package/ios/{RNMappPluginModule.m → RNMappPluginModule.mm} +135 -39
- package/package.json +31 -8
- package/plugin/build/android.d.ts +4 -0
- package/plugin/build/android.js +101 -0
- package/plugin/build/index.d.ts +8 -0
- package/plugin/build/index.js +26 -0
- package/plugin/build/ios.d.ts +7 -0
- package/plugin/build/ios.js +238 -0
- package/plugin/build/types.d.ts +32 -0
- package/plugin/build/types.js +2 -0
- package/plugin/build/validation.d.ts +3 -0
- package/plugin/build/validation.js +76 -0
- package/specs/NativeRNMappPluginModule.js +3 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Breaking changes in 2.0.0
|
|
2
|
+
|
|
3
|
+
Version 2.0.0 is largely source-compatible with 1.4.2, but it is not fully backward-compatible at the platform and behavioral levels. Not every client will need application code changes.
|
|
4
|
+
|
|
5
|
+
No documented JavaScript method was removed or renamed, and existing method parameters remain unchanged. The major version is required because some existing builds, native integrations, and runtime assumptions can break—most notably the increased minimum iOS version.
|
|
6
|
+
|
|
7
|
+
## Changes that may affect 1.4.2 clients
|
|
8
|
+
|
|
9
|
+
### Minimum iOS deployment target
|
|
10
|
+
|
|
11
|
+
The minimum supported iOS deployment target is now 15.1 instead of 10.0.
|
|
12
|
+
|
|
13
|
+
Applications targeting an older iOS version cannot install or build the pod until their deployment target is raised to iOS 15.1 or newer. This platform-support removal is a breaking change even when the application does not need JavaScript changes.
|
|
14
|
+
|
|
15
|
+
### Android dependency resolution
|
|
16
|
+
|
|
17
|
+
The plugin exports strict compatibility constraints for the supported Mapp Engage 7.1.2 and Expo SDK 57 runtime:
|
|
18
|
+
|
|
19
|
+
- Kotlin 2.1.20
|
|
20
|
+
- Coroutines 1.11.0
|
|
21
|
+
- AndroidX Core 1.18.0
|
|
22
|
+
- WorkManager 2.10.5
|
|
23
|
+
- Lifecycle 2.10.0
|
|
24
|
+
- Play Services Location 21.3.0
|
|
25
|
+
|
|
26
|
+
Gradle may fail dependency resolution when an application explicitly requires incompatible versions. Applications already resolving compatible versions do not need a change.
|
|
27
|
+
|
|
28
|
+
### Custom Android Firebase handling
|
|
29
|
+
|
|
30
|
+
The plugin removes the Mapp SDK Firebase service and uses `com.reactlibrary.MessageService` as the default Mapp push owner.
|
|
31
|
+
|
|
32
|
+
Applications that use the default plugin service do not need to migrate their Firebase callbacks. Applications that own a custom `FirebaseMessagingService` must select custom push ownership and forward callbacks through the native helper:
|
|
33
|
+
|
|
34
|
+
```java
|
|
35
|
+
@Override
|
|
36
|
+
public void onMessageReceived(RemoteMessage message) {
|
|
37
|
+
if (!MappPushHelper.handleMessage(getApplication(), message)) {
|
|
38
|
+
// Handle non-Mapp messages.
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@Override
|
|
43
|
+
public void onNewToken(String token) {
|
|
44
|
+
MappPushHelper.handleNewToken(getApplication(), token);
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
For Expo, set `android.pushHandling` to `"custom"`. Successful manifest merging alone does not forward messages to Mapp.
|
|
49
|
+
|
|
50
|
+
### Geofence permission behavior
|
|
51
|
+
|
|
52
|
+
In 1.4.2, `Mapp.requestGeofenceLocationPermission()` only checked the current Android permission state. In 2.0.0, it requests foreground location and then background location when required, which can display system dialogs.
|
|
53
|
+
|
|
54
|
+
Call this method from an appropriate user interaction and only after explaining why the application needs location access.
|
|
55
|
+
|
|
56
|
+
### Firebase token failure handling
|
|
57
|
+
|
|
58
|
+
On Android, `Mapp.getToken()` now rejects with `FCM_REGISTRATION_FAILED` when Firebase token registration fails. In 1.4.2, reading the failed Firebase task result could crash.
|
|
59
|
+
|
|
60
|
+
Consumers awaiting the token should handle rejection:
|
|
61
|
+
|
|
62
|
+
```js
|
|
63
|
+
try {
|
|
64
|
+
const token = await Mapp.getToken();
|
|
65
|
+
} catch (error) {
|
|
66
|
+
// Handle unavailable FCM registration.
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
On iOS, `Mapp.getToken()` rejects with `APNS_TOKEN_UNAVAILABLE` because Mapp auto-integration owns the native APNs token.
|
|
71
|
+
|
|
72
|
+
### Inbox status methods now update Mapp
|
|
73
|
+
|
|
74
|
+
The following Android methods were no-ops in 1.4.2:
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
Mapp.inAppMarkAsRead(templateId, eventId);
|
|
78
|
+
Mapp.inAppMarkAsUnRead(templateId, eventId);
|
|
79
|
+
Mapp.inAppMarkAsDeleted(templateId, eventId);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
In 2.0.0, they call Mapp Engage 7.1.2 to fetch the inbox message and update its real server-side status to `READ`, `UNREAD`, or `DELETED`. This is the intended behavior, but it introduces an observable network and backend side effect.
|
|
83
|
+
|
|
84
|
+
The legacy `eventId` argument remains accepted for source compatibility. Mapp Engage 7.1.2 identifies the message using `templateId`.
|
|
85
|
+
|
|
86
|
+
### Undocumented iOS native methods
|
|
87
|
+
|
|
88
|
+
Applications directly calling these undocumented bridge methods will break because they are no longer exported separately:
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
NativeModules.RNMappPluginModule.autoengage(...);
|
|
92
|
+
NativeModules.RNMappPluginModule.engageInapp(...);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Use the documented public method instead:
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
Mapp.engage(sdkKey, googleProjectId, server, appId, tenantId);
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
On iOS, `Mapp.engage(...)` still initializes push and in-app functionality. `AppoxeeConfig.plist` is the credential source of truth.
|
|
102
|
+
|
|
103
|
+
## Changes that are not immediate breaks
|
|
104
|
+
|
|
105
|
+
- `Mapp.engage2()` remains available but is deprecated in favor of `Mapp.engage(...)`.
|
|
106
|
+
- `Mapp.startGeoFencing()` remains available but is deprecated in favor of `Mapp.startGeofencing()`.
|
|
107
|
+
- `Mapp.stopGeoFencing()` remains available but is deprecated in favor of `Mapp.stopGeofencing()`.
|
|
108
|
+
- `Mapp.setRemoteMessage()`, `Mapp.isPushFromMapp()`, and `Mapp.setToken()` remain supported while JavaScript is guaranteed to be running. Use `MappPushHelper` instead for native background or terminated Firebase callbacks.
|
|
109
|
+
- Android minimum SDK remains 24.
|
|
110
|
+
- React Native peer requirement remains `>=0.84`.
|
|
111
|
+
- Node.js requirement remains `>=20.19.4`.
|
|
112
|
+
|
|
113
|
+
## Who can upgrade without source changes?
|
|
114
|
+
|
|
115
|
+
An application may not need source changes when all of the following are true:
|
|
116
|
+
|
|
117
|
+
- Its iOS deployment target is already 15.1 or newer.
|
|
118
|
+
- Its Android dependencies do not conflict with the exported constraints.
|
|
119
|
+
- It uses the plugin's default Android Mapp push service instead of a custom `FirebaseMessagingService`.
|
|
120
|
+
- It already handles promise rejection from `Mapp.getToken()`.
|
|
121
|
+
- It expects inbox status methods to update the real Mapp message status.
|
|
122
|
+
- It does not call undocumented native bridge methods directly.
|
|
123
|
+
|
|
124
|
+
Even in that case, test push delivery, permission prompts, and inbox status changes on physical devices before releasing the upgrade.
|
|
125
|
+
|
|
126
|
+
For concrete upgrade steps and replacement examples, continue with the [1.4.2 to 2.0.0 migration guide](MIGRATION_2.0.md).
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,28 @@
|
|
|
1
|
+
## Version 2.0.0 (unreleased)
|
|
2
|
+
|
|
3
|
+
***Breaking Changes***
|
|
4
|
+
|
|
5
|
+
- Raised the minimum iOS deployment target from 10.0 to 15.1.
|
|
6
|
+
- Exported strict Android compatibility constraints for the supported Expo SDK 57 toolchain and Mapp Engage 7.1.2 runtime ABI.
|
|
7
|
+
- Changed Android geofence permission handling, FCM service ownership, and inbox status updates.
|
|
8
|
+
- Deprecated `engage2()`, `startGeoFencing()`, and `stopGeoFencing()` in favor of their supported replacements.
|
|
9
|
+
- Review the [breaking changes](BREAKING_CHANGES.md), then follow the [1.4.2 to 2.0.0 migration guide](MIGRATION_2.0.md) for required application changes.
|
|
10
|
+
|
|
11
|
+
***Bug Fixes***
|
|
12
|
+
|
|
13
|
+
- Android: Failed Firebase token registration now rejects with `FCM_REGISTRATION_FAILED` instead of crashing while reading a failed task result.
|
|
14
|
+
- Android: All Mapp engage calls run on the main looper. Background Firebase callbacks wait for a bounded engage attempt and safely return failure after SDK errors, timeout, or interruption.
|
|
15
|
+
- Android/Expo: Mapp and custom push ownership now remove the SDK v7 Firebase service and remain idempotent when prebuild runs repeatedly or changes mode.
|
|
16
|
+
- Android/Expo: The config plugin now writes required permissions, the Mapp messaging service, and the push receiver through `withAndroidManifest`; Firebase configuration remains customer-owned through `expo.android.googleServicesFile`.
|
|
17
|
+
- Android: Exported Expo SDK 57 compatibility constraints stabilize WorkManager, Lifecycle, AndroidX Core, Play Services Location, and Kotlin stdlib for API 36/AGP 8.12/Kotlin 2.1.20 builds.
|
|
18
|
+
- Android: Coroutines remain aligned at 1.11.0 to preserve the Mapp 7.1.2 native in-app dismissal ABI.
|
|
19
|
+
- iOS/Expo: The config plugin now creates and embeds a standalone Notification Service Extension for Mapp rich-push media from `ios_apx_media`, with EAS app-extension metadata and no App Group or extra Pod.
|
|
20
|
+
- iOS/Expo: Verified that Expo SDK 57 CocoaPods autolinking discovers `RNMappPlugin.podspec` and processes `RNMappPlugin` under the New Architecture.
|
|
21
|
+
|
|
22
|
+
***Compatibility***
|
|
23
|
+
|
|
24
|
+
- Verified baseline: Expo SDK 57, React Native 0.86, New Architecture, Android API 36, AGP 8.12, Kotlin 2.1.20, and JDK 21.
|
|
25
|
+
|
|
1
26
|
## Version 1.4.2
|
|
2
27
|
|
|
3
28
|
***Dependency Updates***
|
package/MIGRATION_2.0.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Migrating from 1.4.2 to 2.0.0
|
|
2
|
+
|
|
3
|
+
This guide covers upgrading from the latest published 1.4.x release, 1.4.2. The public JavaScript method names and signatures remain available, but 2.0.0 changes platform requirements, Android dependency resolution, push ownership, and the behavior of several existing methods.
|
|
4
|
+
|
|
5
|
+
Read [Breaking changes in 2.0.0](BREAKING_CHANGES.md) first to determine which changes affect your application.
|
|
6
|
+
|
|
7
|
+
## Migration checklist
|
|
8
|
+
|
|
9
|
+
1. Raise the application deployment target to iOS 15.1 or newer.
|
|
10
|
+
2. Use JDK 21 for the supported Android build baseline and remove dependency pins that conflict with the versions below.
|
|
11
|
+
3. If using Expo, configure the plugin and replace Expo Go with a development build.
|
|
12
|
+
4. Review calls to geofence permission and token APIs for their new prompt and rejection behavior.
|
|
13
|
+
5. If the application owns a `FirebaseMessagingService`, forward messages and tokens through `MappPushHelper`.
|
|
14
|
+
6. Replace deprecated methods using the migration table below.
|
|
15
|
+
7. Verify Android inbox read, unread, and deleted operations against a real Mapp message.
|
|
16
|
+
|
|
17
|
+
## Platform and build requirements
|
|
18
|
+
|
|
19
|
+
- The minimum iOS deployment target is now 15.1 instead of 10.0. Applications targeting an older iOS version must raise their deployment target before installing 2.0.0.
|
|
20
|
+
- Android still requires a minimum SDK of 24, but the plugin exports strict compatibility constraints for Kotlin 2.1.20, coroutines 1.11.0, AndroidX Core 1.18.0, WorkManager 2.10.5, Lifecycle 2.10.0, and Play Services Location 21.3.0. Remove conflicting application-level pins or align them with these versions.
|
|
21
|
+
- JDK 21 is the supported Android build JDK for the tested Expo SDK 57, AGP 8.12, and API 36 baseline.
|
|
22
|
+
- Expo Go is not supported. Expo applications must use CNG with `expo-dev-client` and create a new native build after changing plugin options.
|
|
23
|
+
|
|
24
|
+
## Existing methods with changed behavior
|
|
25
|
+
|
|
26
|
+
| Method | 1.4.2 behavior | 2.0.0 behavior and migration impact |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| `Mapp.requestGeofenceLocationPermission()` | Android only checked whether permissions had already been granted. | Android now displays the foreground-location request and then the background-location request when needed. Call it from an appropriate user action and expect system dialogs. iOS now has a New Architecture implementation as well. |
|
|
29
|
+
| `Mapp.getToken()` | A failed Android Firebase task could crash while its result was read. The iOS implementation was missing. | Android rejects with `FCM_REGISTRATION_FAILED`; consumers must handle promise rejection. iOS rejects with `APNS_TOKEN_UNAVAILABLE` because Mapp auto-integration owns the APNs token. |
|
|
30
|
+
| `Mapp.setToken(token)` | The iOS bridge did not settle the declared promise. | iOS resolves `true` for a base64-encoded native APNs token and rejects with `INVALID_APNS_TOKEN` for invalid input. An Expo push token is not a native APNs token. |
|
|
31
|
+
| `Mapp.inAppMarkAsRead(templateId, eventId)` | Android no-op. | Android fetches the Mapp Engage 7.1.2 inbox message and updates it to `READ`. |
|
|
32
|
+
| `Mapp.inAppMarkAsUnRead(templateId, eventId)` | Android no-op. | Android fetches the inbox message and updates it to `UNREAD`. |
|
|
33
|
+
| `Mapp.inAppMarkAsDeleted(templateId, eventId)` | Android no-op. | Android fetches the inbox message and updates it to `DELETED`. |
|
|
34
|
+
| `Mapp.engage(...)` | iOS JavaScript called the private native `autoengage` and `engageInapp` methods separately. | All platforms use the public native `engage` entry point. On iOS it still initializes both push and in-app, using `AppoxeeConfig.plist` as the credential source of truth. |
|
|
35
|
+
| iOS event listeners | Events emitted before a JavaScript listener was attached were dropped. | Up to 50 cold-start events are buffered and delivered after a listener attaches. Consumers should tolerate receiving an initial queued event. |
|
|
36
|
+
|
|
37
|
+
For the Android inbox methods, `eventId` remains accepted for source compatibility but Mapp Engage 7.1.2 identifies and fetches the message using `templateId`.
|
|
38
|
+
|
|
39
|
+
## Deprecated methods and replacements
|
|
40
|
+
|
|
41
|
+
| Deprecated method | Replacement |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| `Mapp.engage2()` | `Mapp.engage(sdkKey, googleProjectId, server, appId, tenantId)` |
|
|
44
|
+
| `Mapp.startGeoFencing()` | `await Mapp.startGeofencing()` |
|
|
45
|
+
| `Mapp.stopGeoFencing()` | `await Mapp.stopGeofencing()` |
|
|
46
|
+
| Direct `NativeModules.RNMappPluginModule.autoengage(...)` or `engageInapp(...)` calls | `Mapp.engage(...)` |
|
|
47
|
+
|
|
48
|
+
The direct `autoengage` and `engageInapp` bridge methods were never part of the documented JavaScript API and are no longer exported separately.
|
|
49
|
+
|
|
50
|
+
## New Android native push API
|
|
51
|
+
|
|
52
|
+
Applications that own a custom `FirebaseMessagingService` can now use `com.reactlibrary.MappPushHelper`. These methods run without a React Native JavaScript runtime and replace JavaScript forwarding from background or terminated callbacks:
|
|
53
|
+
|
|
54
|
+
| New method | Purpose | Replaces in a native Firebase service |
|
|
55
|
+
| --- | --- | --- |
|
|
56
|
+
| `MappPushHelper.initialize(application)` | Safely engages Mapp on the main looper and waits for the bounded initialization attempt. | Direct background calls to `Appoxee.engage(...)`. |
|
|
57
|
+
| `MappPushHelper.isMappMessage(remoteMessage)` | Returns whether a native `RemoteMessage` belongs to Mapp. | Converting the message to JSON and calling `Mapp.isPushFromMapp(...)`. |
|
|
58
|
+
| `MappPushHelper.handleMessage(application, remoteMessage)` | Initializes Mapp when needed and forwards a Mapp message. It returns `true` only when the message was handled by Mapp. | `Mapp.setRemoteMessage(...)` for background and terminated delivery. |
|
|
59
|
+
| `MappPushHelper.handleNewToken(application, token)` | Initializes Mapp when needed and forwards a new FCM token. | Calling `Mapp.setToken(...)` from a Firebase token callback. |
|
|
60
|
+
| `MappPushHelper.waitUntilReady()` | Waits for the already-engaged SDK to become ready for a bounded period. | Application-owned polling of `Mapp.isReady()`. |
|
|
61
|
+
|
|
62
|
+
`Mapp.setRemoteMessage(...)`, `Mapp.isPushFromMapp(...)`, and `Mapp.setToken(...)` remain supported when JavaScript is guaranteed to be running. They are not reliable replacements for native Firebase callbacks while the application is backgrounded or terminated.
|
|
63
|
+
|
|
64
|
+
## Expo configuration
|
|
65
|
+
|
|
66
|
+
Add the package to the Expo `plugins` array and supply the required iOS Mapp values. The default Android `pushHandling` mode is `"mapp"` and requires `expo.android.googleServicesFile`.
|
|
67
|
+
|
|
68
|
+
Use `pushHandling: "custom"` when the application or another library owns Firebase callbacks. The config plugin then removes both the plugin and Mapp SDK messaging services so the application service is the sole owner.
|
|
69
|
+
|
|
70
|
+
See the [Expo configuration example](README.md#expo-cng) for all options.
|
|
71
|
+
|
|
72
|
+
## Native Android push migration example
|
|
73
|
+
|
|
74
|
+
```java
|
|
75
|
+
import com.google.firebase.messaging.FirebaseMessagingService;
|
|
76
|
+
import com.google.firebase.messaging.RemoteMessage;
|
|
77
|
+
import com.reactlibrary.MappPushHelper;
|
|
78
|
+
|
|
79
|
+
public final class ApplicationMessagingService extends FirebaseMessagingService {
|
|
80
|
+
@Override
|
|
81
|
+
public void onMessageReceived(RemoteMessage message) {
|
|
82
|
+
if (!MappPushHelper.handleMessage(getApplication(), message)) {
|
|
83
|
+
// Handle non-Mapp messages.
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@Override
|
|
88
|
+
public void onNewToken(String token) {
|
|
89
|
+
MappPushHelper.handleNewToken(getApplication(), token);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
For Expo, rebuild the native projects after changing the plugin configuration:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
npx expo prebuild --clean
|
|
98
|
+
npx expo run:android
|
|
99
|
+
npx expo run:ios
|
|
100
|
+
```
|
package/Mapp.js
CHANGED
|
@@ -108,11 +108,8 @@ export class Mapp {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
/**
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* @return {Promise.<string>} A promise with the result.
|
|
111
|
+
* @deprecated Use engage(sdkKey, googleProjectId, server, appID, tenantID).
|
|
114
112
|
*/
|
|
115
|
-
|
|
116
113
|
static engage2() {
|
|
117
114
|
if (Platform.OS == "android") {
|
|
118
115
|
return RNMappPluginModule.engage2();
|
|
@@ -131,10 +128,6 @@ export class Mapp {
|
|
|
131
128
|
appID: string,
|
|
132
129
|
tenantID: string
|
|
133
130
|
) {
|
|
134
|
-
if (Platform.OS == "ios") {
|
|
135
|
-
RNMappPluginModule.autoengage(server);
|
|
136
|
-
return RNMappPluginModule.engageInapp(server);
|
|
137
|
-
}
|
|
138
131
|
return RNMappPluginModule.engage(
|
|
139
132
|
sdkKey,
|
|
140
133
|
googleProjectId,
|
|
@@ -335,10 +328,16 @@ export class Mapp {
|
|
|
335
328
|
return RNMappPluginModule.stopGeofencing();
|
|
336
329
|
}
|
|
337
330
|
|
|
331
|
+
/**
|
|
332
|
+
* @deprecated Use startGeofencing(), which returns the native operation result.
|
|
333
|
+
*/
|
|
338
334
|
static startGeoFencing() {
|
|
339
335
|
return RNMappPluginModule.startGeoFencing();
|
|
340
336
|
}
|
|
341
337
|
|
|
338
|
+
/**
|
|
339
|
+
* @deprecated Use stopGeofencing(), which returns the native operation result.
|
|
340
|
+
*/
|
|
342
341
|
static stopGeoFencing() {
|
|
343
342
|
return RNMappPluginModule.stopGeoFencing();
|
|
344
343
|
}
|
package/README.md
CHANGED
|
@@ -1,93 +1,166 @@
|
|
|
1
|
-
|
|
2
1
|
# react-native-mapp-plugin
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
Mapp Engage native SDK integration for React Native CLI and Expo development builds.
|
|
4
|
+
|
|
5
|
+
## Upgrading from 1.4.x
|
|
6
|
+
|
|
7
|
+
Version 2.0 raises the minimum iOS target to 15.1 and changes Android dependency constraints, permission handling, push ownership, and inbox status updates.
|
|
8
|
+
|
|
9
|
+
Review the [breaking changes](BREAKING_CHANGES.md) and follow the [1.4.2 to 2.0.0 migration guide](MIGRATION_2.0.md) before upgrading.
|
|
10
|
+
|
|
11
|
+
## Expo (CNG)
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
Expo Go is not supported because it cannot load this package's custom native code. Use Continuous Native Generation (CNG) with `expo-dev-client`; generated `android/` and `ios/` directories do not need manual changes.
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
```bash
|
|
16
|
+
npx expo install react-native-mapp-plugin expo-dev-client
|
|
17
|
+
```
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
Configure the installed package by name in `app.json` (values shown are examples):
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"expo": {
|
|
24
|
+
"name": "Mapp app",
|
|
25
|
+
"slug": "mapp-app",
|
|
26
|
+
"newArchEnabled": true,
|
|
27
|
+
"ios": {
|
|
28
|
+
"bundleIdentifier": "com.example.mappapp"
|
|
29
|
+
},
|
|
30
|
+
"android": {
|
|
31
|
+
"package": "com.example.mappapp",
|
|
32
|
+
"googleServicesFile": "./google-services.json"
|
|
33
|
+
},
|
|
34
|
+
"plugins": [
|
|
35
|
+
[
|
|
36
|
+
"react-native-mapp-plugin",
|
|
37
|
+
{
|
|
38
|
+
"android": {
|
|
39
|
+
"enableGeofencing": false,
|
|
40
|
+
"pushHandling": "mapp"
|
|
41
|
+
},
|
|
42
|
+
"ios": {
|
|
43
|
+
"appId": "MAPP_APP_ID",
|
|
44
|
+
"dmcSystemId": 123,
|
|
45
|
+
"sdkKey": "MAPP_SDK_KEY",
|
|
46
|
+
"isEu": true,
|
|
47
|
+
"inAppServerUrl": "MAPP_INAPP_SERVER_URL",
|
|
48
|
+
"openLandingPageInsideApp": false,
|
|
49
|
+
"customFields": ["customString", "customNumber", "customDate"],
|
|
50
|
+
"mediaTimeout": 5,
|
|
51
|
+
"enableGeofencing": false
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
14
59
|
|
|
15
|
-
|
|
16
|
-
`$ react-native link react-native-mapp-plugin`
|
|
60
|
+
The Android package must match the Firebase Android application in `google-services.json`. For iOS, configure an APNs-enabled App ID, matching bundle identifier, and Apple/EAS signing credentials. Values embedded in app config and native resources are public application configuration; do not put service-account keys or signing secrets there.
|
|
17
61
|
|
|
18
|
-
|
|
62
|
+
The Firebase file is customer-owned configuration. Point Expo's built-in `expo.android.googleServicesFile` field at it; this plugin does not copy, generate, or modify `google-services.json`.
|
|
19
63
|
|
|
64
|
+
Generate and run development builds:
|
|
20
65
|
|
|
21
|
-
|
|
66
|
+
```bash
|
|
67
|
+
npx expo prebuild --clean
|
|
68
|
+
npx expo run:android
|
|
69
|
+
npx expo run:ios
|
|
22
70
|
|
|
23
|
-
|
|
71
|
+
# Cloud builds, after configuring EAS
|
|
72
|
+
eas build --profile development --platform all
|
|
73
|
+
eas build --profile preview --platform all
|
|
74
|
+
eas build --profile production --platform all
|
|
24
75
|
```
|
|
25
|
-
|
|
76
|
+
|
|
77
|
+
Changing plugin options or native dependencies requires a new binary. JavaScript-only changes may use EAS Update.
|
|
78
|
+
|
|
79
|
+
### Initialization
|
|
80
|
+
|
|
81
|
+
Register event listeners at application startup, then initialize Mapp. On iOS the generated `AppoxeeConfig.plist` is the credential source of truth; the existing `engage` arguments remain relevant to Android.
|
|
82
|
+
|
|
83
|
+
```js
|
|
84
|
+
import { Mapp, MappEventEmitter } from 'react-native-mapp-plugin';
|
|
85
|
+
|
|
86
|
+
const events = new MappEventEmitter();
|
|
87
|
+
const subscription = events.addListener('com.mapp.deep_link_received', event => {
|
|
88
|
+
// Route the deep link.
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
Mapp.engage('ANDROID_SDK_KEY', 'FCM_PROJECT_ID', 'EMC', 'APP_ID', 'TENANT_ID');
|
|
26
92
|
```
|
|
27
93
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
- Background Modes > Location updates
|
|
94
|
+
### Android push ownership
|
|
95
|
+
|
|
96
|
+
`pushHandling: "mapp"` is the default. It requires `expo.android.googleServicesFile` and retains `com.reactlibrary.MessageService` as the sole normal-priority Mapp FCM callback owner. The config plugin removes the Mapp SDK v7 service (`com.appoxee.shared.MappMessagingService`) from the merged app manifest.
|
|
32
97
|
|
|
33
|
-
|
|
98
|
+
Use `pushHandling: "custom"` when another integration, such as a client-owned `FirebaseMessagingService`, owns callbacks. The plugin removes both its `MessageService` and the Mapp SDK service so the consumer service owns callbacks. Repeated prebuilds and switching modes clean up stale generated markers. From native Android code, use `com.reactlibrary.MappPushHelper`:
|
|
99
|
+
|
|
100
|
+
```java
|
|
101
|
+
@Override public void onMessageReceived(RemoteMessage message) {
|
|
102
|
+
if (!MappPushHelper.handleMessage(getApplication(), message)) {
|
|
103
|
+
// Handle non-Mapp messages here.
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@Override public void onNewToken(String token) {
|
|
108
|
+
MappPushHelper.handleNewToken(getApplication(), token);
|
|
109
|
+
}
|
|
34
110
|
```
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
111
|
+
|
|
112
|
+
`Mapp.setRemoteMessage(...)` remains available when JavaScript is guaranteed to be alive. The native helper is required for reliable background and terminated delivery. `expo-notifications` coexistence must use custom ownership and explicit native forwarding; successful manifest merging alone does not forward payloads.
|
|
113
|
+
|
|
114
|
+
### Geofencing
|
|
115
|
+
|
|
116
|
+
Set `enableGeofencing` on each platform that needs it. Android then adds fine/background location permissions and `Mapp.requestGeofenceLocationPermission()` requests foreground permission before background permission. On iOS, also supply non-empty `locationWhenInUsePermission` and `locationAlwaysPermission` messages. Only request location access when your user-facing feature and store policy justify it.
|
|
117
|
+
|
|
118
|
+
### iOS rich push
|
|
119
|
+
|
|
120
|
+
The Expo config plugin creates a `MappNotificationService` Notification Service Extension with the bundle identifier `<expo.ios.bundleIdentifier>.mappnotificationservice`. The extension reads the public Mapp `ios_apx_media` payload key, downloads the media, and attaches it to the notification. It follows the app minimum deployment target and is set to iOS 15+, uses an App Group shared with the main app, and does not require an additional CocoaPod or React Native code.
|
|
121
|
+
|
|
122
|
+
The extension is also declared in Expo's experimental EAS app-extension metadata so EAS can prepare its signing credentials. Regenerate the iOS project after changing the application bundle identifier.
|
|
123
|
+
|
|
124
|
+
### Tested compatibility
|
|
125
|
+
|
|
126
|
+
| Component | Tested baseline |
|
|
127
|
+
| --- | --- |
|
|
128
|
+
| Expo SDK | 57 |
|
|
129
|
+
| React Native | 0.86 (Expo SDK 57) |
|
|
130
|
+
| New Architecture | Enabled |
|
|
131
|
+
| Android min / compile / target SDK | 24 / 36 / 36 |
|
|
132
|
+
| Android Gradle Plugin / Kotlin / JDK | 8.12 / 2.1.20 / 21 |
|
|
133
|
+
| iOS deployment target | 16.4 (library minimum: 15.1) |
|
|
134
|
+
| Mapp Android SDK | 7.1.2 |
|
|
135
|
+
| Mapp iOS SDKs | Vendored xcframeworks in this package |
|
|
136
|
+
|
|
137
|
+
Mapp Engage Android 7.1.2 currently publishes Android dependencies newer than the Expo SDK 57 toolchain can consume. This release exports bounded compatibility constraints for AndroidX Core 1.18.0, WorkManager 2.10.5, Lifecycle 2.10.0, Play Services Location 21.3.0, and Kotlin stdlib 2.1.20. These pins can be removed after the Mapp Android publication adopts the Expo-compatible versions.
|
|
138
|
+
|
|
139
|
+
Coroutines are intentionally different: Mapp's native in-app UI was compiled against kotlinx-coroutines 1.11.0 and calls an ABI absent from 1.10.x. The plugin therefore exports the coroutines 1.11.0 BOM and strict constraints. Do not downgrade coroutines to 1.10.x; dismissing or replacing a native in-app message can otherwise crash with `Job.cancel$default` `NoSuchMethodError`.
|
|
140
|
+
|
|
141
|
+
Use JDK 21 for Android builds on this baseline. The config plugin does not alter a consumer's Gradle daemon JVM configuration.
|
|
142
|
+
|
|
143
|
+
The separately maintained [sample application](https://github.com/MappCloud/React-Native-Test-Application/) is the physical-device integration consumer. Record its tested revision here when its Expo CNG migration is released.
|
|
144
|
+
|
|
145
|
+
## React Native CLI
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
npm install react-native-mapp-plugin
|
|
149
|
+
cd ios && pod install
|
|
69
150
|
```
|
|
70
151
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
compile project(':react-native-mapp-plugin')
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
## Usage
|
|
87
|
-
```javascript
|
|
88
|
-
import Mapp from 'react-native-mapp-plugin';
|
|
89
|
-
|
|
90
|
-
// TODO: What to do with the module?
|
|
91
|
-
Mapp;
|
|
152
|
+
Modern React Native autolinking discovers the Android package and CocoaPod automatically. Do not run `react-native link`, edit `settings.gradle`, or add `compile project(...)`.
|
|
153
|
+
|
|
154
|
+
No `MainActivity` or `MainApplication` edit is required. The native module is registered by autolinking. In Expo projects, the config plugin applies Android permissions, the Mapp messaging service, and the push receiver during prebuild without modifying consumer Gradle files. React Native CLI projects receive the same declarations through the library manifest merge. On iOS, CocoaPods discovers `RNMappPlugin.podspec` automatically; do not add the pod manually.
|
|
155
|
+
|
|
156
|
+
For a manually maintained iOS native project, add Push Notifications, Remote Notifications background mode, and (only if needed) Location Updates, then include an `AppoxeeConfig.plist` in the application target. Expo clients should use the config plugin above instead.
|
|
157
|
+
|
|
158
|
+
Basic usage:
|
|
159
|
+
|
|
160
|
+
```js
|
|
161
|
+
import { Mapp } from 'react-native-mapp-plugin';
|
|
162
|
+
|
|
163
|
+
Mapp.engage('SDK_KEY', 'FCM_PROJECT_ID', 'EMC', 'APP_ID', 'TENANT_ID');
|
|
92
164
|
```
|
|
93
|
-
|
|
165
|
+
|
|
166
|
+
See the [Mapp integration documentation](https://mapp-wiki.atlassian.net/wiki/spaces/MIC/pages/1154875400/React+Native+Integration+for+Mapp+Cloud) for the full JavaScript API and native Mapp configuration values.
|
package/RNMappPlugin.podspec
CHANGED
|
@@ -12,18 +12,24 @@ Pod::Spec.new do |s|
|
|
|
12
12
|
s.homepage = "https://github.com/mapp-digital/Mapp-Engage-ReactNative-Plugin"
|
|
13
13
|
s.license = "MIT"
|
|
14
14
|
s.author = "Mapp"
|
|
15
|
-
s.platforms = { :ios => "
|
|
15
|
+
s.platforms = { :ios => "15.1" }
|
|
16
16
|
s.source = { :git => "https://github.com/mapp-digital/Mapp-Engage-ReactNative-Plugin", :tag => "#{s.version}" }
|
|
17
17
|
|
|
18
|
-
s.source_files = "ios/**/*.{h,c,m,swift}"
|
|
18
|
+
s.source_files = "ios/**/*.{h,c,m,mm,swift}"
|
|
19
19
|
s.exclude_files = "ios/RNMappPluginTests/**/*"
|
|
20
|
-
|
|
20
|
+
# AppoxeeInapp already contains the push SDK binary. Adding AppoxeeSDK here
|
|
21
|
+
# produces duplicate symbols, so it remains preserved for headers/resources only.
|
|
22
|
+
s.vendored_frameworks = "ios/Frameworks/AppoxeeLocationServices.xcframework", "ios/Frameworks/AppoxeeInapp.xcframework"
|
|
21
23
|
s.resources = "ios/Frameworks/AppoxeeSDKResources.bundle", "ios/Frameworks/AppoxeeInappResources.bundle"
|
|
22
24
|
s.preserve_path = "ios/Frameworks/"
|
|
23
25
|
s.public_header_files = "ios/Frameworks/AppoxeeSDK.xcframework/ios-arm64/Headers/", "ios/Frameworks/AppoxeeLocationServices.xcframework/ios-arm64/Headers/", "ios/Frameworks/AppoxeeInapp.xcframework/ios-arm64/Headers/"
|
|
24
26
|
s.requires_arc = true
|
|
25
27
|
s.frameworks = "WebKit"
|
|
26
28
|
s.library = 'sqlite3'
|
|
27
|
-
|
|
29
|
+
if respond_to?(:install_modules_dependencies, true)
|
|
30
|
+
install_modules_dependencies(s)
|
|
31
|
+
else
|
|
32
|
+
s.dependency "React-Core"
|
|
33
|
+
end
|
|
28
34
|
|
|
29
35
|
end
|