Skip to content

[Bug]: Leak - com.onesignal.inAppMessages.internal.display.impl.OSWebView instance #2312

@qqhokamoto

Description

@qqhokamoto

What happened?

LeakCanary reports:
com.onesignal.inAppMessages.internal.display.impl.OSWebView instance is leaking (and that causes our activity leak)

Steps to reproduce?

1. install our app 
2. our app starts com.xxx.AaaActivity
3. InAppMessage dialog shows up
4. press Back button, and dismiss the InApp Message dialog.
5. our app calls startActivity to start com.xx.BbbActivity
6. com.xxx.AaaActivity is deleted (AaaActivity's onDestroy() fired)


We tried to OneSignal 5.1.34 & OneSignal 5.2.0-beta-03. Both versions reproduced the leak.

What did you expect to happen?

PROBLEM:
As shown in the log out below , OSWebView is still keeping old context (that is destroyed com.xxx.AaaActivity) after com.xxx.AaaActivity is destroyed. That's why LeakCanary thinks AaaActivity is leaking.

FIX required by OneSignal-Android-SDK:
OneSignal-Android-SDK should listen to activity's onDestroy() event (ie. using registerActivityLifecycleCallbacks()), if the activity is destroyed, OneSignal-Android-SDK internal classes need to clear the activity.

OneSignal Android SDK version

5.1.1, 5.1.34, 5.2.0-beta-03

Android version

15, 14

Specific Android models

* Pixel 5 API 34
* Pixel 9 Pro

Relevant log output

====================================
HEAP ANALYSIS RESULT
====================================
1 APPLICATION LEAKS

References underlined with "~~~" are likely causes.
Learn more at https://squ.re/leaks.

318100 bytes retained by leaking objects
Signature: 735ff4135c3598eb5334ca41c037531f1f0e278e
┬───
│ GC Root: Thread object
│
├─ kotlin.concurrent.ThreadsKt$thread$thread$1 instance
│    Leaking: UNKNOWN
│    Retaining 725 B in 22 objects
│    Anonymous subclass of java.lang.Thread
│    Thread name: 'Thread-15'
│    ↓ ThreadsKt$thread$thread$1.$block~~~~~~
├─ com.onesignal.common.threading.ThreadUtilsKt$suspendifyOnThread$1 instance
│    Leaking: UNKNOWN
│    Retaining 16 B in 1 objects
│    Anonymous subclass of kotlin.jvm.internal.Lambda
│    ↓ ThreadUtilsKt$suspendifyOnThread$1.$block~~~~~~
├─ com.onesignal.inAppMessages.internal.InAppMessagesManager$start$1 instance
│    Leaking: UNKNOWN
│    Retaining 36 B in 1 objects
│    Anonymous subclass of kotlin.coroutines.jvm.internal.SuspendLambda
│    ↓ InAppMessagesManager$start$1.this$0~~~~~~
├─ com.onesignal.inAppMessages.internal.InAppMessagesManager instance
│    Leaking: UNKNOWN
│    Retaining 2.7 kB in 83 objects
│    ↓ InAppMessagesManager._displayer
│                           ~~~~~~~~~~
├─ com.onesignal.inAppMessages.internal.display.impl.InAppDisplayer instance
│    Leaking: UNKNOWN
│    Retaining 44 B in 1 objects
│    ↓ InAppDisplayer.lastInstance
│                     ~~~~~~~~~~~~
├─ com.onesignal.inAppMessages.internal.display.impl.WebViewManager instance
│    Leaking: UNKNOWN
│    Retaining 341.1 kB in 6426 objects
│    activity instance of com.xxx.BbbActivity with mDestroyed = false
│    ↓ WebViewManager.webView
│                     ~~~~~~~
├─ com.onesignal.inAppMessages.internal.display.impl.OSWebView instance
│    Leaking: YES (View.mContext references a destroyed activity)
│    Retaining 318.1 kB in 6282 objects
│    View not part of a window view hierarchy
│    View.mAttachInfo is null (view detached)
│    View.mWindowAttachCount = 3
│    mContext instance of com.xxx.AaaActivity with mDestroyed = true
│    ↓ View.mContext
╰→ com.xxx.AaaActivity instance
​     Leaking: YES (ObjectWatcher was watching this because com.xxx.AaaActivity received Activity#onDestroy() callback and Activity#mDestroyed is true)
​     Retaining 298.8 kB in 5999 objects
​     key = 2ed55828-bd7f-4d6c-8651-af97bd136973
​     watchDurationMillis = 5489
​     retainedDurationMillis = 489
​     mApplication instance of com.xxx.AaaApplication
​     mBase instance of androidx.appcompat.view.ContextThemeWrapper
====================================
0 LIBRARY LEAKS

A Library Leak is a leak caused by a known bug in 3rd party code that you do not have control over.
See https://square.github.io/leakcanary/fundamentals-how-leakcanary-works/#4-categorizing-leaks
====================================
0 UNREACHABLE OBJECTS

An unreachable object is still in memory but LeakCanary could not find a strong reference path
from GC roots.
====================================
METADATA

Please include this in bug reports and Stack Overflow questions.

Build.VERSION.SDK_INT: 34
Build.MANUFACTURER: Google
LeakCanary version: 2.14
App process name: com.xxx.xxx
Class count: 36599
Instance count: 312242
Primitive array count: 181494
Object array count: 45239
Thread count: 105
Heap total bytes: 38031273
Bitmap count: 7
Bitmap total bytes: 9347151
Large bitmap count: 0
Large bitmap total bytes: 0
Db 1: open /data/user/0/com.xxx.xxx/databases/com.google.android.datatransport.events
Db 2: open /data/user/0/com.xxx.xxx/databases/OneSignal.db
Db 3: open /data/user/0/com.xxx.xxx/no_backup/androidx.work.workdb
Stats: LruCache[maxSize=3000,hits=137875,misses=274188,hitRate=33%]
RandomAccess[bytes=13658785,reads=274188,travel=105887886511,range=48387967,size=56337261]
Heap dump reason: 10 retained objects, app is visible
Analysis duration: 9541 ms
Heap dump file path: /storage/emulated/0/Download/leakcanary-com.xxx.xxx/2025-06-05_10-19-01_217.
hprof
Heap dump timestamp: 1749133153563
Heap dump duration: 1119 ms
====================================

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions