diff --git a/.github/workflows/create-release-pr.yml b/.github/workflows/create-release-pr.yml
index ec213e71..13e5619e 100644
--- a/.github/workflows/create-release-pr.yml
+++ b/.github/workflows/create-release-pr.yml
@@ -198,7 +198,7 @@ jobs:
cd examples/demo
vp run setup
cd ios
- pod install
+ pod update OneSignalXCFramework
)
echo "✓ Refreshed examples/demo/ios/Podfile.lock"
diff --git a/android/build.gradle b/android/build.gradle
index 7e32d134..1df305bf 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -27,19 +27,13 @@ android {
dependencies {
implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}"
- // androidx.startup runs our OneSignalInitializer during Application.onCreate so we can register
- // an ActivityLifecycleCallbacks before MainActivity.onResume fires. This avoids the cold-start
- // race where ReactApplicationContext.getCurrentActivity() returns null and the OneSignal SDK
- // ends up holding an ApplicationContext instead of the real Activity.
- implementation 'androidx.startup:startup-runtime:1.1.1'
-
// api is used instead of implementation so the parent :app project can access any of the OneSignal Java
// classes if needed. Such as com.onesignal.NotificationExtenderService
//
// Exclude OkHttp from OneSignal's transitive deps: the otel module pulls in OkHttp 5.x
// (via opentelemetry-exporter-sender-okhttp) which is binary-incompatible with React Native's
// networking stack (okhttp3.internal.Util removed in 5.x). React Native already provides OkHttp 4.x.
- api('com.onesignal:OneSignal:5.9.2') {
+ api('com.onesignal:OneSignal:5.9.3') {
exclude group: 'com.squareup.okhttp3', module: 'okhttp'
}
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index 899feb92..94cbbcfc 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -1,14 +1 @@
-
-
-
-
-
-
-
+
diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/ActivityLifecycleTracker.java b/android/src/main/java/com/onesignal/rnonesignalandroid/ActivityLifecycleTracker.java
deleted file mode 100644
index 4079b943..00000000
--- a/android/src/main/java/com/onesignal/rnonesignalandroid/ActivityLifecycleTracker.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.onesignal.rnonesignalandroid;
-
-import android.app.Activity;
-import android.app.Application;
-import android.os.Bundle;
-import androidx.annotation.Nullable;
-import java.lang.ref.WeakReference;
-
-/**
- * Tracks the host app's current Activity from Application.onCreate onward.
- *
- *
Registered very early via {@link OneSignalInitializer} (androidx.startup) so it captures the
- * first {@code MainActivity.onResume} that fires before the React Native bridge has loaded the JS
- * bundle. Without this, {@link com.facebook.react.bridge.ReactApplicationContext#getCurrentActivity()}
- * frequently returns {@code null} during cold start in bridgeless mode, causing
- * {@code RNOneSignal.initialize} to hand the OneSignal SDK an ApplicationContext instead of the
- * real Activity. That in turn leaves {@code ApplicationService.current == null} and queues
- * {@code requestPermission()} until the next foreground.
- */
-public class ActivityLifecycleTracker implements Application.ActivityLifecycleCallbacks {
- private static final ActivityLifecycleTracker INSTANCE = new ActivityLifecycleTracker();
-
- private volatile WeakReference currentActivity = new WeakReference<>(null);
-
- private ActivityLifecycleTracker() {}
-
- public static ActivityLifecycleTracker getInstance() {
- return INSTANCE;
- }
-
- @Nullable
- public Activity getCurrentActivity() {
- return currentActivity.get();
- }
-
- @Override
- public void onActivityCreated(Activity activity, @Nullable Bundle savedInstanceState) {
- currentActivity = new WeakReference<>(activity);
- }
-
- @Override
- public void onActivityStarted(Activity activity) {
- currentActivity = new WeakReference<>(activity);
- }
-
- @Override
- public void onActivityResumed(Activity activity) {
- currentActivity = new WeakReference<>(activity);
- }
-
- @Override
- public void onActivityPaused(Activity activity) {
- // Intentionally no-op: keep the reference so a transient overlay (e.g. permission dialog,
- // PermissionsActivity) doesn't blank out the current Activity for callers that race with it.
- }
-
- @Override
- public void onActivityStopped(Activity activity) {
- // Intentionally no-op for the same reason as onActivityPaused.
- }
-
- @Override
- public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
-
- @Override
- public void onActivityDestroyed(Activity activity) {
- Activity current = currentActivity.get();
- if (current == activity) {
- currentActivity = new WeakReference<>(null);
- }
- }
-}
diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/OneSignalInitializer.java b/android/src/main/java/com/onesignal/rnonesignalandroid/OneSignalInitializer.java
deleted file mode 100644
index 5f295a6a..00000000
--- a/android/src/main/java/com/onesignal/rnonesignalandroid/OneSignalInitializer.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.onesignal.rnonesignalandroid;
-
-import android.app.Application;
-import android.content.Context;
-import androidx.annotation.NonNull;
-import androidx.startup.Initializer;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * androidx.startup entry point that registers {@link ActivityLifecycleTracker} against the host
- * {@link Application} during {@code Application.onCreate}, before any Activity is created.
- *
- * This does NOT initialize the OneSignal SDK itself: the App ID is supplied at runtime by JS
- * via {@code OneSignal.initialize(appId)}. The job here is purely to capture the current Activity
- * early so that when JS later calls initialize, {@code RNOneSignal} can hand a real Activity to
- * {@code OneSignal.initWithContext}.
- */
-public class OneSignalInitializer implements Initializer {
-
- @NonNull
- @Override
- public ActivityLifecycleTracker create(@NonNull Context context) {
- ActivityLifecycleTracker tracker = ActivityLifecycleTracker.getInstance();
- Context appContext = context.getApplicationContext();
- if (appContext instanceof Application) {
- ((Application) appContext).registerActivityLifecycleCallbacks(tracker);
- }
- return tracker;
- }
-
- @NonNull
- @Override
- public List>> dependencies() {
- return Collections.emptyList();
- }
-}
diff --git a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java
index 448af37d..ea4e4c61 100644
--- a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java
+++ b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java
@@ -230,7 +230,7 @@ public void invalidate() {
@Override
public void initialize(String appId) {
OneSignalWrapper.setSdkType("reactnative");
- OneSignalWrapper.setSdkVersion("050406");
+ OneSignalWrapper.setSdkVersion("050407");
if (oneSignalInitDone) {
Logging.debug("Already initialized the OneSignal React-Native SDK", null);
@@ -238,15 +238,7 @@ public void initialize(String appId) {
}
ReactApplicationContext reactContext = getReactApplicationContext();
- // Prefer the Activity captured by ActivityLifecycleTracker (registered via androidx.startup
- // before MainActivity.onResume), then fall back to ReactApplicationContext's accessor and
- // finally the ApplicationContext. Passing the real Activity lets the OneSignal SDK populate
- // ApplicationService.current immediately, so requestPermission() can launch the OS dialog
- // on the first cold-start instead of waiting for the next foreground event.
- Context context = ActivityLifecycleTracker.getInstance().getCurrentActivity();
- if (context == null) {
- context = reactContext.getCurrentActivity();
- }
+ Context context = reactContext.getCurrentActivity();
if (context == null) {
context = reactContext.getApplicationContext();
}
diff --git a/examples/demo/.gitignore b/examples/demo/.gitignore
index 7bc0f3e5..d1b390a3 100644
--- a/examples/demo/.gitignore
+++ b/examples/demo/.gitignore
@@ -1,5 +1,6 @@
# Environment
.env
+.rn-demo-env.stamp
# OSX
#
diff --git a/examples/demo/bun.lock b/examples/demo/bun.lock
index 575fa1d8..a33228da 100644
--- a/examples/demo/bun.lock
+++ b/examples/demo/bun.lock
@@ -1006,7 +1006,7 @@
"react-native-dotenv": ["react-native-dotenv@3.4.11", "", { "dependencies": { "dotenv": "^16.4.5" }, "peerDependencies": { "@babel/runtime": "^7.20.6" } }, "sha512-6vnIE+WHABSeHCaYP6l3O1BOEhWxKH6nHAdV7n/wKn/sciZ64zPPp2NUdEUf1m7g4uuzlLbjgr+6uDt89q2DOg=="],
- "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.79.0" } }, "sha512-/WxWrib5VMiOxe5OAcGSxZI2ABafJISiQSVZBhYJToA19nSIZj/b1IwBs6PUoZWpUJDdFvYJ4DtD0Vc47OIM/g=="],
+ "react-native-onesignal": ["react-native-onesignal@../../react-native-onesignal.tgz", { "dependencies": { "invariant": "^2.2.4" }, "peerDependencies": { "react-native": ">=0.79.0" } }, "sha512-rkTUUbWR/k1Xy6YYZCmkQfj7iv0bP/5QEWhYoz9c7p5QDhhfvyHqtsEhY811ARfdjwvoeiPw7HY86ay+M5UqFg=="],
"react-native-safe-area-context": ["react-native-safe-area-context@5.7.0", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-/9/MtQz8ODphjsLdZ+GZAIcC/RtoqW9EeShf7Uvnfgm/pzYrJ75y3PV/J1wuAV1T5Dye5ygq4EAW20RoBq0ABQ=="],
diff --git a/examples/setup.sh b/examples/setup.sh
index 20e557bb..9f2b6313 100755
--- a/examples/setup.sh
+++ b/examples/setup.sh
@@ -7,6 +7,7 @@ set -euo pipefail
ORIGINAL_DIR=$(pwd)
SDK_ROOT="$(cd ../../ && pwd)"
STAMP_FILE="$SDK_ROOT/.rn-sdk-source.stamp"
+DEMO_ENV_STAMP_FILE="$ORIGINAL_DIR/.rn-demo-env.stamp"
TGZ_FILE="$SDK_ROOT/react-native-onesignal.tgz"
INSTALLED_DIR="$ORIGINAL_DIR/node_modules/react-native-onesignal"
@@ -24,6 +25,34 @@ src_hash=$(find "$SDK_ROOT/src" "$SDK_ROOT/ios" "$SDK_ROOT/android" \
| shasum \
| awk '{print $1}')
+demo_env_hash=$(
+ {
+ for file in "$ORIGINAL_DIR/.env" "$ORIGINAL_DIR/babel.config.js"; do
+ if [ -f "$file" ]; then
+ shasum "$file"
+ else
+ echo "missing $file"
+ fi
+ done
+ } | shasum | awk '{print $1}'
+)
+
+if [ ! -f "$DEMO_ENV_STAMP_FILE" ] || [ "$(cat "$DEMO_ENV_STAMP_FILE")" != "$demo_env_hash" ]; then
+ echo "Demo env inputs changed, clearing Metro cache..."
+ rm -rf "${TMPDIR:-/tmp}"/metro-* "${TMPDIR:-/tmp}"/haste-map-* "$ORIGINAL_DIR/node_modules/.cache/metro" 2>/dev/null || true
+ metro_pids=$(lsof -ti tcp:8081 2>/dev/null || true)
+ for pid in $metro_pids; do
+ args=$(ps -p "$pid" -o args= 2>/dev/null || true)
+ case "$args" in
+ *react-native*|*metro*)
+ echo "Stopping Metro so @env values are reloaded..."
+ kill "$pid" 2>/dev/null || true
+ ;;
+ esac
+ done
+ echo "$demo_env_hash" > "$DEMO_ENV_STAMP_FILE"
+fi
+
# Skip the whole rebuild when:
# - the demo already has the SDK installed,
# - the cached tarball is still on disk, and
diff --git a/ios/RCTOneSignal/RCTOneSignal.mm b/ios/RCTOneSignal/RCTOneSignal.mm
index 6a2db226..bc0ba295 100644
--- a/ios/RCTOneSignal/RCTOneSignal.mm
+++ b/ios/RCTOneSignal/RCTOneSignal.mm
@@ -23,7 +23,7 @@ - (void)initOneSignal:(NSDictionary *)launchOptions {
return;
OneSignalWrapper.sdkType = @"reactnative";
- OneSignalWrapper.sdkVersion = @"050406";
+ OneSignalWrapper.sdkVersion = @"050407";
// initialize the SDK with a nil app ID so cold start click listeners can be
// triggered
[OneSignal initialize:nil withLaunchOptions:launchOptions];
diff --git a/package.json b/package.json
index 061118fb..bbd40177 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "react-native-onesignal",
- "version": "5.4.6",
+ "version": "5.4.7",
"description": "React Native OneSignal SDK",
"keywords": [
"android",
diff --git a/react-native-onesignal.podspec b/react-native-onesignal.podspec
index cf0ca59f..8bc58883 100644
--- a/react-native-onesignal.podspec
+++ b/react-native-onesignal.podspec
@@ -15,5 +15,5 @@ Pod::Spec.new do |s|
install_modules_dependencies(s)
- s.dependency 'OneSignalXCFramework', '5.5.1'
+ s.dependency 'OneSignalXCFramework', '5.5.2'
end