Reverse Activity Trampolining Implementation#1377
Conversation
* This commit contains the working implementation for Reverse Activity Trampolining Implementation. - Other considerations such as outcomes will be done in a follow up commit as part of this PR. * From a high level we are moving the logic of "should we open the app" to notification generation time instead of at click time. * The way this is being done is deciding if we want to display two Activities (OneSignal's invisible click tracking + app's launcher) or just OneSignal's Activity. * Comments added to the code in this commit go into more details.
* Shorter name and flips the logic to make it easier to read.
* Putting the GenerateNotificationOpenIntent class added a previous commit to use. * Removed getNewBaseIntent & getNewActionPendingIntent from GenerateNotification.java as it was moved to GenerateNotificationOpenIntent
* Moved these tests to GenerateNotificationRunner to match the source logic changes.
* Split logic from GenerateNotificationOpenIntentFromPushPayload into OSNotificationOpenBehaviorFromPushPayload so this can be used independly in a follow up commit
* Added this logic back as some app developers may set them from the notification opened callback. - The fallback implemention of waiting for the app resume event doesn't catch this case.
* This logic was moved tot the notification generation as is already covered by tests there.
* Renamed to getShouldOpenActivity as getOpenApp was incorrectly describing the behavior * Fixed usage of startApp * Added getShouldOpenActivity usage to uri
088cfb0 to
bba36be
Compare
* FIxed issue where summary notification did not update with all data from the payload when a child notification is removed.
emawby
left a comment
There was a problem hiding this comment.
Reviewed 6 of 14 files at r2.
Reviewable status: 6 of 14 files reviewed, 2 unresolved discussions (waiting on @jkasten2 and @nan-li)
OneSignalSDK/onesignal/src/main/java/com/onesignal/GenerateNotificationOpenIntent.kt, line 77 at r2 (raw file):
) // Launch desired Activity we want the user to be take to the followed by
Lets clarify this comment
OneSignalSDK/onesignal/src/main/java/com/onesignal/OSNotificationOpenBehaviorFromPushPayload.kt, line 15 at r2 (raw file):
if (!OSNotificationOpenAppSettings.getShouldOpenActivity(context)) return false if (uri != null) return false return true
Does the following work for this:
(OSNotificationOpenAppSettings.getShouldOpenActivity(context) && uri == null)
jkasten2
left a comment
There was a problem hiding this comment.
Reviewable status: 6 of 14 files reviewed, 2 unresolved discussions (waiting on @emawby and @nan-li)
OneSignalSDK/onesignal/src/main/java/com/onesignal/GenerateNotificationOpenIntent.kt, line 77 at r2 (raw file):
Previously, emawby (Elliot Mawby) wrote…
Lets clarify this comment
Wrote this comment section to so should be more clear now.
OneSignalSDK/onesignal/src/main/java/com/onesignal/OSNotificationOpenBehaviorFromPushPayload.kt, line 15 at r2 (raw file):
Previously, emawby (Elliot Mawby) wrote…
if (!OSNotificationOpenAppSettings.getShouldOpenActivity(context)) return false if (uri != null) return false return trueDoes the following work for this:
(OSNotificationOpenAppSettings.getShouldOpenActivity(context) && uri == null)
Yes! That makes this a lot easier to read. Done
emawby
left a comment
There was a problem hiding this comment.
Reviewable status: 6 of 14 files reviewed, all discussions resolved (waiting on @nan-li)
Description
One Line Summary
Moved the logic of "should we open the app" from on notification tapped time to notification generation time.
Details
Pre-existing code & Android 12 restrictions
This PR focuses on providing as direct as possible path from notification open to showing the user an Activity. This change was inspired by the Notification trampoline restrictions in Android 12 which to quote this Google page was done to "To improve app performance and UX ...".
Technically the OneSignal-Android-SDK 4.0.0 and newer already meets the requirements as the notification open is starting an
Activity. However this is an invisibleActivitythat conditionally shows another visible Activity after some runtime processing, which in spirit is basically the same asBroadcastorServiceGoogle is trying to prevent here.Limited Android Notification API
OneSignal starts an invisible Activity (NotificationOpenedReceiver) so it can know the user opened the notifications to provide click counts, outcomes, etc on it. This is done so this is automatic and requires zero extra code / configuration by the app developer. Android does not provide a way to attach both an Activity and a background job (Broadcast, Service, etc) to support this without some kind of trampolining.
Solution implemented - Reverse Activity Trampolining
As noted above, Android does not allow attaching both an
Activityand a backgroundIntent, however it does provide an API to attach multiple Activities withPendingIntent.getActivities. This means we can have Android Launch both our invisibleNotificationOpenedReceiverActivity to track the even while also attaching the visible Activity the app developer wants the user to be shown. You can call this Reverse Activity Trampolining as the OneSignal tracking Activity will be created first but as soon as it is finished Android show the next one in the back stack automatically, hence reverse in the name.Changes
OSNotificationOpenAppSettings- New class to read global settings for how notification opens behave.OSNotificationOpenBehaviorFromPushPayload- Based on the notification payload andOSNotificationOpenAppSettingsdetermine if the notification should open the app or not or if it should open a URL.GenerateNotificationOpenIntent- This logic was moved fromGenerateNotification.javaand has additions to support Reverse Activity Trampolining.GenerateNotificationOpenIntentFromPushPayload- This usesOSNotificationOpenBehaviorFromPushPayloadto create aGenerateNotificationOpenIntentinstance. This gets consumed byGenerateNotification.java.OneSignal.java- ThestartActivitylogic has been pulled out since it has been moved to notification generation time.Fixes
Future
Interduce a OneSignal API to the OneSignal
NotificationServiceExtensionto allow setting anActivityIntentto control which Activity is shown directly at the notification generation time.Today if the developer does not want to first show their launcher Activity they have to set
"com.onesignal.NotificationOpened.DEFAULT"in theirAndroidManifest.xmland then usestartActivityfrom the OneSignal notification open event. Basically the benefits from this PR can't be used when the developer needs to make this customization until OneSignal adds this feature.This change is