react-native-acoustic-connect-beta 18.0.29 → 18.0.30

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.
@@ -2,8 +2,25 @@ require "json"
2
2
 
3
3
  package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
4
 
5
- # package = JSON.parse(File.read('package.json'))
6
- connectConfig = JSON.parse(File.read('../../ConnectConfig.json'))
5
+ # Resolve the consumer's ConnectConfig.json from the Podfile's project root.
6
+ #
7
+ # Using CocoaPods' install root (the directory containing the Podfile) rather
8
+ # than a path relative to this podspec makes config resolution correct in every
9
+ # layout, so SDK integration is seamless for clients:
10
+ # - Standalone consumer: the pod lives under <app>/node_modules, the install
11
+ # root is <app>/ios, so <install_root>/../ConnectConfig.json resolves to
12
+ # <app>/ConnectConfig.json.
13
+ # - In-repo example apps (this monorepo's Examples/*): the install root is the
14
+ # example's own ios/ dir, so it resolves to that example's ConnectConfig.json
15
+ # instead of escaping above the repo (which a podspec-relative climb did).
16
+ # Falls back to the legacy podspec-relative path when the install root isn't
17
+ # available (e.g. `pod spec lint`), preserving prior behaviour.
18
+ installRoot = (defined?(Pod::Config) && Pod::Config.instance.installation_root) || nil
19
+ consumerConfigPath = File.join(installRoot.to_s, '..', 'ConnectConfig.json') if installRoot
20
+ connectConfigPath =
21
+ (consumerConfigPath && File.exist?(consumerConfigPath)) ? consumerConfigPath
22
+ : File.join(__dir__, '..', '..', 'ConnectConfig.json')
23
+ connectConfig = JSON.parse(File.read(connectConfigPath))
7
24
  repository = package["repository"]["url"]
8
25
  useRelease = connectConfig["Connect"]["useRelease"]
9
26
  dependencyName = useRelease ? 'AcousticConnect' : 'AcousticConnectDebug'
@@ -188,6 +188,23 @@ dependencies {
188
188
  //noinspection GradleDynamicVersion
189
189
  implementation "io.github.go-acoustic:$acousticArtifact:$acousticVersion"
190
190
 
191
+ // Firebase Cloud Messaging — required by the push variant. The
192
+ // `connect-push-fcm` AAR calls `com.google.firebase.messaging.*`
193
+ // (its `FCMPushService` extends `FirebaseMessagingService`) but its
194
+ // published POM does NOT declare firebase-messaging, so the transitive
195
+ // never arrives. Without it the push classes fail to link at runtime and
196
+ // push silently stays inactive — the bridge logs
197
+ // `connect-push-fcm on classpath: false` and no FCM token is ever
198
+ // requested. Gated by the same `PushEnabled` flag so analytics-only
199
+ // builds pull zero Firebase. The host app still supplies its own
200
+ // `google-services.json` and applies the `com.google.gms.google-services`
201
+ // plugin (the bare-workflow demo does this conditionally). The BoM aligns
202
+ // messaging + its installations/datatransport transitives. See CA-144314.
203
+ if (acousticPushEnabled) {
204
+ implementation platform('com.google.firebase:firebase-bom:33.7.0')
205
+ implementation 'com.google.firebase:firebase-messaging'
206
+ }
207
+
191
208
  // Version range enforced by the RN bridge. Lower bound prevents downgrades
192
209
  // to releases that lack APIs this bridge calls; upper bound prevents a
193
210
  // future 12.x major (with potentially breaking changes) from being picked
@@ -1,4 +1,4 @@
1
- #Fri Jun 05 02:59:23 PDT 2026
1
+ #Thu Jun 11 03:38:51 PDT 2026
2
2
  UseWhiteList=true
3
3
  PrintScreen=3
4
4
  UseRandomSample=false
@@ -49,6 +49,7 @@ import com.acoustic.connect.android.connectmod.Connect.onResume
49
49
  import com.acoustic.connect.android.connectmod.Connect.registerFormField
50
50
  import com.acoustic.connect.android.connectmod.Connect.resumeConnect
51
51
  import com.acoustic.connect.android.connectmod.push.PushPermissionState
52
+ import com.acoustic.connect.android.connectmod.push.core.MobileServiceType
52
53
  import com.facebook.react.bridge.LifecycleEventListener
53
54
  import com.facebook.react.bridge.ReactApplicationContext
54
55
  import com.facebook.react.uimanager.UIManagerHelper
@@ -156,9 +157,59 @@ class HybridAcousticConnectRN : HybridAcousticConnectRNSpec(),
156
157
  Connect.init(app)
157
158
  }
