From 8a633335aa7b6386a1eaa8ee67803729f334bb4a Mon Sep 17 00:00:00 2001 From: Fadi George Date: Tue, 2 Jun 2026 19:25:53 -0700 Subject: [PATCH] fix: [SDK-4741] remove React Native lifecycle tracker Co-authored-by: Cursor --- android/build.gradle | 6 -- android/src/main/AndroidManifest.xml | 15 +--- .../ActivityLifecycleTracker.java | 72 ------------------- .../OneSignalInitializer.java | 37 ---------- .../rnonesignalandroid/RNOneSignal.java | 10 +-- 5 files changed, 2 insertions(+), 138 deletions(-) delete mode 100644 android/src/main/java/com/onesignal/rnonesignalandroid/ActivityLifecycleTracker.java delete mode 100644 android/src/main/java/com/onesignal/rnonesignalandroid/OneSignalInitializer.java diff --git a/android/build.gradle b/android/build.gradle index 7e32d134..1a5428b4 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -27,12 +27,6 @@ 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 // 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..b4311696 100644 --- a/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java +++ b/android/src/main/java/com/onesignal/rnonesignalandroid/RNOneSignal.java @@ -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(); }