purchases-flutter icon indicating copy to clipboard operation
purchases-flutter copied to clipboard

Callback function of addCustomerInfoUpdateListener() is not called on hot restart in development or on restart after OOM kill in production

Open kaboc opened this issue 1 year ago • 8 comments

Environment

  • [x] Output of flutter doctor
    Doctor summary (to see all details, run flutter doctor -v):
    [√] Flutter (Channel stable, 3.24.3, on Microsoft Windows [Version 10.0.22631.4317], locale ja-JP)
    [√] Windows Version (Installed version of Windows is version 10 or higher)
    [√] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    [X] Chrome - develop for the web (Cannot find Chrome executable at .\Google\Chrome\Application\chrome.exe)
        ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.
    [√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.11.5)
    [!] Android Studio (not installed)
    [√] IntelliJ IDEA Ultimate Edition (version 2024.2)
    [√] VS Code (version 1.94.2)
    [√] Connected device (3 available)
    [√] Network resources
    
    ! Doctor found issues in 2 categories.
    
  • [x] Version of purchases-flutter
    • 8.1.6
  • [x] Testing device version e.g.: iOS 15.5, Android API 30, etc.
    • Android API 34
  • [x] How often the issue occurs- every one of your customers is impacted? Only in dev?
    • Only in dev
  • [x] Debug logs that reproduce the issue
    I/[Purchases] - INFO(31871): Purchases instance already set with the same configuration. Ignoring duplicate call.
    I/[Purchases] - INFO(31871): 😻💰 Purchase history retrieved skus: [xxxx], purchaseTime: 1729920583381, purchaseToken: xxxxxxxx
    
  • [x] Steps to reproduce, with a description of expected vs. actual behavior
    1. Place print('Some message.'); in the callback function of addCustomerInfoUpdateListener().
    2. Run the app.
    3. Check that the message is printed in the console.
    4. Hot restart the app.
    5. Check that the message is not printed.
      • Expected behaviour: The message is printed.

Other information (e.g. stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, etc.)

Describe the bug

The callback function of addCustomerInfoUpdateListener() used to be called both on app start and on hot restart. I have confirmed it with purchases_flutter 8.1.0. I upgraded the package to 8.1.6 today and found it is no longer called on hot restart.

Additional context

It is really inconvenient that I need to kill and rerun an app to avoid the issue in debugging.

It looks like the callback function is not called when restorePurchases() is executed after a hot restart either.

kaboc avatar Oct 26 '24 05:10 kaboc

👀 We've just linked this issue to our internal tracker and notified the team. Thank you for reporting, we're checking this out!

RCGitBot avatar Oct 26 '24 05:10 RCGitBot

Same issue here

alihuseyin avatar Oct 29 '24 11:10 alihuseyin

Facing same issue!

Even in prod, some users are reporting that they are not able to access the Premium features, which means that this callback is not getting triggered on initialization.

// Initialization code for EntitlementRepository
// ...

Purchases.addCustomerInfoUpdateListener((customerInfo) {
      debugPrint('loaded customer info for: ${customerInfo.originalAppUserId}');
      _customerInfo = customerInfo;
      _isEntitled = _customerInfo!.entitlements.all[premiumEntitlementKey]?.isActive ??
              false;
      debugPrint('isEntitled: $_isEntitled');
    });

amitm29 avatar Nov 13 '24 06:11 amitm29

Even in prod, some users are reporting that they are not able to access the Premium features, which means that this callback is not getting triggered on initialization.

It is very likely to be true. It can be simulated with the following steps.

  1. Enable this setting: Settings > Developer options > Don't keep activities
  2. Open your app and see the callback is called on app launch
  3. Send the app to the background
  4. Bring the app back to the foreground

At the point of 4 above, the app behaves like it has restarted. However, because the callback is not called this time, the app cannot get the purchase information. A user with a valid subscription is treated as a free plan user.

I need to avoid using the package versions with this bug for production. The latest version 8.2.1 still has the issue.

kaboc avatar Nov 20 '24 06:11 kaboc

Hi all,

In a hot reload, the SDK remains configured so a new customer info is not sent.

However, the flutter side caches are lost. In flutter, we cache the last customer info to send to the listener when a new listener is added, but that cached customer info is lost upon the hot reload so it won't call the new listener here.

We're looking into the best way to fix this in the SDK, and will keep you updated.

rglanz-rc avatar Dec 03 '24 17:12 rglanz-rc

My current workaround is to avoid relying solely on the listener and manually use Purchases.getCustomerInfo() together.

var wasListenerCalled = false;

Purchases.addCustomerInfoUpdateListener((info) {
  wasListenerCalled = true;
  _someHandler(customerInfo: info);
});

if (!wasListenerCalled) {
  // getCustomerInfo() works fine even if the callback was not called
  // on registration above due to the bug.
  final info = await Purchases.getCustomerInfo();
  _someHandler(customerInfo: info);
}

It seems the listener of addCustomerInfoUpdateListener() is not called immediately on registration when the app restarts after being killed, but it is called on later events (e.g. a purchase).

kaboc avatar Dec 27 '24 10:12 kaboc

Same happening here

javiermrz avatar May 14 '25 16:05 javiermrz

i have the same issue, the listener is not working

rymesaint avatar Oct 06 '25 02:10 rymesaint