OneSignal / OneSignal-Android-SDK

OneSignal is a free push notification service for mobile apps. This plugin makes it easy to integrate your native Android or Amazon app with OneSignal. https://onesignal.com
Other
604 stars 368 forks source link

Error Caused by java.lang.ClassNotFoundException: com.huawei.hms.api.HuaweiApiAvailability #1423

Closed fillipeoliveira-hotmart closed 2 years ago

fillipeoliveira-hotmart commented 3 years ago

Description:

After add Dexguard on our project, I start to receive some errors of NoClassDefFoundError on HuaweiApiAvailability. I search on other issues, like https://github.com/OneSignal/OneSignal-Android-SDK/issues/1194 and https://github.com/OneSignal/OneSignal-Android-SDK/issues/1085 but the only solution is keep everything from OneSignal on dexguard rules.

Environment

OneSignal 4.4.2 via Gradle + Dexguard implementation ('com.onesignal:OneSignal:4.4.2')

Steps to Reproduce Issue:

None

Anything else:

Fatal Exception: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/huawei/hms/api/HuaweiApiAvailability;
       at com.onesignal.OSUtils.isHMSCoreInstalledAndEnabled(OSUtils.java:289)
       at com.onesignal.OSUtils.supportsHMS(OSUtils.java:317)
       at com.onesignal.OSUtils.getDeviceType(OSUtils.java:349)
       at com.onesignal.OSUtils.initializationChecker(OSUtils.java:112)
       at com.onesignal.OneSignal.init(OneSignal.java:711)
       at com.onesignal.OneSignal.setAppId(OneSignal.java:625)
       at com.onesignal.OneSignal.reassignDelayedInitParams(OneSignal.java:1028)
       at com.onesignal.OneSignal.onRemoteParamSet(OneSignal.java:759)
       at com.onesignal.OneSignal$5.complete(OneSignal.java:969)
       at com.onesignal.OneSignalRemoteParams.processJson(OneSignalRemoteParams.java:205)
       at com.onesignal.OneSignalRemoteParams.access$100(OneSignalRemoteParams.java:12)
       at com.onesignal.OneSignalRemoteParams$1.onSuccess(OneSignalRemoteParams.java:150)
       at com.onesignal.OneSignalRestClient$5.run(OneSignalRestClient.java:269)
       at java.lang.Thread.run(Thread.java:929)
Caused by java.lang.ClassNotFoundException: com.huawei.hms.api.HuaweiApiAvailability
       at com.onesignal.OSUtils.isHMSCoreInstalledAndEnabled(OSUtils.java:289)
       at com.onesignal.OSUtils.supportsHMS(OSUtils.java:317)
       at com.onesignal.OSUtils.getDeviceType(OSUtils.java:349)
       at com.onesignal.OSUtils.initializationChecker(OSUtils.java:112)
       at com.onesignal.OneSignal.init(OneSignal.java:711)
       at com.onesignal.OneSignal.setAppId(OneSignal.java:625)
       at com.onesignal.OneSignal.reassignDelayedInitParams(OneSignal.java:1028)
       at com.onesignal.OneSignal.onRemoteParamSet(OneSignal.java:759)
       at com.onesignal.OneSignal$5.complete(OneSignal.java:969)
       at com.onesignal.OneSignalRemoteParams.processJson(OneSignalRemoteParams.java:205)
       at com.onesignal.OneSignalRemoteParams.access$100(OneSignalRemoteParams.java:12)
       at com.onesignal.OneSignalRemoteParams$1.onSuccess(OneSignalRemoteParams.java:150)
       at com.onesignal.OneSignalRestClient$5.run(OneSignalRestClient.java:269)
       at java.lang.Thread.run(Thread.java:929)

Maybe, if add an try/catch on this method https://github.com/OneSignal/OneSignal-Android-SDK/blob/main/OneSignalSDK/onesignal/src/main/java/com/onesignal/OSUtils.java#L287 like this one https://github.com/OneSignal/OneSignal-Android-SDK/blob/main/OneSignalSDK/onesignal/src/main/java/com/onesignal/OSUtils.java#L160 or check if HuaweiApiAvailability exists inside supportsHMS(), help to solve the problem

This erros are more frequently on huawei phones image

fillipeoliveira-hotmart commented 3 years ago

Update to version 4.6.0 and the problem persists

jkasten2 commented 2 years ago

@fillipeoliveira-hotmart Thanks for reporting. I believe Dexguard is removing the hasHMSAvailabilityLibrary() and hasAllHMSLibrariesForPushKit() checks since it believes they are not needed. Could you share your Dexguard config so we can test with the same configuration as your project to try to come up with a solution?

