Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions OneSignalSDK/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ buildscript {
// AndroidX Lifecycle and Activity versions
lifecycleVersion = '2.6.2'
activityVersion = '1.7.2'
startupVersion = '1.1.1'
ktlintVersion = '0.50.0' // Used by Spotless for Kotlin formatting (compatible with Kotlin 1.7.10)
spotlessVersion = '6.25.0'
tdunningJsonForTest = '1.0' // DO NOT upgrade for tests, using an old version so it matches AOSP
Expand Down
3 changes: 3 additions & 0 deletions OneSignalSDK/onesignal/core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion"
implementation "androidx.activity:activity-ktx:$activityVersion"

// Registers activity lifecycle observation at process start (see ActivityLifecycleInitializer)
implementation "androidx.startup:startup-runtime:$startupVersion"

compileOnly('com.amazon.device:amazon-appstore-sdk:[3.0.1, 3.0.99]')

api('androidx.appcompat:appcompat') {
Expand Down
13 changes: 13 additions & 0 deletions OneSignalSDK/onesignal/core/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@
<activity android:name="com.onesignal.core.activities.PermissionsActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:exported="false" />

<!-- Observe the activity lifecycle from process start so late SDK init (wrapper SDKs)
still sees the first activity's full lifecycle. Merges into the app's androidx.startup
provider; hosts that disable it fall back to lifecycle registration at init time. -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="com.onesignal.core.internal.application.impl.ActivityLifecycleInitializer"
android:value="androidx.startup" />
</provider>
</application>

<!-- NOTE: See release version for tags with placeholders -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ internal class CoreModule : IModule {
.provides<IStartableService>()
builder.register<HttpConnectionFactory>().provides<IHttpConnectionFactory>()
builder.register<HttpClient>().provides<IHttpClient>()
builder.register<ApplicationService>().provides<IApplicationService>()
// Reuse the process-wide instance shared with ActivityLifecycleInitializer (so the activity
// lifecycle observed before SDK init is visible) when the startup initializer ran; otherwise
// create a fresh instance for this init.
builder.register { ApplicationService.getInstanceOrNull() ?: ApplicationService() }
.provides<IApplicationService>()
builder.register<DeviceService>().provides<IDeviceService>()
builder.register<Time>().provides<ITime>()
builder.register<DatabaseProvider>().provides<IDatabaseProvider>()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.onesignal.core.internal.application

/**
* Marker for SDK-internal, transient activities (such as the notification-open trampolines) that
* must be excluded from app focus / foreground tracking.
*
* These activities are launched by the SDK itself, often before the host app's real activity
* resumes, and they finish immediately after handling their intent. Counting them toward focus
* would prematurely toggle [IApplicationService.isInForeground] / entry state and corrupt the
* activity reference count once the SDK observes the full activity lifecycle from process start.
*/
interface OneSignalInternalActivity
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.onesignal.core.internal.application.impl

import android.app.Application
import android.content.Context
import androidx.startup.Initializer
import com.onesignal.core.internal.application.IApplicationService

/**
* Registers activity lifecycle observation at process start via androidx.startup, before the host
* app initializes the SDK.
*
* Wrapper SDKs (Flutter/React Native/Capacitor/etc.) call `initWithContext` late — after the first
* activity has already been created/started/resumed — so observing the lifecycle only from `start`
* misses those early callbacks. Registering here lets [ApplicationService] see the first activity's
* full lifecycle regardless of when init later happens.
*
* This intentionally does NOT initialize the SDK or require an App ID; it only attaches lifecycle
* observation. App ID / consent gating remains in the runtime `initWithContext` path.
*/
class ActivityLifecycleInitializer : Initializer<IApplicationService> {
override fun create(context: Context): IApplicationService {
val applicationService = ApplicationService.getInstance()
(context.applicationContext as? Application)?.let { application ->
applicationService.attachToApplication(application)
}
return applicationService
}

override fun dependencies(): List<Class<out Initializer<*>>> = emptyList()
}
Loading
Loading