Hello Amazon Appstore SDK team,
I am reporting what appears to be an SDK-internal listener registration regression in Amazon Appstore SDK 3.0.5 and later.
In a FlutterActivity-based Android app, PurchasingService.registerListener(applicationContext, listener) throws:
Resource already registered
After this exception, the PurchasingListener is not fully registered. In SDK 3.0.5 and later, subsequent calls to purchase() and getPurchaseUpdates() fail with:
You must register a PurchasingListener before invoking this operation
SDK 3.0.4 is the only tested version where the app can continue successfully, but log evidence suggests 3.0.4 may also throw the same internal resource-registration exception and then tolerate the partial registration state.
Environment:
-
App name: Beadwell
-
Package name:
com.beadwell.app -
Product ID:
parent_toolkit_lifetime -
Product type: one-time non-consumable / entitlement unlock
-
App type: Flutter Android app using
FlutterActivity -
Native bridge: Android/Kotlin wrapper around Amazon Appstore SDK IAP APIs
-
Android version tested: Android 13
-
Install source/signing: installed via Amazon Appstore / production signature
-
SDK versions tested: 3.0.4, 3.0.5, 3.0.6, 3.0.8, 3.0.9
Steps to reproduce:
-
Create a Flutter Android app using
FlutterActivity. -
Add Amazon Appstore SDK dependency
com.amazon.device:amazon-appstore-sdk:3.0.5or later. -
Register a
PurchasingListenerby calling:
PurchasingService.registerListener(applicationContext, listener) -
Call registration from an early lifecycle point. We tested:
-
ContentProvider.onCreate()withandroid:initOrder="1000" -
Application.onCreate() -
Activity.onCreate() -
deferred/lazy registration before first IAP call
-
-
Build, install via Amazon Appstore using production signing, and launch the app.
-
Observe logcat filtered to
AmazonIapPlugin,Kiwi,ResourceManagerImpl, andPurchasingService.
Expected behavior:
PurchasingService.registerListener() should complete without throwing when called once from the app process before any IAP operation.
After successful listener registration, calls to PurchasingService.purchase(), getPurchaseUpdates(), and product/entitlement APIs should function normally.
Actual behavior:
PurchasingService.registerListener() throws internally:
Resource already registered: z2.g@a22d1cf
at H1.b.a(SourceFile:87)
at x1.a.<init>(SourceFile:180)
at x1.a.b(SourceFile:24)
at X1.a.b(SourceFile:1)
Kiwi resource logs show the SDK creating/registering two instances of the same adapter/resource class during a single registerListener() call:
ResourceManagerImpl: Registering resource: z2.g@f26eca9
ResourceManagerImpl: Registering resource: L1.e@364722e
ResourceManagerImpl: Registering resource: z2.g@a22d1cf
The second z2.g registration throws Resource already registered.
After this exception, SDK 3.0.5+ rejects later IAP operations with:
You must register a PurchasingListener before invoking this operation
Version matrix:
| SDK version | Result | Notes |
|---|---|---|
| 3.0.4 | Works | Registration path appears to hit the same internal exception, but later purchase() and getPurchaseUpdates() still accept the partial state. |
| 3.0.5 | Fails | Same internal double-registration exception; later IAP calls reject the partial state. |
| 3.0.6 | Fails | Same stack trace/source line pattern as 3.0.5. |
| 3.0.8 | Fails | Same failure pattern. |
| 3.0.9 | Fails | Same failure pattern; internal adapter class name changed in logs, but behavior is equivalent. |
Isolation already performed:
-
Confirmed the app is not intentionally calling
registerListener()twice. -
Tested with only one app-side registration path enabled.
-
Disabled eager provider-based registration and tested Activity-only registration.
-
Tested earliest possible provider registration using
android:initOrder="1000". -
Tested Application, Activity, and deferred/lazy registration.
-
Failure occurs before product loading, purchase, restore, or entitlement checks.
-
The Flutter layer only affects lifecycle timing; the exception is thrown inside
PurchasingService.registerListener()/ Kiwi resource registration.
Current assessment:
The log evidence suggests PurchasingService.registerListener() internally creates/registers the same Kiwi adapter/resource class twice during a single call. Since the Kiwi ResourceManager appears to key resources by class/type, the second registration throws Resource already registered.
This appears to be SDK-internal behavior, not app-side duplicate listener registration.
Workaround:
Pinned to com.amazon.device:amazon-appstore-sdk:3.0.4.
This is not ideal because 3.0.4 is old and may eventually be deprecated or delisted.
Request:
-
Please confirm whether this is a known issue in Appstore SDK 3.0.5+.
-
Please confirm the recommended lifecycle point for
PurchasingService.registerListener()in FlutterActivity-based Android apps. -
Please investigate why
registerListener()appears to register the same Kiwi adapter/resource class twice during a single call. -
Please provide a supported workaround or fixed SDK version for FlutterActivity-based apps.
-
If SDK 3.0.4 is currently the only safe workaround, please confirm whether it remains supported for production apps.
I can provide full logcat files, Gradle dependency tree, Fire tablet model, Fire OS version, APK/AAB build details, and a minimal reproduction project if needed.