In the mean time you can use the following in your Proguard config to keep minifying most of the OneSignal code but keep the problematic com.onesignal.OSUtils code as-is:

-keep class com.onesignal.OSUtils** {*;}
fillipeoliveira-hotmart commented 2 years ago

Hi @jkasten2 We already try with -keep class com.onesignal.** {*;} but nothing changed.

I can try with this one you said and report back when get some results.

fillipeoliveira-hotmart commented 2 years ago

Hi @jkasten2 We release the new version of the app with this change on dexguard yesterday and we already started to receive the crash again.

Fatal Exception: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/huawei/hms/api/HuaweiApiAvailability;
       at com.onesignal.OSUtils.isHMSCoreInstalledAndEnabled(OSUtils.java:288)
       at com.onesignal.OSUtils.supportsHMS(OSUtils.java:316)
       at com.onesignal.OSUtils.getDeviceType(OSUtils.java:348)
       at com.onesignal.OSUtils.initializationChecker(OSUtils.java:111)
       at com.onesignal.OneSignal.init(OneSignal.java:797)
       at com.onesignal.OneSignal.setAppId(OneSignal.java:693)
       at com.onesignal.OneSignal.reassignDelayedInitParams(OneSignal.java:1137)
       at com.onesignal.OneSignal.onRemoteParamSet(OneSignal.java:845)
       at com.onesignal.OneSignal$6.complete(OneSignal.java:1078)
       at com.onesignal.OneSignalRemoteParams.processJson(OneSignalRemoteParams.java:206)
       at com.onesignal.OneSignalRemoteParams.access$100(OneSignalRemoteParams.java:12)
       at com.onesignal.OneSignalRemoteParams$1.onSuccess(OneSignalRemoteParams.java:151)
       at com.onesignal.OneSignalRestClient$5.run(OneSignalRestClient.java:283)
       at java.lang.Thread.run(Thread.java:929)
Caused by java.lang.ClassNotFoundException: com.huawei.hms.api.HuaweiApiAvailability
       at com.onesignal.OSUtils.isHMSCoreInstalledAndEnabled(OSUtils.java:288)
       at com.onesignal.OSUtils.supportsHMS(OSUtils.java:316)
       at com.onesignal.OSUtils.getDeviceType(OSUtils.java:348)
       at com.onesignal.OSUtils.initializationChecker(OSUtils.java:111)
       at com.onesignal.OneSignal.init(OneSignal.java:797)
       at com.onesignal.OneSignal.setAppId(OneSignal.java:693)
       at com.onesignal.OneSignal.reassignDelayedInitParams(OneSignal.java:1137)
       at com.onesignal.OneSignal.onRemoteParamSet(OneSignal.java:845)
       at com.onesignal.OneSignal$6.complete(OneSignal.java:1078)
       at com.onesignal.OneSignalRemoteParams.processJson(OneSignalRemoteParams.java:206)
       at com.onesignal.OneSignalRemoteParams.access$100(OneSignalRemoteParams.java:12)
       at com.onesignal.OneSignalRemoteParams$1.onSuccess(OneSignalRemoteParams.java:151)
       at com.onesignal.OneSignalRestClient$5.run(OneSignalRestClient.java:283)
       at java.lang.Thread.run(Thread.java:929)

we are using this version of oneSignal now

object OneSignal {
        const val base = "4.6.2"
        const val plugin = "0.13.4"
    }

The dexguard config file you requested, I sent directly to support team by email (before of this change).

jkasten2 commented 2 years ago

@fillipeoliveira-hotmart I found that -assumenosideeffects seems to override the -keep in some cases. Stripping out getName() can't be used on the current version of OneSignal because of the way the SDK uses it with NoClassDefFoundError in com.onesignal.OSUtils to detect if some classes exists.

Workaround for OneSignal 4.6.3 & older

Remove the following getName() rule from your .pro proguard / dexguard rule file.

-assumenosideeffects public final class java.lang.Class {
    // Comment out this getName() line
    public java.lang.String getName();
}

Fix

For future versions of OneSignal removing this rule won't be required, it is being addressed in PR #1492 and will be in a future release (4.6.4 and/or 4.7.0)

Reproducing the crash

