Android
A Java library for API 21 and later, package com.stash.stashnative. Source: Android.
Structure
flowchart TB
Game[Game activity] -->|open| Plugin[StashNativePlugin]
Plugin -->|starts| Activity[StashCardActivity]
Activity -->|in-app broadcast| Plugin
Plugin -->|listener| Game
StashNative forwards to StashNativePlugin, which tracks the session and calls the listener. Every card presentation runs in StashCardActivity, a non-exported activity in the game’s process. The activity reports events through package-local broadcasts tagged with the session ID. Events from an old session are dropped.
| Class | Responsibility |
|---|---|
StashNative | Public API |
StashNativePlugin | Session, listener, system browser, presentation options |
StashCardActivity | Hosts one card presentation |
StashPresentationController | Layout, insets, keyboard, folds, gestures |
StashCheckoutWebViewSupport | WebView setup, loading, errors |
StashCheckoutJsInterface | StashAndroid bridge |
StashNativeBrowserProxyActivity | Custom Tabs launch and close detection |
Layout
- Rotation, folding, and multi-window changes resize the activity in place.
- A separating fold splits the window; the card uses the larger pane.
- Panes narrower than 600 dp get a full-width card at the bottom. The card extends behind the navigation bar, and the WebView ends above it. Windows shorter than 600 dp, such as a phone in landscape, also get a bottom card, at the configured width and centered. Panes that are wide and tall get a centered floating card.
- Portrait is requested only in compact fullscreen windows. Back counts as a player dismissal.
WebView
- The bridge script is injected as each page starts and accepts calls from the top document only.
- File access, zoom, and algorithmic darkening are off.
- The first load waits for the final card size, so older WebViews render at the right scale.
- When checkout navigates to a hosted Klarna, PayPal, or Stripe page, a Return to checkout button reloads the original checkout. It is disabled while checkout is locked. iOS has no equivalent.
System browser
- Custom Tabs open through an internal proxy activity that detects when the tab closes. The game does not forward
onActivityResult. - Without
androidx.browser, links open withACTION_VIEW, and the close event fires when the launching activity resumes. - A
keepOpenbrowser opens from the card activity, in the game’s task.closeBrowser()and the keep-alive notification return to the card by finishing what lies above it, so the card and the game’s activities stay as they were. When the card ends first, it clears the browser the same way before finishing. - Keep-alive starts only after a browser opens. A failed launch ends a handoff or
openBrowserwithonBrowserDismissed.
Modules
- Each optional module is a separate AAR or Gradle module with its own dependencies and permissions.
- Module content runs in the same activity and card. The core loads it by reflection through a content contract.
- An open call for a missing module, or a module missing one of its libraries, reports an unavailable error without launching the card.