customerio / customerio-reactnative

MIT License
25 stars 13 forks source link

Proguard enabled in Android Expo project causes customerio to fail with error "HTTP request failed. Error: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType" #251

Closed kimdanielarthur-cowlabs closed 7 months ago

kimdanielarthur-cowlabs commented 7 months ago

SDK version: customerio-expo-plugin: 1.0.0-beta.15 (latest in repostiroy) customerio-reactnative 3.5.2 react: 18.2.0 expo: 50.0.13 eas-cli@7.6.2

Environment: Production

Are logs available? from adb logs 03-28 15:40:04.779 10470 10551 D [CIO] : HTTP request failed. Error: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType

Describe the bug When enabling Proguard for production builds customer.io fails to send events.

To Reproduce

Expected behavior

Additional context I have already had to add an extra proguard rule to the expo project in order for it to build. Are there further proguard rules that need to be included which it maybe is not able to copy from the customer.io plugin? extraProguardRules: "-dontwarn org.slf4j.impl.StaticLoggerBinder",

Shahroz16 commented 7 months ago

Hey @kimdanielarthur-cowlabs thank you for reaching out and raising this issue, if there a sample project where its reproducible that would be great and speed up the process, otherwise we are going to try reproduce it and get back with more information.

kimdanielarthur-cowlabs commented 7 months ago

Thanks!

I can see if there is time to set up a clean test project, but i doubt will find the time...

I guess i can try to check the source code here to see what proguard rules are in the android native code, as i suspect its the build process on expo that is somehhow not copying them over. Given the error I had on that org.slf4j.impl.StaticLoggerBinder

Shahroz16 commented 7 months ago

@kimdanielarthur-cowlabs Thank you for your patience here, even though we don't utilize it or add it in our SDK. SLF4J Android – is a Simple Logging Facade for Java (SLF4J) that adds a logger binding for the Android platform. So I believe, by having this rule in your extended proguard, should be enough.

-dontwarn org.slf4j.impl.StaticLoggerBinder

Please, feel free to reopen the ticket in case there is any other dependency that gives you an issue, nothing stood out while we tested.

kimdanielarthur-cowlabs commented 7 months ago

Thanks,

My original issue is not related ot the StaticLoggerBinder, but "03-28 15:40:04.779 10470 10551 D [CIO] : HTTP request failed. Error: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType"

This issue still persists and I believe it may be related to gradle v8 and how proguard R8 by default does the optimisation/obfuscation. If I add the rule: -keep class * extends com.google.protobuf.** { *; } -keep,allowobfuscation,allowshrinking class kotlin.coroutines.Continuation -keep class io.customer.** { *; }

The customerio requests still fail, but I get a different error message than earlier reported

c04-02 21:16:53.896  5326  5399 D [CIO]   : HTTP request failed. Error: Response must include generic type (e.g., Response<String>)
04-02 21:16:53.896  5326  5399 D [CIO]   :     for method CustomerIOService.identifyCustomer

I am exploring further to try to figure out what classes are causing the problem.

I think the main point is that there seems to be issues with using Customer.io with expo 50 when proguard is enabled for release builds.

To be clear: The StaticLoggerBinder issue was another earlier problem with the SDK in latest expo and is not the main topic for this ticket

Shahroz16 commented 7 months ago

@kimdanielarthur-cowlabs thanks for adding this extra context, very much helpful and needed here. I suspect the same thing, gradle v8 enables R8 (obfuscation tool) full mode by default.

We are working on gradle V8 support as we speak and hopefully we should roll out a fix for it soon, I would recommend not moving to Gradle 8 if possible till then?

kimdanielarthur-cowlabs commented 7 months ago

Thanks!

I'll check if we somehow can control this when building using expo EAS build service

kimdanielarthur-cowlabs commented 7 months ago

Quick question: do you guys use retrofit2 rest library at all? I see quite a few issues related to R8 fullMode around github for that package

Shahroz16 commented 7 months ago

Yup we do and absolutely, most of the R8 restrictions are indeed coming from them. With our Gradle 8 support release we plan to ship proguarding updates for retrofit too after testing them.

kimdanielarthur-cowlabs commented 7 months ago

Ok great understand!

We are using Expo managed builds so I made a quick expo build pluging that sets the needed gradle property that disables R8 fullMode for now. That fixes the problem

const {withGradleProperties} = require("@expo/config-plugins");

module.exports = (config) => {
    return withGradleProperties(config, (config) => {
        config.modResults.push({
            type: "property",
            key: "android.enableR8.fullMode",
            value: "false",
        });
        return config;
    });
};
Shahroz16 commented 7 months ago

@kimdanielarthur-cowlabs We just released a new version with the support for R8 rules for the internal dependencies.

kimdanielarthur-cowlabs commented 7 months ago

@kimdanielarthur-cowlabs We just released a new version with the support for R8 rules for the internal dependencies.

Nice one, we can update and revert or disabling of fullMode