Listen Plan Events¶
Listen and respond to user interactions and runtime messages from a plan.
Overview¶
- Implement
IExpoFpPlanMessageListener
to receive event callbacks. - Assign the listener when creating the presenter (recommended) or later via
setMessageListener(...)
. - Callbacks are invoked on the main thread.
- The SDK does not retain your listener globally; manage its lifecycle in your UI/component.
Step 1. Implement a Listener¶
class YourListener : IExpoFpPlanMessageListener {
override fun bookmarkDidClick(
bookmark: ExpoFpResult<ExpoFpBookmark>,
from: ExpoFpLinkType
) {
// Handle bookmark click (success or error)
}
override fun boothDidClick(
boothEvent: ExpoFpResult<ExpoFpBoothClickEvent>,
from: ExpoFpLinkType
) { /* ... */ }
override fun categoryDidClick(
category: ExpoFpResult<ExpoFpCategory>,
from: ExpoFpLinkType
) { /* ... */ }
override fun currentFloorDidChange(
floor: ExpoFpResult<ExpoFpFloor>,
from: ExpoFpLinkType
) { /* ... */ }
override fun currentPositionDidChange(
position: ExpoFpResult<ExpoFpPosition>,
from: ExpoFpLinkType
) { /* ... */ }
override fun detailsDidClick(
details: ExpoFpResult<ExpoFpDetails?>,
from: ExpoFpLinkType
) { /* ... */ } // details may be null
override fun directionDidBuild(
direction: ExpoFpResult<ExpoFpDirection?>,
from: ExpoFpLinkType
) { /* ... */ } // direction may be null (reset)
override fun exhibitorCustomButtonDidClick(
buttonEvent: ExpoFpResult<ExpoFpCustomButtonEvent>,
from: ExpoFpLinkType
) { /* ... */ }
override fun visitedDidClick(
visitedEvent: ExpoFpResult<ExpoFpVisitedClickEvent>,
from: ExpoFpLinkType
) { /* ... */ }
// Debug-only (fires only in debug mode, see below)
override fun windowErrorDidReceive(
error: ExpoFpResult<ExpoFpWindowError>,
from: ExpoFpLinkType
) { /* ... */ }
override fun consoleMessageDidReceive(
message: ExpoFpResult<ExpoFpConsoleMessage>,
from: ExpoFpLinkType
) { /* ... */ }
}
Step 2. Attach the Listener¶
Recommended: set during presenter creation¶
val listener = YourListener()
val presenter = ExpoFpPlan.createPlanPresenter(
planLink = ExpoFpLinkType.ExpoKey("demo"),
messageListener = listener
)
Alternatively: set after creation¶
presenter.setMessageListener(YourListener())
// Later, to remove:
presenter.removeMessageListener()
Tip: Attaching the listener at creation ensures you do not miss early events during initial loading.
Step 3. Use in UI¶
View-based UI (Activity/Fragment)¶
class MainActivity : AppCompatActivity() {
private lateinit var presenter: IExpoFpPlanPresenter
private val listener = YourListener()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ExpoFpPlan.initialize(this)
presenter = ExpoFpPlan.createPlanPresenter(
planLink = ExpoFpLinkType.RawLink("https://demo.expofp.com"),
messageListener = listener
)
val expoView = ExpoFpView(this).apply { attachPresenter(presenter) }
setContentView(expoView)
}
override fun onDestroy() {
presenter.removeMessageListener()
super.onDestroy()
}
}
Jetpack Compose¶
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ExpoFpPlan.initialize(this)
val listener = YourListener()
val presenter = ExpoFpPlan.createPlanPresenter(
planLink = ExpoFpLinkType.RawLink("https://demo.expofp.com"),
messageListener = listener
)
setContent {
AndroidView(factory = { presenter.getView() })
}
}
}
Events Reference¶
Event (method) | Payload type | Notes |
---|---|---|
bookmarkDidClick(bookmark, from) |
ExpoFpResult<ExpoFpBookmark> |
User tapped a bookmark. |
boothDidClick(boothEvent, from) |
ExpoFpResult<ExpoFpBoothClickEvent> |
Booth pressed on the plan. |
categoryDidClick(category, from) |
ExpoFpResult<ExpoFpCategory> |
Category selected. |
currentFloorDidChange(floor, from) |
ExpoFpResult<ExpoFpFloor> |
Current floor changed. |
currentPositionDidChange(position, from) |
ExpoFpResult<ExpoFpPosition> |
Position updates (if location provider is active). |
detailsDidClick(details, from) |
ExpoFpResult<ExpoFpDetails?> |
Details selected/deselected. null means deselected. |
directionDidBuild(direction, from) |
ExpoFpResult<ExpoFpDirection?> |
Direction built or reset. null on reset. |
exhibitorCustomButtonDidClick(buttonEvent, from) |
ExpoFpResult<ExpoFpCustomButtonEvent> |
Custom button pressed. |
visitedDidClick(visitedEvent, from) |
ExpoFpResult<ExpoFpVisitedClickEvent> |
Visited pressed. |
windowErrorDidReceive(error, from) |
ExpoFpResult<ExpoFpWindowError> |
Debug only: JS window.onerror . |
consoleMessageDidReceive(message, from) |
ExpoFpResult<ExpoFpConsoleMessage> |
Debug only: Web console messages. |
About
ExpoFpResult<T>
Handle bothsuccess
anderror
branches. Do not assume success-only callbacks. Treat nullable payloads (T?
) accordingly.
Debug-only Events¶
These fire only if you enable debug mode before loading a plan.
// Enable debug mode (do this before creating/loading the presenter)
ExpoFpPlan.isDebugModeEnabled = true
- WebView
window.onerror
:windowErrorDidReceive(error, from)
→ExpoFpResult<ExpoFpWindowError>
- Web
console
messages:consoleMessageDidReceive(message, from)
→ExpoFpResult<ExpoFpConsoleMessage>
Note: Debug mode can slow down initialization and increase logging. Use it only in debug builds.
Best Practices¶
- Attach early: Provide
messageListener
increatePlanPresenter(...)
to capture early lifecycle events. - Main thread work: Keep callbacks lightweight; offload heavy work to background coroutines.
- Lifecycle ownership: Create and remove the listener with your screen/component lifecycle to prevent leaks.
- Null-aware handling: Some payloads can be
null
(e.g.,details
,direction
on reset). Check before use. - Error-aware handling: Always handle
ExpoFpResult
errors (network, parsing, etc.). - Debug mode: Enable only when troubleshooting. Disable in production.