Troubleshooting
initialize()’s completion resolved false
Not an exception — initialize() never throws. A false completion means the API key couldn’t
be resolved: no app.onesygnal.API_KEY <meta-data> entry in AndroidManifest.xml, and no
prior setApiKey() call, or the key resolved to a blank string. Fix the manifest entry or call
setApiKey() before initialize() — calling it after is a silent no-op, since the key is
only read once, at initialize() time.
initialize() resolved true but I don’t think config actually loaded
initialize() can succeed even if the config-fetch network call fails. refreshConfig() only
short-circuits (and marks initialization as failed) if the server explicitly reports the project
inactive; a network failure just means configManager.fetch() returns null, which is treated
as “nothing to apply” rather than an error. The SDK falls back to whatever’s cached, or to
built-in defaults (SdkSettings()’s 1440min cooldown / 3-per-day cap / 30min session timeout) if
there’s no cache either. This isn’t a bug: it lets the SDK still track events and run cached
surveys offline.
Surveys never trigger, ready never fires, but initialize() didn’t obviously fail
Any uncaught Throwable inside backgroundInit() (e.g. a NetworkOnMainThreadException, which
would only happen if internal dispatcher wiring were broken) is swallowed silently, and:
- the completion resolves
false readynever firesnativeTriggerCheckstaysnullfor the rest of the process’s life, so every subsequent trigger check short-circuits — no survey will ever show, even ones that would otherwise match, until you restart the process and callinitialize()again.
A survey should have triggered but nothing rendered, and no event fired
insertSurveyOverlay() fails closed with no exception and no survey:dismissed event if there’s
no resumed Activity implementing the lifecycle owner interfaces the overlay’s ComposeView
needs. This typically means initialize() was called with a Context that isn’t (or wasn’t
recently) a resumed Activity — e.g. applicationContext instead of the calling Activity — so
CurrentActivityTracker has nothing to seed from. Pass the Activity itself to initialize(),
or ensure it happens after an Activity has resumed.
A survey disappeared immediately after showing, and survey:dismissed fired for a question I didn’t answer
This is the fail-closed path for an unsupported question type. The SDK logs
Survey suppressed: unsupported question type '<type>' via Log.w (unconditionally — this
still logs in a release build, since a published AAR’s BuildConfig.DEBUG is false), reports
the error internally, tears down the overlay, and emits survey:dismissed with that survey’s ID
so an integrator listening for dismissals still hears about it.
Missing native library crash risk (JS rules engine)
If quickjs-android’s native library (libquickjs.so) is missing or corrupt, loading it throws
UnsatisfiedLinkError — an Error, not an Exception. This is specifically caught (catch (_: Throwable), not catch (_: Exception)) around the rules-engine init step inside
backgroundInit(), so it’s non-fatal: initialize() still succeeds, but any survey whose
trigger rules require the JS rules engine (Stage 2) won’t evaluate those rules for the rest of
the session.
Calling initialize() a second time
OneSygnal is a singleton with a hard if (initialized) return guard. A second call’s
completion fires with true immediately, and nothing else runs — the API key, locale, and every
other setting from the first call stick. There’s no supported way to re-initialize with
different settings without restarting the process.