158
159
  Connect.enable()
160
+ maybeEnablePushOnMain(app)
159
161
  Log.i(TAG, "[bridge] SDK auto-initialised at bridge construction")
160
162
  }
161
163
 
164
+ /**
165
+ * Bootstraps the native Connect push transport when the push variant is
166
+ * present. This is REQUIRED — it is not automatic. The `connect` /
167
+ * `connect-push-fcm` AARs declare no ContentProvider or `Startup`
168
+ * initializer, so nothing self-bootstraps `ConnectPush`. Its
169
+ * `enable(...)` is the sole entry point that creates the FCM
170
+ * [com.acoustic.connect.android.connectmod.push.PushService] transport,
171
+ * sets `isInitialized = true`, registers the activity-lifecycle
172
+ * callbacks, and constructs the `TokenUpdaterReceiver` that turns the
173
+ * FCM `onNewToken` broadcast into a Connect PushRegistration. Without
174
+ * this call the token broadcast is dropped and `sendToken()` no-ops on
175
+ * `isInitialized == false`, so no registration ever reaches Connect.
176
+ *
177
+ * Gated by [isConnectPushFcmAvailable] so analytics-only
178
+ * (`PushEnabled=false`) builds — which bundle no Firebase — never touch
179
+ * the FCM transport classes. Idempotent: short-circuits once
180
+ * `Connect.push.isInitialized()` is true, so it is safe to call from
181
+ * every init path (construction auto-init, JS `enable()`, lifecycle
182
+ * resume). `MobileServiceType.FCM` is hard-coded: FCM is the only push
183
+ * provider on the JS surface (HMS was dropped — see deviation 4).
184
+ *
185
+ * MUST be called on the main looper, after `Connect.enable()`.
186
+ */
187
+ private fun maybeEnablePushOnMain(application: Application) {
188
+ if (!isConnectPushFcmAvailable()) return
189
+ if (Connect.push.isInitialized()) return
190
+ val smallIconRes = resolvePushSmallIconRes(application)
191
+ Connect.push.enable(application, true, smallIconRes, MobileServiceType.FCM) { e ->
192
+ Log.w(TAG, "[bridge] push enable failed — ${e.message}")
193
+ }
194
+ Log.i(TAG, "[bridge] Connect push transport enabled (FCM)")
195
+ }
196
+
197
+ /**
198
+ * Resolves the status-bar notification small-icon drawable for push.
199
+ * Looks up `ic_stat_push` (the demo's committed monochrome icon, also
200
+ * the `AndroidNotificationIconResName` convention) and falls back to the
201
+ * app's launcher icon when absent, so consumers that didn't add a
202
+ * dedicated push icon still get a valid resource rather than `0`.
203
+ */
204
+ private fun resolvePushSmallIconRes(application: Application): Int {
205
+ val byName = application.resources.getIdentifier(
206
+ "ic_stat_push",
207
+ "drawable",
208
+ application.packageName,
209
+ )
210
+ return if (byName != 0) byName else application.applicationInfo.icon
211
+ }
212
+
162
213
  /**
163
214
  * Resolves the host app's `Application` from
164
215
  * `NitroModules.applicationContext`. Returns `null` (with a logged
@@ -214,6 +265,7 @@ class HybridAcousticConnectRN : HybridAcousticConnectRNSpec(),
214
265
  }
215
266
  Connect.init(application)
216
267
  Connect.enable()
268
+ maybeEnablePushOnMain(application)
217
269
  Log.i(TAG, "[bridge] SDK initialised")
218
270
  }
219
271
  return true
@@ -235,31 +287,40 @@ class HybridAcousticConnectRN : HybridAcousticConnectRNSpec(),
235
287
 
236
288
  // region Push (Android)
237
289
  //
238
- // The shared Nitro spec declares these push methods on both platforms. On
239
- // Android the native SDK owns the ENTIRE push lifecycle — Connect's own
240
- // FirebaseMessagingService (shipped in connect-push-fcm) handles inbound
241
- // delivery, PushReceived / PushAction logging, and token registration
242
- // automatically. Unlike iOS, Android has no manual JS-forwarding API, so
243
- // every JS→native forwarder is a no-op that reports "handled", kept only
244
- // for cross-platform API symmetry:
290
+ // The shared Nitro spec declares these push methods on both platforms.
291
+ // Once the bridge bootstraps the native push transport via
292
+ // [maybeEnablePushOnMain] (`Connect.push.enable(..., MobileServiceType.FCM)`
293
+ // at SDK init), the native SDK owns the rest of the push lifecycle:
294
+ // Connect's own FirebaseMessagingService (shipped in connect-push-fcm)
295
+ // handles inbound delivery and PushReceived / PushAction logging, and the
296
+ // `TokenUpdaterReceiver` registered by `enable(...)` turns the FCM
297
+ // `onNewToken` broadcast into a Connect PushRegistration. That bootstrap
298
+ // is NOT automatic — the AARs declare no ContentProvider / Startup
299
+ // initializer, so without the `enable(...)` call no token ever registers.
300
+ //
301
+ // After bootstrap there is no manual JS-forwarding API on Android (unlike
302
+ // iOS), so every JS→native forwarder below is a no-op that reports
303
+ // "handled", kept only for cross-platform API symmetry:
245
304
  // - pushDidReceiveNotification, pushDidReceiveResponse,
246
305
  // pushDidRegisterWithToken, pushDidFailToRegister,
247
306
  // pushDidReceiveAuthorization
248
307
  //
249
- // The only Android-relevant behaviour is permission wiring:
308
+ // The only Android-relevant runtime interaction is permission wiring:
250
309
  // - pushRequestPermission / pushGetPermissionState — POST_NOTIFICATIONS
251
310
  //
252
311
  // pushGetToken / pushGetTokenAsync are intentionally NOT on the surface —
253
- // parked (the native SDK registers the token with Connect automatically;
254
- // no JS accessor is needed). None of these methods reject.
312
+ // parked (the native transport registers the token with Connect once
313
+ // enabled; no JS accessor is needed). None of these methods reject.
255
314
 
256
315
  /**
257
- * iOS-primary forwarder. On Android the FCM token is captured and registered
258
- * with Connect automatically by the native messaging service, so this is a
259
- * no-op that reports "handled". Never rejects.
316
+ * iOS-primary forwarder. On Android the FCM token is captured and
317
+ * registered with Connect by the native transport once it is bootstrapped
318
+ * via [maybeEnablePushOnMain] (the `TokenUpdaterReceiver` set up by
319
+ * `Connect.push.enable(...)` consumes the `onNewToken` broadcast), so this
320
+ * JS forwarder is a no-op that reports "handled". Never rejects.
260
321
  */
