Load and Show Plan¶
This section explains how to load and display a plan using the SDK.
Overview¶
- A plan is managed by a presenter created with
ExpoFpPlan.createPlanPresenter(...). - The presenter provides a
ViewviagetView(). It is a self-sizing host container that fills its parent (not aWebView).- In a View-based UI, attach the presenter to an
ExpoFpView. - In Jetpack Compose, host the View directly via
AndroidView.
- In a View-based UI, attach the presenter to an
- You can optionally provide additional parameters, a location provider, and a message listener.
Step 1. Initialize the SDK¶
Call ExpoFpPlan.initialize(context) once, usually in Application or the first Activity.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ExpoFpPlan.initialize(this)
}
Step 2. Minimal Example (View-based)¶
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ExpoFpPlan.initialize(this)
val presenter = ExpoFpPlan.createPlanPresenter(
planLink = ExpoFpLinkType.ExpoKey("demo")
)
val expoView = ExpoFpView(this).apply {
attachPresenter(presenter)
}
setContentView(expoView)
}
}
Step 3. Minimal Example (Jetpack Compose)¶
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
ExpoFpPlan.initialize(this)
val presenter = ExpoFpPlan.createPlanPresenter(
planLink = ExpoFpLinkType.ExpoKey("demo")
)
setContent {
AndroidView(
factory = { presenter.getView() },
modifier = Modifier.fillMaxSize()
)
}
}
}
Note:
getView()returns a self-sizing container that fills its parent, so you can host it directly inAndroidView. No manualFrameLayoutwrapping is needed.
Step 4. Advanced Initialization¶
You can customize the presenter by passing additional parameters, a location provider, and a message listener.
val expoKey = "YourExpoKey"
val additionalParams = listOf(ExpoFpPlanParameter.NoOverlay(true), ExpoFpPlanParameter.HideHeaderLogo(true))
val locationProvider: IExpoFpLocationProvider = YourLocationProvider()
val messageListener: IExpoFpPlanMessageListener = YourMessageListener()
val presenter = ExpoFpPlan.createPlanPresenter(
planLink = ExpoFpLinkType.ExpoKey(expoKey),
additionalParams = additionalParams,
locationProvider = locationProvider,
messageListener = messageListener
)
Presenter Lifetime¶
A non-preloaded presenter is disposed automatically when the LifecycleOwner of the view tree it is first shown in is destroyed. In a Fragment this is the Fragment's view lifecycle, which ends whenever the Fragment's view is destroyed, including when another screen covers it in the back stack. If the same presenter is shown again after that, its plan is gone.
When the presenter must outlive the view of its screen, turn automatic disposal off and dispose the presenter yourself once the plan is no longer needed. Until then the presenter keeps its plan in memory, as a preloaded plan does.
val presenter = ExpoFpPlan.createPlanPresenter(
planLink = ExpoFpLinkType.ExpoKey(expoKey),
isLifecycleAutoDisposeEnabled = false
)
// When the plan is no longer needed, for example in ViewModel.onCleared():
presenter.dispose()
dispose() has no effect for a preloaded plan, dispose it with ExpoFpPlan.preloader.disposePreloadedPlan().
Step 5. Links That Leave the Plan¶
A plan can contain links to other websites and apps, for example exhibitor websites, tel: and mailto: links, or directions between venues that continue in a maps app. The SDK applies the rules below to every navigation of the plan's main frame, so a tapped link opens outside the app instead of replacing the plan, and an app-specific link never leaves the plan on an error page. This policy is built in and has no public setting.
Stays in the plan (loaded by the WebView):
- Navigation within the plan's own host, including offline plans served from
https://localhost. - Navigation inside subframes, except the internal and local storage schemes listed under "Never opened".
- Server redirects. A link on the plan's host that redirects to another website is loaded in the plan; the redirect is treated as part of the page load, not as a new tap.
- Form submissions to another website with a method other than GET, because a browser could not receive the submitted data.
- Web navigation that is not started by a user tap, such as a script changing
location.hrefto another website.
Opens outside the app, only after a user tap:
- Links to other websites open in the browser or in the app that handles that website, for example Google Maps for a
https://www.google.com/maps/...link. If no app can open the link, it is loaded in the plan. - App-specific links open in the app that handles them:
tel:,mailto:,sms:,geo:,market:,intent:and vendor schemes such aswhatsapp:. Whenever anintent:link does not open an app, because the app is not installed or because the link was not allowed, itsbrowser_fallback_urlis opened as a plain web link, provided it is anhttporhttpsURL. If no app can open the link, nothing happens and the plan stays.
Never opened:
- App-specific links without a user tap (main frame).
- App-specific links that would open your own app (main frame): an
intent:link that names your package, and anyintent:link or app-specific scheme that resolves to one of your activities. Plan content cannot trigger your deep links this way. Plainhttp/httpslinks to your app links domain, including thebrowser_fallback_urlof a blockedintent:link, are the exception and behave as they would from a browser. - Internal WebView protocols and local storage schemes (
ws,wss,filesystem,view-source,android-app,file,content,chrome), in the main frame and in subframes. A tappedintent:link whose data uses one of these schemes is not opened either.
App-specific links that were blocked or not opened are logged with tag WKWebViewClient at warning level, so adb logcat -s WKWebViewClient:W shows that an app-specific navigation was dropped and which scheme it had. The log carries the scheme only, and it does not distinguish a missing app from a link that was not allowed to open your own app. A website link that no app could open is loaded in the plan without a log entry.