@attentive-mobile/attentive-react-native-sdk 2.0.0-beta.7 → 2.0.0-beta.8

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/README.md CHANGED
@@ -81,7 +81,12 @@ Attentive.initialize(config);
81
81
 
82
82
  #### Android — Initialize from Native Code
83
83
 
84
- On Android, `AttentiveSdk.initialize()` **must** be called from your `Application.onCreate()` in native Kotlin/Java code. This is required so that lifecycle observers (e.g. `AppLaunchTracker`) are registered before the React Native bridge is ready. Calling `initialize()` from TypeScript on Android is a **no-op** — the SDK will not be started and all subsequent event calls will fail.
84
+ On Android, `AttentiveSdk.initialize()` **must** be called from your `Application.onCreate()` in native Kotlin/Java code. There are two reasons for this:
85
+
86
+ 1. **Lifecycle observers must be registered before the React Native bridge is ready.** Internally, the SDK creates an `AppLaunchTracker` that calls `lifecycle.addObserver()` on the `ProcessLifecycleOwner`. If initialization happens after the bridge starts, early app-launch events can be missed.
87
+ 2. **`lifecycle.addObserver()` requires the main thread.** AndroidX enforces this with an `IllegalStateException` if called from a background thread. `Application.onCreate()` is guaranteed by the Android system to run on the main thread, so calling `initialize` there satisfies this requirement automatically — no extra threading machinery needed.
88
+
89
+ > **Do not** call `AttentiveSdk.initialize()` from a background thread or a coroutine dispatcher other than `Dispatchers.Main`. Doing so will throw an `IllegalStateException` from inside the AndroidX Lifecycle library.
85
90
 
86
91
  Add the following to your `MainApplication.kt` (or `MainApplication.java`):
87
92
 
@@ -90,7 +95,6 @@ import android.app.Application
90
95
  import com.attentive.androidsdk.AttentiveConfig
91
96
  import com.attentive.androidsdk.AttentiveSdk
92
97
  import com.attentive.androidsdk.AttentiveLogLevel
93
- import com.facebook.react.bridge.UiThreadUtil
94
98
 
95
99
  class MainApplication : Application(), ReactApplication {
96
100
 
@@ -109,15 +113,14 @@ class MainApplication : Application(), ReactApplication {
109
113
  .logLevel(AttentiveLogLevel.VERBOSE)
110
114
  .build()
111
115
 
112
- // AttentiveSdk.initialize registers lifecycle observers and must run on the main thread.
113
- UiThreadUtil.runOnUiThread {
114
- AttentiveSdk.initialize(config)
115
- }
116
+ // Application.onCreate() is always called on the main thread by the Android system,
117
+ // so no thread-switching wrapper is needed here.
118
+ AttentiveSdk.initialize(config)
116
119
  }
117
120
  }