261
322
  override fun pushDidRegisterWithToken(deviceToken: ArrayBuffer): Promise<Boolean> {
262
- Log.d(TAG, "[bridge] pushDidRegisterWithToken: no-op on Android (native SDK owns token registration)")
323
+ Log.d(TAG, "[bridge] pushDidRegisterWithToken: no-op on Android (native transport owns token registration once enabled)")
263
324
  return Promise.resolved(true)
264
325
  }
265
326
 
@@ -1283,6 +1344,7 @@ class HybridAcousticConnectRN : HybridAcousticConnectRNSpec(),
1283
1344
  // call the native SDK's `Connect.enable()` directly so the
1284
1345
  // log line "called from JS" doesn't fire on lifecycle wake-ups.
1285
1346
  Connect.enable()
1347
+ resolveApplication()?.let { maybeEnablePushOnMain(it) }
1286
1348
  }
1287
1349
  onResume(activity, null)
1288
1350
  }
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "Connect": {
3
- "AndroidVersion": "11.0.12-beta",
4
3
  "AppKey": "b6c3709b7a4c479bb4b5a9fb8fec324c",
5
4
  "KillSwitchUrl": "https://lib-us-2.brilliantcollector.com/collector/switch/b6c3709b7a4c479bb4b5a9fb8fec324c",
6
5
  "PostMessageUrl": "https://lib-us-2.brilliantcollector.com/collector/collectorPost",
6
+ "AndroidVersion": "",
7
7
  "iOSVersion": "",
8
+ "PushEnabled": false,
9
+ "iOSPushMode": "automatic",
10
+ "iOSAppGroupIdentifier": null,
11
+ "AndroidNotificationIconResName": null,
8
12
  "layoutConfigAndroid": {
9
13
  "AppendMapIds": {
10
14
  "[w,9290],[v,0]": {
package/package.json CHANGED
@@ -195,7 +195,7 @@
195
195
  "source": "src/index",
196
196
  "summary": "react-native ios android tealeaf connect cxa wxca er enhanced-replay",
197
197
  "types": "./lib/typescript/src/index.d.ts",
198
- "version": "18.0.29",
198
+ "version": "18.0.30",
199
199
  "workspaces": [
200
200
  "example",
201
201
  "Examples/bare-workflow"