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 with ACTION_VIEW, and the close event fires when the launching activity resumes.
  • A keepOpen browser 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 openBrowser with onBrowserDismissed.

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.