flutterdartrevenuecat

Flutter: java.lang.IncompatibleClassChangeError: Found interface com.revenuecat.purchases.models.StoreProduct, but class was expected


After Configuring RevenueCat SDK, when I attempt to purchase a product or to open a paywall this error shows in the debug tab and crashes my app. Note that I only use Android for now, so everything is configured for play store mainly, thus why I configured google Api Key without checking the platform.

This is the init function after login (I use firebase for login and use the email for revenuecat id login)

Future<void> initPlatformState() async {
    // Enable debug logs before calling `configure`.
    await Purchases.setLogLevel(LogLevel.debug);

    /*
    - appUserID is nil, so an anonymous ID will be generated automatically by the Purchases SDK. Read more about Identifying Users here: https://docs.revenuecat.com/docs/user-ids
    - observerMode is false, so Purchases will automatically handle finishing transactions. Read more about Observer Mode here: https://docs.revenuecat.com/docs/observer-mode
    */
    PurchasesConfiguration configuration;

    configuration = PurchasesConfiguration(googleApiKey)
      ..appUserID = null
      ..observerMode = false;

    await Purchases.configure(configuration);
    await Purchases.enableAdServicesAttributionTokenCollection();

    appData.appUserID = await Purchases.appUserID;

    Purchases.addCustomerInfoUpdateListener((customerInfo) async {
      appData.appUserID = await Purchases.appUserID;

      CustomerInfo customerInfo = await Purchases.getCustomerInfo();
      (customerInfo.entitlements.all[entitlementID] != null &&
              customerInfo.entitlements.all[entitlementID]!.isActive)
          ? appData.entitlementIsActive = true
          : appData.entitlementIsActive = false;

      //setState(() {});
    });
  }

  @override
  void initState() {
    initPlatformState();

    super.initState();
  }

And this is a product that should be bought before accessed

InkWell(
                  onTap: () async {
                    if (_isMathA == true) {
                      Navigator.push(
                        context,
                        MaterialPageRoute(
                            builder: (context) => const CourseMathAScreen()),
                      );
                    } else {
                      try {
                        Offerings offerings = await Purchases.getOfferings();
                        var package =
                            offerings.getOffering("Math A Course")?.lifetime;
                        await Purchases.purchasePackage(package!);
                        setState(() {
                          _isMathA = true;
                        });
                      } catch (e) {
                        debugPrint("Failed to purchase product: $e");
                      }
                    }
                  },
                  child: CourseWidget(
                    path: "assets/images/math.png",
                    title: "Mathematics A",
                    subtitle:
                        "MEXT Mathematics course A (beginner) broken down into chapters:\nNumbers and expressions\nQuadratic functions\nFigures and measurements\nThe number of possible outcomes and probability\nProperties of integers\nProperties of figures",
                    price: _isMathA ? "OPEN" : "\$17",
                  ),
                ),

And if it helps this is the paywall function I made. This also triggers the crash.

void checkUserPaywall(context, doFunction) async {
  CustomerInfo customerInfo = await Purchases.getCustomerInfo();
  if (customerInfo.entitlements.all[entitlementID] != null &&
      customerInfo.entitlements.all[entitlementID]!.isActive == true) {
    doFunction();
  } else {
    Offerings offerings;
    try {
      offerings = await Purchases.getOfferings();

      if (offerings == null || offerings.current == null) {
        //offerings are empty show message to user
      } else {
        //show paywall
        await showModalBottomSheet(
            useRootNavigator: true,
            isDismissible: true,
            isScrollControlled: true,
            backgroundColor: Styles.orangeColor,
            shape: const RoundedRectangleBorder(
                borderRadius: BorderRadius.vertical(top: Radius.circular(25))),
            context: context,
            builder: (BuildContext context) {
              return StatefulBuilder(
                  builder: (BuildContext context, StateSetter setModalState) {
                return Paywall(
                  offering: offerings.current,
                );
              });
            });
      }
    } on PlatformException catch (e) {
      await showDialog(
          context: context,
          builder: (context) {
            return SimpleDialog(
              title: const Text("Error"),
              children: [Text('${e.message}')],
            );
          });
    }
  }
}

This is the app build.gradle dependecies

dependencies {
    def billing_version = "5.1.0"
    implementation platform('com.google.firebase:firebase-bom:31.3.0')
    implementation "com.revenuecat.purchases:purchases:6.0.0"
    implementation "com.android.billingclient:billing:$billing_version"
    implementation "com.android.billingclient:billing-ktx:$billing_version"
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

I tried building an appbundle and it also crashes on my mobile phone. Also I tried pub clean, pub cache repair. I tried removing the billing client in dependencies and nothing different happened. I am quite desperate so please help!


Solution

  • I was having this same issue. RevenueCat support told me to check the version I am using in my pubspec.yaml file. As of this post the latest version is 4.11.1.

    AI told me there is likely a difference or incompatibility between my SDK version and the Google Play Billing Library version.

    After being stuck for a few days, I commented out the line in my build.gradle file that said

    implementation "com.revenuecat.purchases:purchases:6.0.0"
    

    and that seemed to fix the issue for me. Let me know if this helps!