Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IllegalArgumentException: width and height must be > 0 (Android) #1186

Open
9 of 11 tasks
hirosz opened this issue Oct 17, 2024 · 3 comments
Open
9 of 11 tasks

IllegalArgumentException: width and height must be > 0 (Android) #1186

hirosz opened this issue Oct 17, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@hirosz
Copy link

hirosz commented Oct 17, 2024

‼️ Required data ‼️

Do not remove any of the steps from the template below. If a step is not applicable to your issue, please leave that step empty.

There are a lot of things that can contribute to things not working. Having a very basic understanding of your environment will help us understand your issue faster!

Environment

  • Output of flutter doctor
    [✓] Flutter (Channel stable, 3.24.3, on macOS 14.6.1 23G93 darwin-arm64, locale pl-PL)
    [✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    [✓] Xcode - develop for iOS and macOS (Xcode 16.0)
    [✓] Chrome - develop for the web
    [!] Android Studio (version unknown)
    ✗ Unable to determine Android Studio version.
    [✓] VS Code (version 1.94.1)
    [✓] Connected device (5 available)
    [✓] Network resources
  • Version of purchases-flutter : 8.1.6
  • Testing device version e.g.: different versions of Android
  • How often the issue occurs- every one of your customers is impacted? Only in dev?
    It is in production version. Not all users
  • Debug logs that reproduce the issue
  • Steps to reproduce, with a description of expected vs. actual behavior
    Other information (e.g. stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, etc.)

Describe the bug

RevenueCat Paywall make sometimes error:

Exception java.lang.IllegalArgumentException: width and height must be > 0
  at android.graphics.Bitmap.createBitmap (Bitmap.java:1111)
  at android.graphics.Bitmap.createBitmap (Bitmap.java:1078)
  at android.graphics.Bitmap.createBitmap (Bitmap.java:1028)
  at android.graphics.Bitmap.createBitmap (Bitmap.java:989)
  at androidx.core.graphics.drawable.DrawableKt.toBitmap (Drawable.kt:1)
  at androidx.core.graphics.drawable.DrawableKt.toBitmap$default (Drawable.kt:1)
  at com.revenuecat.purchases.ui.revenuecatui.composables.IconImageKt.AppIcon (IconImage.kt:1)
  at com.revenuecat.purchases.ui.revenuecatui.composables.IconImageKt.IconImage-djqs-MU (IconImage.kt:1)
  at com.revenuecat.purchases.ui.revenuecatui.templates.Template2Kt.IconImage (Template2.kt:1)
  at com.revenuecat.purchases.ui.revenuecatui.templates.Template2Kt.Template2PortraitContent (Template2.kt:1)
  at com.revenuecat.purchases.ui.revenuecatui.templates.Template2Kt.Template2 (Template2.kt:1)
  at com.revenuecat.purchases.ui.revenuecatui.LoadingPaywallKt$LoadingPaywall$3$1.invoke (LoadingPaywall.kt:2)
  at com.revenuecat.purchases.ui.revenuecatui.LoadingPaywallKt$LoadingPaywall$3$1.invoke (LoadingPaywall.kt:1)
  at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke (ComposableLambdaImpl.java:1)
  at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke (ComposableLambdaImpl.java:1)
  at com.revenuecat.purchases.ui.revenuecatui.composables.DisableTouchesComposableKt.DisableTouchesComposable (DisableTouchesComposable.kt:1)
  at com.revenuecat.purchases.ui.revenuecatui.LoadingPaywallKt.LoadingPaywall (LoadingPaywall.kt:2)
  at com.revenuecat.purchases.ui.revenuecatui.LoadingPaywallKt.LoadingPaywall (LoadingPaywall.kt:1)
  at com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt$InternalPaywall$2$1.invoke (InternalPaywall.kt:2)
  at com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt$InternalPaywall$2$1.invoke (InternalPaywall.kt:1)
  at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke (ComposableLambdaImpl.java:1)
  at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke (ComposableLambdaImpl.java:2)
  at androidx.compose.animation.AnimatedVisibilityKt.AnimatedEnterExitImpl (AnimatedVisibility.kt:1)
  at androidx.compose.animation.AnimatedVisibilityKt.AnimatedVisibilityImpl (AnimatedVisibility.kt:1)
  at androidx.compose.animation.AnimatedVisibilityKt.AnimatedVisibility (AnimatedVisibility.kt:1)
  at com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt$InternalPaywall$2.invoke (InternalPaywall.kt:2)
  at com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt$InternalPaywall$2.invoke (InternalPaywall.kt:1)
  at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke (ComposableLambdaImpl.java:1)
  at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke (ComposableLambdaImpl.java:1)
  at com.revenuecat.purchases.ui.revenuecatui.fonts.PaywallThemeKt.PaywallTheme (PaywallTheme.kt:1)
  at com.revenuecat.purchases.ui.revenuecatui.InternalPaywallKt.InternalPaywall (InternalPaywall.kt:1)
  at com.revenuecat.purchases.ui.revenuecatui.PaywallKt.Paywall (Paywall.kt:1)
  at com.revenuecat.purchases.ui.revenuecatui.activity.PaywallActivity$onCreate$1$1$1.invoke (PaywallActivity.java:2)
  at com.revenuecat.purchases.ui.revenuecatui.activity.PaywallActivity$onCreate$1$1$1.invoke (PaywallActivity.java:1)
  at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke (ComposableLambdaImpl.java:1)
  at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke (ComposableLambdaImpl.java:2)
  at androidx.compose.material3.ScaffoldKt$ScaffoldLayoutWithMeasureFix$1$1$bodyContentPlaceables$1.invoke (Scaffold.kt:2)
  at androidx.compose.material3.ScaffoldKt$ScaffoldLayoutWithMeasureFix$1$1$bodyContentPlaceables$1.invoke (Scaffold.kt:1)
  at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke (ComposableLambdaImpl.java:1)
  at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke (ComposableLambdaImpl.java:1)
  at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$subcompose$3$1$1.invoke (LayoutNodeSubcompositionsState.java:2)
  at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$subcompose$3$1$1.invoke (LayoutNodeSubcompositionsState.java:1)
  at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke (ComposableLambdaImpl.java:1)
  at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke (ComposableLambdaImpl.java:1)
  at androidx.compose.runtime.ActualJvm_jvmKt.invokeComposable (ActualJvm_jvm.kt:1)
  at androidx.compose.runtime.ComposerImpl.doCompose (ComposerImpl.java:1)
  at androidx.compose.runtime.ComposerImpl.composeContent$runtime_release (ComposerImpl.java:1)
  at androidx.compose.runtime.CompositionImpl.composeContent (CompositionImpl.java:1)
  at androidx.compose.runtime.Recomposer.composeInitial$runtime_release (Recomposer.java:1)
  at androidx.compose.runtime.ComposerImpl$CompositionContextImpl.composeInitial$runtime_release (ComposerImpl.java:1)
  at androidx.compose.runtime.CompositionImpl.composeInitial (CompositionImpl.java:1)
  at androidx.compose.runtime.CompositionImpl.setContent (CompositionImpl.java:1)
  at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcomposeInto (LayoutNodeSubcompositionsState.java:1)
  at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose (LayoutNodeSubcompositionsState.java:1)
  at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose (LayoutNodeSubcompositionsState.java:1)
  at androidx.compose.ui.layout.LayoutNodeSubcompositionsState.subcompose (LayoutNodeSubcompositionsState.java:1)
  at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$Scope.subcompose (LayoutNodeSubcompositionsState.java:1)
  at androidx.compose.material3.ScaffoldKt$ScaffoldLayoutWithMeasureFix$1$1.invoke-0kLqBqw (Scaffold.kt:1)
  at androidx.compose.material3.ScaffoldKt$ScaffoldLayoutWithMeasureFix$1$1.invoke (Scaffold.kt:1)
  at androidx.compose.ui.layout.LayoutNodeSubcompositionsState$createMeasurePolicy$1.measure-3p2s80s (LayoutNodeSubcompositionsState.java:1)
  at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0 (InnerNodeCoordinator.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke (LayoutNodeLayoutDelegate.java:2)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.runtime.snapshots.Snapshot$Companion.observe (Snapshot.java:1)
  at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe (SnapshotStateObserver.java:1)
  at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads (SnapshotStateObserver.java:1)
  at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release (OwnerSnapshotObserver.java:1)
  at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release (OwnerSnapshotObserver.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0 (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0 (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0 (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0 (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.foundation.layout.BoxMeasurePolicy.measure-3p2s80s (BoxMeasurePolicy.java:1)
  at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0 (InnerNodeCoordinator.java:1)
  at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s (SimpleGraphicsLayerModifier.java:1)
  at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0 (LayoutModifierNodeCoordinator.java:1)
  at androidx.compose.ui.graphics.SimpleGraphicsLayerModifier.measure-3p2s80s (SimpleGraphicsLayerModifier.java:1)
  at androidx.compose.ui.node.LayoutModifierNodeCoordinator.measure-BRTryo0 (LayoutModifierNodeCoordinator.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke (LayoutNodeLayoutDelegate.java:2)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.runtime.snapshots.Snapshot$Companion.observe (Snapshot.java:1)
  at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe (SnapshotStateObserver.java:1)
  at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads (SnapshotStateObserver.java:1)
  at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release (OwnerSnapshotObserver.java:1)
  at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release (OwnerSnapshotObserver.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0 (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0 (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0 (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.measure-BRTryo0 (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.ui.layout.RootMeasurePolicy.measure-3p2s80s (RootMeasurePolicy.java:1)
  at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0 (InnerNodeCoordinator.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke (LayoutNodeLayoutDelegate.java:2)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.runtime.snapshots.Snapshot$Companion.observe (Snapshot.java:1)
  at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe (SnapshotStateObserver.java:1)
  at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads (SnapshotStateObserver.java:1)
  at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release (OwnerSnapshotObserver.java:1)
  at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release (OwnerSnapshotObserver.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0 (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0 (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0 (LayoutNodeLayoutDelegate.java:1)
  at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release (LayoutNode.java:1)
  at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA (MeasureAndLayoutDelegate.java:1)
  at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureOnly (MeasureAndLayoutDelegate.java:1)
  at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureOnly (MeasureAndLayoutDelegate.java:1)
  at androidx.compose.ui.platform.AndroidComposeView.onMeasure (AndroidComposeView.java:1)
  at android.view.View.measure (View.java:26535)
  at androidx.compose.ui.platform.AbstractComposeView.internalOnMeasure$ui_release (AbstractComposeView.java:1)
  at androidx.compose.ui.platform.AbstractComposeView.onMeasure (AbstractComposeView.java:1)
  at android.view.View.measure (View.java:26535)
  at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7109)
  at android.widget.FrameLayout.onMeasure (FrameLayout.java:194)
  at android.view.View.measure (View.java:26535)
  at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7109)
  at android.widget.LinearLayout.measureChildBeforeLayout (LinearLayout.java:1552)
  at android.widget.LinearLayout.measureVertical (LinearLayout.java:842)
  at android.widget.LinearLayout.onMeasure (LinearLayout.java:721)
  at android.view.View.measure (View.java:26535)
  at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:7109)
  at android.widget.FrameLayout.onMeasure (FrameLayout.java:194)
  at com.android.internal.policy.DecorView.onMeasure (DecorView.java:762)
  at android.view.View.measure (View.java:26535)
  at android.view.ViewRootImpl.performMeasure (ViewRootImpl.java:4064)
  at android.view.ViewRootImpl.measureHierarchy (ViewRootImpl.java:2779)
  at android.view.ViewRootImpl.performTraversals (ViewRootImpl.java:3044)
  at android.view.ViewRootImpl.doTraversal (ViewRootImpl.java:2495)
  at android.view.ViewRootImpl$TraversalRunnable.run (ViewRootImpl.java:9251)
  at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1234)
  at android.view.Choreographer$CallbackRecord.run (Choreographer.java:1242)
  at android.view.Choreographer.doCallbacks (Choreographer.java:902)
  at android.view.Choreographer.doFrame (Choreographer.java:835)
  at android.view.Choreographer$FrameDisplayEventReceiver.run (Choreographer.java:1217)
  at android.os.Handler.handleCallback (Handler.java:942)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loopOnce (Looper.java:201)
  at android.os.Looper.loop (Looper.java:288)
  at android.app.ActivityThread.main (ActivityThread.java:8115)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:703)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:911)

Additional context

I configure RevenueCat in main with this:

  Future<void> configure() async {

      PurchasesConfiguration configuration;

      if (Platform.isAndroid) {
        configuration = PurchasesConfiguration(googleApiKey)..appUserID = null
          ..purchasesAreCompletedBy = const PurchasesAreCompletedByRevenueCat();
      } else if (Platform.isIOS) {
        configuration = PurchasesConfiguration(appleApiKey)..appUserID = null
          ..purchasesAreCompletedBy = const PurchasesAreCompletedByRevenueCat();
      } else {
        throw UnsupportedError('Unsupported platform');
      }

      await Purchases.configure(configuration);

  }

and when I'm showing paywall I use that code:

  Future<bool> presentPaywall(
      BuildContext context, String previousScreen) async {
    await checkPurchaseConfiguration();

    bool purchaseOrRestoreSuccess = false;
    final completer = Completer<bool>();

    CustomerInfo customerInfo = await Purchases.getCustomerInfo();
    if (customerInfo.entitlements.all[entitlementID]?.isActive != true) {
      final remoteConfigHelper = await RemoteConfigHelper.getInstance();
      await remoteConfigHelper.updateConfigIfNeeded();

      if (remoteConfigHelper.showRevenueCatPaywall(previousScreen)) {
        try {
          await context.router.push(
            ParentalGateRoute(
              onVerified: () async {
                final paywallResult = await RevenueCatUI.presentPaywall(
                  displayCloseButton: true,
                );
                FirebaseAnalytics.instance.logEvent(
                  name: 'view_rc_subscription_screen',
                  parameters: {
                    'timestamp': DateTime.now().toIso8601String(),
                    'previous_screen': previousScreen ?? 'none',
                  },
                );
                if (paywallResult == PaywallResult.purchased ||
                    paywallResult == PaywallResult.restored) {
                  appData.updatePremiumStatus(ref, true);
                  FirebaseAnalytics.instance.logEvent(
                    name: 'trial_activated_rc',
                    parameters: {
                      'timestamp': DateTime.now().toIso8601String(),
                      'paywallResult': paywallResult.toString(),
                      'previous_screen': previousScreen ?? 'none',
                    },
                  );
                  purchaseOrRestoreSuccess = true;
                }
                // Mark the completer as complete after handling the paywall result
                completer.complete(purchaseOrRestoreSuccess);
              },
            ),
          );
        } catch (e) {
          // If there's an error (e.g., network issue), log it and fall back to the custom subscription screen
          print("Error while fetching CustomerInfo or RevenueCat paywall : $e");
          FirebaseCrashlytics.instance.recordError(e, null);
          // Fallback: Show your own subscription screen if there's a network error or other issue
          bool? result = await context.router.push<bool>(
            SubscriptionRoute(previousScreen: previousScreen),
          );
          purchaseOrRestoreSuccess = result ?? false;
          completer.complete(purchaseOrRestoreSuccess);
        }
      } else {
        bool? result = await context.router.push<bool>(
          SubscriptionRoute(previousScreen: previousScreen),
        );
        purchaseOrRestoreSuccess = result ?? false;
        completer.complete(purchaseOrRestoreSuccess);
        // }
      }
    } else {
      // Complete the completer if the user already has premium active
      completer.complete(false);
    }

    // Wait for the paywall process to finish before returning
    return completer.future;
  }
}

  Future<void> checkPurchaseConfiguration() async {
    bool isConfigured = await Purchases.isConfigured;
    if (!isConfigured) {
      PurchasesConfiguration configuration;
      if (Platform.isAndroid) {
        configuration = PurchasesConfiguration(googleApiKey);
      } else {
        configuration = PurchasesConfiguration(appleApiKey);
      }
      await Purchases.configure(configuration);
    }
  }
@hirosz hirosz added the bug Something isn't working label Oct 17, 2024
@RCGitBot
Copy link
Contributor

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

@michaelAtRC
Copy link

Hey @hirosz ,

Thanks for reaching out, we'd be happy to help.

If this is happening in production but not to all users do you have a list of users that might be experiencing this? Also, do these users share something in common? This could be something like same entitlement/subscripiton, same device, same country, etc...

If so, this could help us narrow down the possible issue here, in this case where its not all users it would be helpful to find a pattern in which users are experiencing it.

Let me know if that helps.

@michaelAtRC
Copy link

Hey @hirosz ,

Are you still experiencing this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants