Implements queue mechanism (in Kotlin) for handling and displaying in-app messages and actions.
Exposes additional handlers which can be used by developers to decide ad-hoc which messages to be displayed, delayed or discarded. Adds callbacks for display, dismiss, action run.
Implementation
Code is organised in two packages:
com.leanplum.actions - Contains the API for clients to interact with the queue mechanism, described in Client interface paragraph.
com.leanplum.actions.internal - Contains implementation of the queue mechanism. Code is separated in several classes, containing extension methods for the old com.leanplum.internal.ActionManager:
ActionManagerDefinition - Contains the predefined templates and all custom client templates for the actions.
ActionManagerModel - Contains the model objects for the actions queue.
ActionManagerTriggering - Contains the triggering functionality that append to queue based on priority.
ActionManagerExecution - Contains the most important method performActions() that cycles over the queue and pops actions for execution.
Client interface
Client accessible interfaces are located in the com.leanplum.actions package:
LeanplumActions - Main point for interaction. Contains all available points for configuration. Check javadoc for more details:
MessageDisplayController - Interface to provide queue functionality on how to process the messages. Has two methods:
shouldDisplayMessage - Decide whether to show/discard/delay a message.
prioritizeMessages - Decide in which order and which of the messages to be presented.
MessageDisplayListener - Interface to receive callback information when a given message is processed. Has three methods with descriptive names and javadoc:
onMessageDisplayed
onMessageDismissed
onActionExecuted
Breaking changes !!!
Leanplum.defineAction
The parameter ActionCallback responder was replaced by ActionCallback presentHandler parameter and ActionCallback dismissHandler parameter.
presentHandler parameter is the same as the old responder parameter
dismissHandler parameter - By default if you have an inapp message presented it would be dismissed if you click on a push notification with open action, which is another inapp. In response to that request the dismissHandler will be invoked to close the inapp message. This behaviour can be changed using LeanplumActions.setDismissOnPushOpened(false). In that case the open action from the push notification will go into the queue instead of immediate presentation.
MessageTemplate.java
Interface is used for easier registration of the actions/templates.
Removed methods:
handleAction(ActionContext) - replaced by present(ActionContext)
waitFilesAndVariables() - not needed any more
New methods:
present(ActionContext) - the same as the previous handleAction(ActionContet), except you need to return boolean value representing the outcome of message handling. If you executed the action return true, otherwise return false.
dismiss(ActionContext) - By default if you have an inapp message presented it would be dismissed if you click on a push notification with open action, which is another inapp. In response to that request the dismiss(ActionContext) method will be invoked to close the inapp message and you must return a boolean value representing the outcome of the request, i.e. if the inapp is dismissed return true, otherwise false. This behaviour can be changed using LeanplumActions.setDismissOnPushOpened(false). In that case the open action from the push notification will go into the queue instead of immediate presentation.
Testing steps
Testing of functionality
Throughout the implementation process a lot of functionalities has been tested including and not limited to:
Multiple inapp messages - different scenarios with multiple inapp messages shown on the same event, on different events, containing chained actions
Open push notification - Opening push notification with open action inapp when another inapp is already presented:
Android 11
Android 12
Huawei
Xiaomi
Using legacy Messaging in Leanplum Dashboard
Using single message campaigns
Using multi-message campaigns
Using the Don't keep activities setting from Developer options
Inbox read action
Triggering action before any activity is presented
Defer messages for activities -> removed from source code. Replaced by MessageDisplayController.
Recording of message impressions
Local caps
Local push notifications
Rotation of screen - works as before, i.e. dismissing the message
Preview of inapp and push from dashboard
Sync of templates from device
Testing of new interfaces
LeanplumActions
MessageDisplayController
MessageDisplayListener
Known Issues
Opening push notification while other inapp is presented
There is a change that prevents leaking of Dialog objects when switching activities. Read the commit's message for more details and check the following case:
If you have inapp M1 presented, M2 waiting in the queue, and a push P1 comes with payload M3. What will happen on a P1 click is first M1 dismisses, because activity changes (depends on implementation), next M2 is presented, but the M3 from payload is added with higher priority, so M2 is dismissed too and only M3 is presented. If you have a third inapp it will remain in the queue and will present after M3.
Background
Implements queue mechanism (in Kotlin) for handling and displaying in-app messages and actions. Exposes additional handlers which can be used by developers to decide ad-hoc which messages to be displayed, delayed or discarded. Adds callbacks for display, dismiss, action run.
Implementation
Code is organised in two packages:
com.leanplum.actions
- Contains the API for clients to interact with the queue mechanism, described in Client interface paragraph.com.leanplum.actions.internal
- Contains implementation of the queue mechanism. Code is separated in several classes, containing extension methods for the oldcom.leanplum.internal.ActionManager
:ActionManagerDefinition
- Contains the predefined templates and all custom client templates for the actions.ActionManagerModel
- Contains the model objects for the actions queue.ActionManagerTriggering
- Contains the triggering functionality that append to queue based on priority.ActionManagerExecution
- Contains the most important methodperformActions()
that cycles over the queue and pops actions for execution.Client interface
Client accessible interfaces are located in the
com.leanplum.actions
package:LeanplumActions
- Main point for interaction. Contains all available points for configuration. Check javadoc for more details:setDismissOnPushOpened(Boolean)
setContinueOnActivityResumed(Boolean)
setMessageDisplayController(MessageDisplayController)
setMessageDisplayListener(MessageDisplayListener)
triggerDelayedMessages()
setQueuePaused(Boolean)
setQueueEnabled(Boolean)
MessageDisplayController
- Interface to provide queue functionality on how to process the messages. Has two methods:shouldDisplayMessage
- Decide whether to show/discard/delay a message.prioritizeMessages
- Decide in which order and which of the messages to be presented.MessageDisplayListener
- Interface to receive callback information when a given message is processed. Has three methods with descriptive names and javadoc:onMessageDisplayed
onMessageDismissed
onActionExecuted
Breaking changes !!!
Leanplum.defineAction
The parameter
ActionCallback responder
was replaced byActionCallback presentHandler
parameter andActionCallback dismissHandler
parameter.presentHandler
parameter is the same as the oldresponder
parameterdismissHandler
parameter - By default if you have an inapp message presented it would be dismissed if you click on a push notification with open action, which is another inapp. In response to that request thedismissHandler
will be invoked to close the inapp message. This behaviour can be changed usingLeanplumActions.setDismissOnPushOpened(false)
. In that case the open action from the push notification will go into the queue instead of immediate presentation.MessageTemplate.java
Interface is used for easier registration of the actions/templates.
Removed methods:
handleAction(ActionContext)
- replaced bypresent(ActionContext)
waitFilesAndVariables()
- not needed any moreNew methods:
present(ActionContext)
- the same as the previoushandleAction(ActionContet)
, except you need to return boolean value representing the outcome of message handling. If you executed the action return true, otherwise return false.dismiss(ActionContext)
- By default if you have an inapp message presented it would be dismissed if you click on a push notification with open action, which is another inapp. In response to that request thedismiss(ActionContext)
method will be invoked to close the inapp message and you must return a boolean value representing the outcome of the request, i.e. if the inapp is dismissed return true, otherwise false. This behaviour can be changed usingLeanplumActions.setDismissOnPushOpened(false)
. In that case the open action from the push notification will go into the queue instead of immediate presentation.Testing steps
Testing of functionality
Throughout the implementation process a lot of functionalities has been tested including and not limited to:
Testing of new interfaces
LeanplumActions
MessageDisplayController
MessageDisplayListener
Known Issues
Opening push notification while other inapp is presented
There is a change that prevents leaking of Dialog objects when switching activities. Read the commit's message for more details and check the following case:
If you have inapp M1 presented, M2 waiting in the queue, and a push P1 comes with payload M3. What will happen on a P1 click is first M1 dismisses, because activity changes (depends on implementation), next M2 is presented, but the M3 from payload is added with higher priority, so M2 is dismissed too and only M3 is presented. If you have a third inapp it will remain in the queue and will present after M3.
Other documentation
iOS's IAM Handlers PR. Internal document about Use Cases.
Is this change backwards-compatible?
Check Breaking changes paragraph for more details.