Skip to content

Commit 57462d2

Browse files
authored
fix: [SDK-4746] register Android click listener lazily to replay cold-start clicks (#881)
1 parent 75f43ae commit 57462d2

1 file changed

Lines changed: 54 additions & 3 deletions

File tree

com.onesignal.unity.android/Runtime/AndroidNotificationsManager.cs

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,61 @@ public AndroidNotificationsManager(AndroidJavaClass sdkClass)
4747
}
4848

4949
public event EventHandler<NotificationWillDisplayEventArgs> ForegroundWillDisplay;
50-
public event EventHandler<NotificationClickEventArgs> Clicked;
5150
public event EventHandler<NotificationPermissionChangedEventArgs> PermissionChanged;
5251

52+
// Only set the native listener once
53+
private bool _clickNativeListenerSet;
54+
55+
private readonly object _clickRegistrationLock = new object();
56+
57+
private EventHandler<NotificationClickEventArgs> _clicked;
58+
59+
/// <summary>
60+
/// The native click listener is registered lazily on the first subscription. The native SDK
61+
/// queues clicks that occur before a listener is added (e.g. a cold start from a notification
62+
/// tap) and replays them when one is registered, so deferring registration until a C# handler
63+
/// exists ensures those events are not dropped. The handler must be attached before the
64+
/// native call, since the replay fires as soon as the listener registers. The flag is only
65+
/// set after a successful native call so a transient failure can retry on the next
66+
/// subscription.
67+
/// </summary>
68+
public event EventHandler<NotificationClickEventArgs> Clicked
69+
{
70+
add
71+
{
72+
lock (_clickRegistrationLock)
73+
{
74+
_clicked += value;
75+
76+
if (!_clickNativeListenerSet)
77+
{
78+
try
79+
{
80+
_notifications.Call(
81+
"addClickListener",
82+
new InternalNotificationClickListener(this)
83+
);
84+
}
85+
catch
86+
{
87+
// Roll back so a failed subscription has no effect; retrying won't
88+
// add the same handler twice.
89+
_clicked -= value;
90+
throw;
91+
}
92+
_clickNativeListenerSet = true;
93+
}
94+
}
95+
}
96+
remove
97+
{
98+
lock (_clickRegistrationLock)
99+
{
100+
_clicked -= value;
101+
}
102+
}
103+
}
104+
53105
public bool Permission
54106
{
55107
get => _notifications.Call<bool>("getPermission");
@@ -91,7 +143,6 @@ public void Initialize()
91143
"addForegroundLifecycleListener",
92144
new InternalNotificationLifecycleListener(this)
93145
);
94-
_notifications.Call("addClickListener", new InternalNotificationClickListener(this));
95146
}
96147

97148
private sealed class InternalPermissionObserver : OneSignalAwaitableAndroidJavaProxy<bool>
@@ -194,7 +245,7 @@ public void onClick(AndroidJavaObject clickEvent)
194245
result
195246
);
196247

197-
EventHandler<NotificationClickEventArgs> handler = _parent.Clicked;
248+
EventHandler<NotificationClickEventArgs> handler = _parent._clicked;
198249
if (handler != null)
199250
{
200251
UnityMainThreadDispatch.Post(state => handler(_parent, args));

0 commit comments

Comments
 (0)