118
121
  ```
119
122
 
120
- After the native initialization, all other SDK operations (`identify`, `recordAddToCartEvent`, `recordPurchaseEvent`, etc.) are called from TypeScript as normal on both platforms. The TypeScript `initialize()` call is still required on iOS but is safely ignored on Android.
123
+ After the native initialization, all other SDK operations (`identify`, `recordAddToCartEvent`, `recordPurchaseEvent`, etc.) are called from TypeScript as normal on both platforms.
121
124
 
122
125
  > **Tip:** If you see `[AttentiveSDK] recordAddToCartEvent failed — SDK may not be initialized` in your Android logcat, it means `AttentiveSdk.initialize()` was not called from native code before the event was recorded. Check your `Application.onCreate()` setup.
123
126
 
@@ -218,7 +221,7 @@ Attentive.identify({phone: '+15556667777'};)
218
221
 
219
222
  ### Push Notifications (iOS and Android)
220
223
 
221
- The SDK supports push notification integration on both iOS (APNs) and Android (runtime permission + optional FCM). The following sections cover iOS-specific flows and a full **App events on Android** implementation that mirrors the behavior of the [Bonni](https://github.com/attentive-mobile/attentive-react-native-sdk/tree/main/Bonni) example app.
224
+ The SDK supports push notification integration on both iOS (APNs) and Android (FCM). The following sections cover iOS-specific setup flows. On Android, push notification integration is handled entirely in native Kotlin/Java code see [App Events on Android](#app-events-on-android) for details.
222
225
 
223
226
  > **iOS — required setup:** Your AppDelegate **must** forward notification
224
227
  > responses to the SDK for push tracking to work. Add this single line to your
@@ -243,22 +246,9 @@ The SDK supports push notification integration on both iOS (APNs) and Android (r
243
246
 
244
247
  ### App Events on Android
245
248
 
246
- This section describes how to implement Attentive app events on Android so they behave like the iOS flow: **regular app opens** (launch and resume from background) and **notification permission** are handled using the SDK’s native Android APIs. You can add FCM token registration and push open handling when your app uses Firebase Cloud Messaging.
249
+ On Android, **regular app open and foreground events are handled automatically** by the native Android SDK once `AttentiveSdk.initialize()` is called from `Application.onCreate()` (see [Android Native Initialization](#android--initialize-from-native-code)). The lifecycle observers registered during initialization (e.g. `AppLaunchTracker`) take care of this transparently there is no need to manually call `handleRegularOpen` or subscribe to `AppState` changes.
247
250
 
248
- | SDK method | Purpose on Android |
249
- |------------|--------------------|
250
- | `getPushAuthorizationStatus()` | Returns `authorized`, `denied`, or `notDetermined` (uses `POST_NOTIFICATIONS` on API 33+). Use before `handleRegularOpen` so tracking uses the correct status. |
251
- | `registerForPushNotifications()` | Requests `POST_NOTIFICATIONS` on Android 13+; no-op on older versions. |
252
- | `handleRegularOpen(authStatus)` | Tracks a regular app open (launch or return to foreground). Call after `identify()` and pass the result of `getPushAuthorizationStatus()`. |
253
- | `registerDeviceToken` / `registerDeviceTokenWithCallback` | Optional. Register your FCM token when using Firebase Cloud Messaging. |
254
- | `handlePushOpen` / `handleForegroundPush` | Optional. Call when the user opens a notification or receives one in the foreground. |
255
-
256
- #### Overview
257
-
258
- - **Regular app open** – Call `handleRegularOpen(authorizationStatus)` when the app is opened (launch or returning to foreground). The SDK uses this for tracking and the `/mtctrl` endpoint.
259
- - **Permission status** – On Android 13+ (API 33+), notification permission is `POST_NOTIFICATIONS`. The SDK exposes `getPushAuthorizationStatus()` so you can pass the correct status into `handleRegularOpen`.
260
- - **Requesting permission** – Call `registerForPushNotifications()` to trigger the system permission dialog on Android 13+; it is a no-op on older versions.
261
- - **Order of operations** – Always call `identify()` before any `handleRegularOpen()` so the SDK has user context for network requests.
251
+ The only TypeScript-side step required on Android is calling `identify()` with any available user identifiers as early as possible in your app’s lifecycle (e.g. in the root component `useEffect`).
262
252
 
263
253
  #### Prerequisites
264
254
 
@@ -271,115 +261,78 @@ This section describes how to implement Attentive app events on Android so they
271
261
  </manifest>
272
262
  ```
273
263
 
274
- 2. **Initialize and identify first** – The SDK must be initialized natively from `Application.onCreate()` on Android (see [Android Native Initialization](#android--initialize-from-native-code) above). Then, in your app entry (e.g. root component `useEffect`), call `identify(identifiers)` before any push or app-event logic.
275
-
276
- #### 1. On app launch (Android)
264
+ 2. **Native initialization** – The SDK must be initialized from `Application.onCreate()` on Android (see [Android Native Initialization](#android--initialize-from-native-code) above). App open and lifecycle events are then tracked automatically.
277
265
 
278
- Right after `identify()`, do the following for the Android path:
266
+ #### TypeScript setup (Android)
279
267
 
280
- 1. Get the current notification authorization status with `getPushAuthorizationStatus()`.
281
- 2. Call `handleRegularOpen(authStatus)` with that status.
282
- 3. Optionally call `registerForPushNotifications()` to prompt for permission (Android 13+).
268
+ After native initialization, the only required TypeScript call is `identify()`:
283
269
 
284
270
  ```typescript
285
271
  import { Platform } from 'react-native';
286
- import {
287
- initialize,
288
- identify,
289
- getPushAuthorizationStatus,
290
- registerForPushNotifications,
291
- handleRegularOpen,
292
- type AttentiveSdkConfiguration,
293
- type PushAuthorizationStatus,
294
- } from 'attentive-react-native-sdk';
272
+ import { initialize, identify } from 'attentive-react-native-sdk';
295
273
 
296
274
  // Inside your root component (e.g. App.tsx useEffect):
297
-
298
- // iOS only: initialize from TypeScript.
299
- // Android: initialization must be done natively from Application.onCreate() — see README.
300
275
  if (Platform.OS === 'ios') {
301
276
  initialize(config);
302
277
  }
303
278
 
304
279
  identify({ email: 'user@example.com', clientUserId: 'id-123' });
305
-
306
- if (Platform.OS === 'android') {
307
- getPushAuthorizationStatus()
308
- .then((authStatus: PushAuthorizationStatus) => {
309
- handleRegularOpen(authStatus);
310
- })
311
- .catch(() => {
312
- handleRegularOpen('authorized'); // fallback
313
- });
314
- registerForPushNotifications(); // Shows permission dialog on Android 13+
315
- }
316
280
  ```
317
281
 
318
- #### 2. When app returns to foreground (Android)
282
+ #### Push notifications on Android (FCM)
319
283
 
320
- Subscribe to `AppState` and, when the app becomes `active`, get the current status and call `handleRegularOpen` again:
284
+ On Android, FCM token registration and push notification handling are managed natively in Kotlin/Java. This gives you full control over the Firebase Messaging lifecycle and ensures events are tracked before the React Native bridge initialises.
321
285
 
322
- ```typescript
323
- import { AppState } from 'react-native';
324
- import { getPushAuthorizationStatus, handleRegularOpen } from 'attentive-react-native-sdk';
325
- import type { PushAuthorizationStatus } from 'attentive-react-native-sdk';
326
-
327
- const subscription = AppState.addEventListener('change', (nextAppState) => {
328
- if (nextAppState === 'active' && Platform.OS === 'android') {
329
- getPushAuthorizationStatus()
330
- .then((authStatus: PushAuthorizationStatus) => {
331
- handleRegularOpen(authStatus);
332
- })
333
- .catch(() => {
334
- handleRegularOpen('authorized');
335
- });
336
- }
337
- });
338
-
339
- // Cleanup on unmount:
340
- return () => subscription.remove();
341
- ```
286
+ Add Firebase Cloud Messaging to your app following the [Firebase Android setup guide](https://firebase.google.com/docs/cloud-messaging/android/client), then handle token registration and notification events in your native `FirebaseMessagingService`:
342
287
 
343
- #### 3. Optional: Register FCM token (Android)
288
+ ```kotlin
289
+ import com.attentive.androidsdk.AttentiveSdk
290
+ import com.google.firebase.messaging.FirebaseMessagingService
291
+ import com.google.firebase.messaging.RemoteMessage
344
292
 
345
- **Recommended:** This React Native SDK’s Android native module depends on Attentive Android SDK **2.1.1**, which exposes `AttentiveSdk.getPushTokenWithCallback`. Calling `registerForPushNotifications()` from JS triggers that API: the SDK requests permission (when needed), fetches the FCM token, and registers it with Attentive. No separate native code is required.
293
+ class AttentiveMessagingService : FirebaseMessagingService() {
346
294
 
347
- **Alternative (token from JS):** If you obtain the FCM token elsewhere (e.g. Firebase Messaging), use `registerDeviceTokenWithCallback` and then call `handleRegularOpen` in the callback:
295
+ override fun onNewToken(token: String) {
296
+ super.onNewToken(token)
297
+ // Register the FCM token with the Attentive SDK
298
+ AttentiveSdk.registerDeviceToken(token)
299
+ }
348
300
 
349
- ```typescript
350
- import { registerDeviceTokenWithCallback, handleRegularOpen } from 'attentive-react-native-sdk';
351
-
352
- getPushAuthorizationStatus().then((authStatus) => {
353
- registerDeviceTokenWithCallback(
354
- fcmToken,
355
- authStatus,
356
- (data, url, response, error) => {
357
- if (error) {
358
- console.error('Attentive token registration failed', error);
359
- }
360
- handleRegularOpen(authStatus);
301
+ override fun onMessageReceived(remoteMessage: RemoteMessage) {
302
+ super.onMessageReceived(remoteMessage)
303
+ // Handle foreground push delivery
304
+ AttentiveSdk.handleForegroundPush(remoteMessage.data)
361
305
  }
362
- );
363
- });
306
+ }
364
307
  ```
365
308
 
366
- #### 4. Optional: Handle notification opens and foreground (Android)
309
+ For notification opens (when the user taps a push notification), handle the intent in your main `Activity`:
367
310
 
368
- If you handle FCM messages (e.g. with `@react-native-firebase/messaging`), you can report notification opens and foreground receives the same way as on iOS:
311
+ ```kotlin
312
+ import com.attentive.androidsdk.AttentiveSdk
369
313
 
370
- - **User opened notification (background/inactive):** `handlePushOpen(payload, authorizationStatus)`
371
- - **Notification received while app in foreground:** `handleForegroundPush(payload, authorizationStatus)`
314
+ class MainActivity : ReactActivity() {
372
315
 
373
- Get `authorizationStatus` via `getPushAuthorizationStatus()` when handling the event.
316
+ override fun onResume() {
317
+ super.onResume()
318
+ intent?.let { AttentiveSdk.handlePushOpen(it) }
319
+ }
320
+ }
321
+ ```
374
322
 
375
- #### Complete Android flow (reference)
323
+ Declare the service in your `AndroidManifest.xml`:
376
324
 
377
- The [Bonni](https://github.com/attentive-mobile/attentive-react-native-sdk/tree/main/Bonni) example app ([App.tsx](https://github.com/attentive-mobile/attentive-react-native-sdk/blob/main/Bonni/App.tsx)) implements the full flow:
325
+ ```xml
326
+ <service
327
+ android:name=".AttentiveMessagingService"
328
+ android:exported="false">
329
+ <intent-filter>
330
+ <action android:name="com.google.firebase.MESSAGING_EVENT" />
331
+ </intent-filter>
332
+ </service>
333
+ ```
378
334
 
379
- 1. **Launch:** Native `AttentiveSdk.initialize(config)` (from `Application.onCreate()`) TypeScript `identify` `getPushAuthorizationStatus()` `handleRegularOpen(authStatus)` `registerForPushNotifications()`.
380
- 2. **Foreground:** `AppState.addEventListener('change', …)` → when `active` and Android → `getPushAuthorizationStatus()` → `handleRegularOpen(authStatus)`.
381
- 3. **Optional:** When FCM token is available → `registerDeviceTokenWithCallback(token, authStatus, callback)` → in callback call `handleRegularOpen(authStatus)`.
382
- 4. **Optional:** When user opens a notification or receives one in foreground → `handlePushOpen` / `handleForegroundPush` with payload and status from `getPushAuthorizationStatus()`.
335
+ Refer to the [Attentive Android SDK documentation](https://github.com/attentive-mobile/attentive-android-sdk) for the full list of native APIs available for push notification integration.
383
336
 
384
337
  ---
385
338
 
@@ -393,9 +346,9 @@ import { registerForPushNotifications } from 'attentive-react-native-sdk';
393
346
  registerForPushNotifications();
394
347
  ```
395
348
 
396
- #### Register Device Token (iOS: APNs / Android: FCM)
349
+ #### Register Device Token (iOS)
397
350
 
398
- When your app receives a device token (APNs on iOS, FCM on Android), register it with the Attentive backend:
351
+ When your iOS app receives an APNs device token, register it with the Attentive backend:
399
352
 
400
353
  ```typescript
401
354
  import { registerDeviceToken } from 'attentive-react-native-sdk';
@@ -412,7 +365,7 @@ The `authorizationStatus` parameter should be one of:
412
365
  - `'provisional'` - Provisional authorization (quiet notifications)
413
366
  - `'ephemeral'` - App Clip notifications
414
367
 
415
- #### Handle Push Notification Opens (iOS and Android)
368
+ #### Handle Push Notification Opens (iOS)
416
369
 
417
370
  When a user taps on a push notification, track the event:
418
371
 
@@ -428,7 +381,7 @@ handlePushOpened(
428
381
  );
429
382
  ```
430
383
 
431
- #### Handle Foreground Notifications (iOS and Android)
384
+ #### Handle Foreground Notifications (iOS)
432
385
 
433
386
  When a notification arrives while the app is in the foreground:
434
387
 
@@ -523,9 +476,8 @@ func application(
523
476
  ```
524
477
 
525
478
  **Documentation:**
526
- - [Push Token Registration Guide](./PUSH_TOKEN_REGISTRATION_GUIDE.md) - Detailed guide for callback-based registration
527
- - [AppDelegate Callback Example](./APPDELEGATE_CALLBACK_EXAMPLE.md) - Complete AppDelegate implementation
528
- - [Push Notifications Setup](./PUSH_NOTIFICATIONS_SETUP.md) - General push notification setup
479
+ - [Push Notifications Integration Guide](./docs/PUSH_NOTIFICATIONS_INTEGRATION.md) - Callback-based registration, complete AppDelegate implementation, Android and iOS token flow
480
+ - [Push Notifications Setup](./docs/PUSH_NOTIFICATIONS_SETUP.md) - Apple Developer Portal, APNs certificates, and TestFlight configuration
529
481
  - [iOS Native SDK documentation](https://github.com/attentive-mobile/attentive-ios-sdk) - Native SDK reference
530
482
 
531
- For a full Android implementation (app launch, foreground, permission, and optional FCM), see the **[App Events on Android](#app-events-on-android)** section above.
483
+ For Android push notification integration, see the **[App Events on Android](#app-events-on-android)** section above.
@@ -88,7 +88,7 @@ class AttentiveReactNativeSdkModule(reactContext: ReactApplicationContext) :
88
88
  ) {
89
89
  debugHelper.initialize(enableDebugger)
90
90
 
91
- Log.w(
91
+ Log.d(
92
92
  TAG,
93
93
  "[AttentiveSDK] initialize() called from TypeScript is a NO-OP on Android. " +
94
94
  "You must call AttentiveSdk.initialize(config) from your Application.onCreate() " +
@@ -187,17 +187,7 @@ class AttentiveReactNativeSdkModule(reactContext: ReactApplicationContext) :
187
187
  val itemsList = buildItems(items)
188
188
  val productViewEvent = ProductViewEvent.Builder().items(itemsList).deeplink(deeplink).build()
189
189
 
190
- try {
191
- AttentiveSdk.recordEvent(productViewEvent)
192
- } catch (e: Exception) {
193
- Log.e(
194
- TAG,
195
- "[AttentiveSDK] recordProductViewEvent failed — SDK may not be initialized. " +
196
- "On Android, call AttentiveSdk.initialize(config) from Application.onCreate() " +
197
- "before recording events. Error: ${e.message}"
198
- )
199
- return
200
- }
190
+ if (!recordEventSafely("recordProductViewEvent") { AttentiveSdk.recordEvent(productViewEvent) }) return
201
191
 
202
192
  if (debugHelper.isDebuggingEnabled()) {
203
193
  val debugData = mutableMapOf<String, Any>()
@@ -227,17 +217,7 @@ class AttentiveReactNativeSdkModule(reactContext: ReactApplicationContext) :
227
217
  }
228
218
  val purchaseEvent = purchaseBuilder.build()
229
219
 
230
- try {
231
- AttentiveSdk.recordEvent(purchaseEvent)
232
- } catch (e: Exception) {
233
- Log.e(
234
- TAG,
235
- "[AttentiveSDK] recordPurchaseEvent failed — SDK may not be initialized. " +
236
- "On Android, call AttentiveSdk.initialize(config) from Application.onCreate() " +
237
- "before recording events. Error: ${e.message}"
238
- )
239
- return
240
- }
220
+ if (!recordEventSafely("recordPurchaseEvent") { AttentiveSdk.recordEvent(purchaseEvent) }) return
241
221
 
242
222
  if (debugHelper.isDebuggingEnabled()) {
243
223
  val debugData = mutableMapOf<String, Any>()
@@ -260,17 +240,7 @@ class AttentiveReactNativeSdkModule(reactContext: ReactApplicationContext) :
260
240
  val itemsList = buildItems(items)
261
241
  val addToCartEvent = AddToCartEvent.Builder().items(itemsList).deeplink(deeplink).build()
262
242
 
263
- try {
264
- AttentiveSdk.recordEvent(addToCartEvent)
265
- } catch (e: Exception) {
266
- Log.e(
267
- TAG,
268
- "[AttentiveSDK] recordAddToCartEvent failed — SDK may not be initialized. " +
269
- "On Android, call AttentiveSdk.initialize(config) from Application.onCreate() " +
270
- "before recording events. Error: ${e.message}"
271
- )
272
- return
273
- }
243
+ if (!recordEventSafely("recordAddToCartEvent") { AttentiveSdk.recordEvent(addToCartEvent) }) return
274
244
 
275
245
  if (debugHelper.isDebuggingEnabled()) {
276
246
  val debugData = mutableMapOf<String, Any>()
@@ -290,17 +260,7 @@ class AttentiveReactNativeSdkModule(reactContext: ReactApplicationContext) :
290
260
  val propertiesMap = convertToStringMap(properties.toHashMap())
291
261
  val customEvent = CustomEvent.Builder().type(type).properties(propertiesMap).build()
292
262
 
293
- try {
294
- AttentiveSdk.recordEvent(customEvent)
295
- } catch (e: Exception) {
296
- Log.e(
297
- TAG,
298
- "[AttentiveSDK] recordCustomEvent failed — SDK may not be initialized. " +
299
- "On Android, call AttentiveSdk.initialize(config) from Application.onCreate() " +
300
- "before recording events. Error: ${e.message}"
301
- )
302
- return
303
- }
263
+ if (!recordEventSafely("recordCustomEvent") { AttentiveSdk.recordEvent(customEvent) }) return
304
264
 
305
265
  if (debugHelper.isDebuggingEnabled()) {
306
266
  val debugData = mutableMapOf<String, Any>()
@@ -844,6 +804,36 @@ class AttentiveReactNativeSdkModule(reactContext: ReactApplicationContext) :
844
804
  * @param rawItems The raw item array as received from the React Native bridge.
845
805
  * @return A list of maps, one per item, containing all present fields.
846
806
  */
807
+ /**
808
+ * Executes [block] (which calls [AttentiveSdk.recordEvent]) and catches any [Exception].
809
+ *
810
+ * When an exception is caught the log always includes the exception's simple class name so
811
+ * callers can distinguish an uninitialized-SDK error (typically [IllegalStateException]) from
812
+ * a programming mistake such as [NullPointerException] or [IllegalArgumentException] in event
813
+ * construction — both of which would have been silently misattributed to initialization
814
+ * failure under the previous broad catch-and-blame pattern.
815
+ *
816
+ * @param callerName Method name to include in the log for quick triage (e.g. "recordPurchaseEvent").
817
+ * @param block Lambda that performs the [AttentiveSdk.recordEvent] call.
818
+ * @return `true` if [block] completed without throwing, `false` if an exception was caught.
819
+ */
820
+ private fun recordEventSafely(callerName: String, block: () -> Unit): Boolean {
821
+ return try {
822
+ block()
823
+ true
824
+ } catch (e: Exception) {
825
+ // Include the exception class so the developer can tell apart an uninitialized SDK
826
+ // (IllegalStateException) from a malformed-event bug (NullPointerException, etc.)
827
+ Log.e(
828
+ TAG,
829
+ "[AttentiveSDK] $callerName failed with ${e.javaClass.simpleName}: ${e.message}. " +
830
+ "If the SDK was not initialized via AttentiveSdk.initialize() in Application.onCreate(), " +
831
+ "that is the most likely cause. Otherwise, inspect the exception type above."
832
+ )
833
+ false
834
+ }
835
+ }
836
+
847
837
  private fun extractItemsDebugData(rawItems: ReadableArray): List<Map<String, Any>> {
848
838
  val result = mutableListOf<Map<String, Any>>()
849
839
  for (i in 0 until rawItems.size()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@attentive-mobile/attentive-react-native-sdk",
3
- "version": "2.0.0-beta.7",
3
+ "version": "2.0.0-beta.8",
4
4
  "description": "React Native Module for the Attentive SDK",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -1,7 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <Workspace
3
- version = "1.0">
4
- <FileRef
5
- location = "self:">
6
- </FileRef>
7
- </Workspace>
@@ -1,14 +0,0 @@
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>SchemeUserState</key>
6
- <dict>
7
- <key>AttentiveReactNativeSdk.xcscheme_^#shared#^_</key>
8
- <dict>
9
- <key>orderHint</key>
10
- <integer>0</integer>
11
- </dict>
12
- </dict>
13
- </dict>
14
- </plist>