Overview
Encore.placement(id).show() returns a PresentationResult: the complete factual record of the presentation. It never throws, and it resolves exactly once. Three rules cover almost every integration:
- Invoke
show()from the right context. The call is safe from any thread or scope, but it needs a foreground Activity. The callback form is always delivered on the main thread; the suspending form resumes in your caller’s context. - Results are values: await inline for control flow. Branch on the record where the call site already owns what happens next, or take the callback form when the call site isn’t a coroutine.
Encore.outcomesis for passive observers. Analytics, logging, and entitlement sync consume the stream instead of owning a call site.
Await the result
Use this when the place you callshow() from already owns the follow-up logic.
Basic example
From Compose
onClick is synchronous, so launch a coroutine on the lifecycle scope:
Callback form
Use this when the call site isn’t a coroutine and you don’t want to manage a scope. The callback is delivered exactly once, on the main thread:The outcomes stream
For observation that shouldn’t live at every call site, collectEncore.outcomes once, right after configure(). There is no replay, so subscribe at startup:
Platform-specific notes
show()never throws. Every failure is a value:NotPresented(reason), with errors carried asNotPresentedReason.Error. There is no need for a try/catch around anyshow()call.show()is safe to call from any thread or scope. The suspending form does its work on a background dispatcher and hops to Main internally. The callback form is always delivered on the main thread; the suspending form resumes in your caller’s context.- The no-arg overloads auto-resolve the current foreground Activity.
show(activity)andshow(activity) { result -> }are available when you need to bind to a specific one. Nothing in the foreground resolves toNotPresented(NoForegroundActivity). - Purchases run through your registered
EncorePurchaseController. There is no billing code path inside the SDK, so the awaited result’spublisheraxis is your own controller’s verdict reflected back. - JVM target: the SDK is built with JVM target 17. Your app must match (most modern Android Gradle plugins default to this).