To reproduce the crash with com.onesignal.OSUtils when proguard / dexguard is enabled one of the following can be done.

  1. Install the app on a device or emulator that does not have Google Play Services installed on it.
  2. Or if you don't have a test device like this, exclude firebase-message from OneSignal with the following.
    • exclude group: 'com.google.firebase', module: 'firebase-messaging'
    • (note if you use this to repo the issue you will notice an NPE on com.onesignal.OneSignal.registerForPushToken. This 2nd crash isn't a proguard issue, you can ignore this as excluding firebase shouldn't be done for when targeting devices with Google Play services)
fillipeoliveira-hotmart commented 2 years ago

Hi @jkasten2 That's good news!

I have not yet found a way to do this workaround on Dexguard, but if in the next version the problem is fixed, that's not a problem.

When we release a new version with the workaround or with the new version, I return with the results. Thx for your help!

raghav2945 commented 2 years ago

This problem has resurfaced with your version: 4.6.3. for us [Audiomack]. The stacks looks similar but still I am uploading the latest stack-trace from Firebase.

Stack-trace

Fatal Exception: java.lang.NoClassDefFoundError: Failed resolution of: Lcom/huawei/hms/api/HuaweiApiAvailability; at com.onesignal.OSUtils.isHMSCoreInstalledAndEnabled(OSUtils.java:289) at com.onesignal.OSUtils.supportsHMS(OSUtils.java:317) at com.onesignal.OSUtils.getDeviceType(OSUtils.java:349) at com.onesignal.OSUtils.initializationChecker(OSUtils.java:112) at com.onesignal.OneSignal.init(OneSignal.java:796) at com.onesignal.OneSignal.setAppId(OneSignal.java:692) at com.onesignal.OneSignal.reassignDelayedInitParams(OneSignal.java:1136) at com.onesignal.OneSignal.onRemoteParamSet(OneSignal.java:844) at com.onesignal.OneSignal$6.complete(OneSignal.java:1077) at com.onesignal.OneSignalRemoteParams.processJson(OneSignalRemoteParams.java:206) at com.onesignal.OneSignalRemoteParams.access$100(OneSignalRemoteParams.java:12) at com.onesignal.OneSignalRemoteParams$1.onSuccess(OneSignalRemoteParams.java:151) at com.onesignal.OneSignalRestClient$5.run(OneSignalRestClient.java:283) at java.lang.Thread.run(Thread.java:818)

Caused by java.lang.ClassNotFoundException: Didn't find class "com.huawei.hms.api.HuaweiApiAvailability" on path: DexPathList[[zip file "/system/framework/android.test.runner.jar", zip file "/data/app/com.audiomack-1/base.apk"],nativeLibraryDirectories=[/data/app/com.audiomack-1/lib/arm64, /data/app/com.audiomack-1/base.apk!/lib/arm64-v8a, /vendor/lib64, /system/lib64]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56) at java.lang.ClassLoader.loadClass(ClassLoader.java:511) at java.lang.ClassLoader.loadClass(ClassLoader.java:469) at com.onesignal.OSUtils.isHMSCoreInstalledAndEnabled(OSUtils.java:289) at com.onesignal.OSUtils.supportsHMS(OSUtils.java:317) at com.onesignal.OSUtils.getDeviceType(OSUtils.java:349) at com.onesignal.OSUtils.initializationChecker(OSUtils.java:112) at com.onesignal.OneSignal.init(OneSignal.java:796) at com.onesignal.OneSignal.setAppId(OneSignal.java:692) at com.onesignal.OneSignal.reassignDelayedInitParams(OneSignal.java:1136) at com.onesignal.OneSignal.onRemoteParamSet(OneSignal.java:844) at com.onesignal.OneSignal$6.complete(OneSignal.java:1077) at com.onesignal.OneSignalRemoteParams.processJson(OneSignalRemoteParams.java:206) at com.onesignal.OneSignalRemoteParams.access$100(OneSignalRemoteParams.java:12) at com.onesignal.OneSignalRemoteParams$1.onSuccess(OneSignalRemoteParams.java:151) at com.onesignal.OneSignalRestClient$5.run(OneSignalRestClient.java:283) at java.lang.Thread.run(Thread.java:818)

fillipeoliveira-hotmart commented 2 years ago

Hi @raghav2945 , the fix for this bug is in 4.6.5, but I not tested it yet. https://github.com/OneSignal/OneSignal-Android-SDK/pull/1492

raghav2945 commented 2 years ago

Hi @raghav2945 , the fix for this bug is in 4.6.5, but I not tested it yet. #1492

We will update the SDK and monitor it, and if everything goes well, we will inform you here.

fillipeoliveira-hotmart commented 2 years ago

Everything working on version 4.6.5. Thx @jkasten2 for your help!