Skip to content

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 View via getView(). It is a self-sizing host container that fills its parent (not a WebView).
    • In a View-based UI, attach the presenter to an ExpoFpView.
    • In Jetpack Compose, host the View directly via AndroidView.
  • 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 in AndroidView. No manual FrameLayout wrapping 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
)

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.href to 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 as whatsapp:. Whenever an intent: link does not open an app, because the app is not installed or because the link was not allowed, its browser_fallback_url is opened as a plain web link, provided it is an http or https URL. 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 any intent: link or app-specific scheme that resolves to one of your activities. Plan content cannot trigger your deep links this way. Plain http/https links to your app links domain, including the browser_fallback_url of a blocked intent: 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 tapped intent: 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.