Repository navigation
Releases: tapayadot/accept-android
Releases · tapayadot/accept-android
Release list
Accept SDK 1.16.0
[1.16.0] - 2026-09-30
Added
AcceptPlugin.updateInfo()answers from the backend's release metadata, unauthenticated,
against the installed package, so it works with no store and with the plugin absent. A
Play-installed plugin is still measured against Play, since a release reaches the backend while
the same build can sit in review; the plugin's own check stays the fallback.- accept-installer: new optional artifact,
com.tapaya:accept-installer. On a storeless device
AcceptPlugin.install()downloads the APK and installs it through the system installer.
Depending on the artifact is the opt-in — it carriesREQUEST_INSTALL_PACKAGES, which Play
requires integrators to declare, and:acceptnever asks for it. The APK is verified
against its SHA-256, declared package and version code, a pinned signer, and the installed
plugin's own signer before anything is committed. PluginStoreUnavailable,PluginSelfInstallUnavailable,PluginInstallPermissionRequired,
PluginInstallAuthRequiredandPluginDownloadNotPermittederrors from
AcceptPlugin.install()— no store, no installer artifact, no "Install unknown apps" grant, no
merchant session, or a merchant the backend does not allow the APK. The last is an entitlement
decision rather than anything retryable: point the merchant at their account manager or
developers@tapaya.com.
Changed
AcceptPlugin.install()no longer always opens a store listing: with no store it takes the
download path above, which needs an authenticated merchant and says so before the transfer
starts rather than after.
Fixed
Integration
implementation("com.tapaya:accept:1.16.0")Accept SDK 1.15.0
[1.15.0] - 2026-09-23
Added
Changed
Fixed
- Payments failed with
LocationUnavailableorLocationTimeouton terminals whosefused
provider reports itself present and enabled but never produces a fix. On API 31+ a live fix was
requested fromfusedalone, so a null or silent answer ended the request even whilenetwork
andgpswere enabled and working. A live fix now races every enabled provider at once and
takes the first to answer, failing only once all of them have answered without a location. The
OS last-known lookup that seeds the cache also coversfusedandpassivenow, so a cold start
more often avoids blocking at all.
Integration
implementation("com.tapaya:accept:1.15.0")Accept SDK 1.14.2
[1.14.2] - 2026-09-22
Added
Changed
- Payments no longer wait on a location fix. Every
pay()used to race a live fix against a
timeout before the payment could be created, so a terminal on a weak location stack paid that
latency on every transaction and reached its last-known fix only after the timeout had already
been spent. The most recent known fix is now served immediately, and is refreshed in the
background — off the payment path — once it is older than an hour. The cache is seeded from the
OS last-known location on a cold start, so only a terminal that has never held a fix blocks at
all, and that first wait is capped at 30 seconds. A terminal does not move between transactions,
so an hour-old fix describes its location as well as a fresh one. One consequence worth knowing:
a cached fix no longer has an upper age bound, so a terminal that has been offline for days
serves a days-old fix and refreshes afterwards.
Fixed
Integration
implementation("com.tapaya:accept:1.14.2")Accept SDK 1.14.1
[1.14.1] - 2026-09-22
Added
Changed
Fixed
- Payments on devices with a weak or non-GMS location stack failed with
LocationUnavailableeven
though the device held a usable fix. The fused provider returned nothing within
FRESH_FIX_TIMEOUT_MS, and the last-known fallback then rejected the only fix on the device
becauseMAX_CACHED_LOCATION_AGE_MSwas 2 minutes — on a stationary countertop terminal the last
fix is routinely tens of minutes old. The cached/last-known window is now 30 minutes, so the
fallback accepts the fixes it exists to accept. A terminal does not move between transactions, so
a half-hour-old fix describes its location as well as a fresh one; the fresh-fix attempt still
runs first and is still preferred when it succeeds.
Integration
implementation("com.tapaya:accept:1.14.1")Accept SDK 1.14.0
[1.14.0] - 2026-09-15
Added
Accept.setTheme()/getTheme()let host apps forward org branding (colors + logos) to the
companion app's activation, status, and payment screens.AcceptThememirrors the existing
org-theme wire format field-for-field, pushed to the plugin via thesetTheme()AIDL call and
aTHEME_JSONintent extra onPAY/ACTIVATE_TERMINAL/WARM_UP.setTheme()persists until
changed or cleared (null, orclear()) — it's session-wide branding, not a per-payment
override — and is safe to call before or afterinitialize().Accept.createLocalThemeImageUri()covers logos the host app has locally (e.g. picked from the
photo gallery) rather than hosted at a stable URL: writes the bytes to SDK-private storage and
returns acontent://URI the companion is granted read access to, usable anywhere
AcceptTheme's image fields take a URL.
Changed
Fixed
activateTerminal()now fails fast withMerchantOnboardingIncompletewhen the merchant hasn't
finished onboarding or its card payment method isn't ready, instead of proceeding to build the
intent and launch the plugin activity. The gate had been temporarily disabled while merchant
onboarding was being fixed on the backend; it's re-enabled now that the backend fix has shipped.- Plugin binder calls (bind/connect/AIDL call) now run on
Dispatchers.IOinstead of whatever
dispatcher the caller launched on. The cold-bind wait (up toBIND_TIMEOUT_MS) previously ran on
Main by default when called from a ViewModel'sviewModelScope.launch, freezing input dispatch
and risking an ANR.setTheme()is also markedoneway, so pushing a theme never waits on the
companion at all.
Integration
implementation("com.tapaya:accept:1.14.0")Accept SDK 1.13.0
[1.13.0] - 2026-09-10
Added
Changed
- A plugin bind that fails now says why.
PluginUnavailableused to be raised behind a single
plugin bind failedline, which reads identically whether the plugin is not installed, installed
but disabled, uninstalled-for-this-user with its data kept, or merely invisible because the host
app's merged manifest is missing the<queries>entry API 30+ package visibility requires. The
SDK now tells those four apart and logs the distinction to integrators, alongside the counts of
services that resolved with and without disabled components, the plugin's version and install
source, and which other environment's plugin build is on the device. A successful bind records
the same identity once, and again whenever it changes, so a later failure can be read against a
baseline instead of in isolation — a version skew and a plugin disabled after the fact no longer
look alike in a field report. Diagnostics only: no public type changed, andisInstalled()still
answers exactly what it did before, a disabled plugin included.
Fixed
- Every failed bind leaked a
ServiceConnection.bindService()registers the connection before
it asks the system to bind, so neither afalsereturn nor a thrownSecurityException
unregisters it, and the hostContextaccumulated one leaked connection per failure
(ServiceConnectionLeaked). Both paths now unbind. - A
SecurityExceptionfrombindService()— the plugin's service not exported to the host app,
or gated behind a permission it does not hold — propagated to the caller as-is instead of the
PluginUnavailablethe API documents. It is now caught, logged with its cause attached, and
reported asPluginUnavailable. - A plugin whose process died before it connected — killed, updated, or force-stopped mid-bind —
made the caller wait out the full bind timeout for a connection that was never coming. The
binding's death now fails the call immediately.
Integration
implementation("com.tapaya:accept:1.13.0")Accept SDK 1.12.0
[1.12.0] - 2026-09-08
Added
- The hosted receipt page's URL is now available from the payment flow itself, instead of only from
a laterPaymentStatuslookup.PaymentEvent.CreatedcarriesreceiptUrlalongside the payment
token — so the link is in hand before the plugin is even launched — andPayResult.Success/
PayResult.Declinedcarry it too, so a terminal result is self-contained. The URL resolves to the
finished receipt once the payment settles; the link itself is stable from creation. Both fields
are nullable and default tonull, so existing construction andcopy()calls keep compiling.
Changed
Fixed
Integration
implementation("com.tapaya:accept:1.12.0")Accept SDK 1.11.0
[1.11.0] - 2026-09-05
Added
NfcPositionConfig.ExternalReaderfor setups where the antenna is on a separate reader that is
not above the device — a counter reader, a side-mounted pinpad, a customer-facing dock. There is
no point on the device to place and no direction to point at, so the companion drops its tap
indicator entirely and shows the amount with a prompt underneath it instead. Its optional
messagereplaces the companion's own localized prompt for setups the default wording doesn't
describe; you own its localization, blank counts as unset, and the companion trims and clamps it.
Companion app 1.5.2 or newer is required — older builds treat the new mode as no override at all
and keep resolving antenna position themselves, so nothing breaks.
Changed
Fixed
Integration
implementation("com.tapaya:accept:1.11.0")Accept SDK 1.10.0
[1.10.0] - 2026-09-03
Added
AcceptPlugin.activateTerminal()now throwsNoTidsAvailableForMerchantwhen the merchant has
no unassigned terminal (TID) left to activate, instead of a genericUnknownerror.- Dual-sided ("double-sided") device support:
Accept.displays(all(),customerFacing(),
isDualScreen) reports the device's screens, and the newPaymentDisplayoption on
AcceptPayments.setOptions(display = ...)/pay(display = ...)runs the plugin's payment UI
on the customer-facing panel while the host app keeps the merchant one. A target that can't be
honored falls back to the default display, so single-screen behavior is unchanged. The terminal
warm-up fired byauthenticate()follows the same target. New:dualscreensample app shows
the full two-panel checkout.
Changed
PayHostActivitynow declares an emptytaskAffinity, so a payment always starts a fresh task
instead of stacking onto the host app's. Required for the cross-display launch above; on a
single-screen device the only visible difference is that the invisible host no longer joins the
host app's back stack.- The SDK's remote diagnostics now identify the device behind a log line: device id, brand, model,
OS version, and the host app's package name, plus a one-time record of the device's display
layout atinitialize(). Internal diagnostics only — nothing about the merchant's customers is
collected, and the sink stays off entirely in debug builds.
Fixed
Integration
implementation("com.tapaya:accept:1.10.0")Accept SDK 1.9.1
[1.9.1] - 2026-08-27
Fixed
- Location fixes now fall back to the OS's last-known location when a fresh fix times out or the
live request reports unavailable, instead of failing outright. On Android 11 (API 30),
LocationManager.getCurrentLocation()is no longer used — it's unreliable on that API level —
in favor of a one-shotrequestLocationUpdates()request. Also guards against duplicate/late
location callbacks and prefers the network provider before GPS.
Integration
implementation("com.tapaya:accept:1.9.1")