javaandroidamazon-web-servicesapache-commons-loggingandroid-9.0-pie

How to avoid appcrashes in Android 9 with AmazonSNSClient?


In Android 9 (API 28) my App crashes when creating a new AmazonSNSClient (in API 26 I don't get any errors):

AmazonSNSClient pushClient = new AmazonSNSClient(credentialsProvider);

My LogCat says:

    java.lang.NoClassDefFoundError: Failed resolution of: Lorg/apache/commons/logging/LogFactory;
        at com.amazonaws.AmazonWebServiceClient.<clinit>(AmazonWebServiceClient.java:55)
        at myapp.service.AWSMessagingService.createEndpoint(AWSMessagingService.java:170)
        at myapp.service.AWSMessagingService.registerWithSNS(AWSMessagingService.java:103)
        at myapp.service.PushNotificationService.sendRegistrationToAWS(PushNotificationService.java:109)
        at myapp.service.PushNotificationService.onNewToken(PushNotificationService.java:105)
        at com.google.firebase.messaging.FirebaseMessagingService.zzd(Unknown Source:86)
        at com.google.firebase.iid.zzg.run(Unknown Source:4)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at com.google.android.gms.common.util.concurrent.zza.run(Unknown Source:7)
        at java.lang.Thread.run(Thread.java:764)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "org.apache.commons.logging.LogFactory" on path: DexPathList[[zip file "/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/base.apk", zip file "/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_dependencies_apk.apk", zip file "/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_resources_apk.apk", zip file "/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_0_apk.apk", zip file "/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_1_apk.apk", zip file "/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_2_apk.apk", zip file "/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_3_apk.apk", zip file "/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_4_apk.apk", zip file "/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_5_apk.apk", zip file "/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_6_apk.apk", zip file "/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_7_apk.apk", zip file "/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_8_apk.apk", zip file "/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_9_apk.apk"],nativeLibraryDirectories=[/data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/lib/x86, /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/base.apk!/lib/x86, /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_dependencies_apk.apk!/lib/x86, /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_resources_apk.apk!/lib/x86, /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_0_apk.apk!/lib/x86, /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_1_apk.apk!/lib/x86, /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_2_apk.apk!/lib/x86, /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_3_apk.apk!/lib/x86, /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_4_apk.apk!/lib/x86, /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_5_apk.apk!/lib/x86, /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_6_apk.apk!/lib/x86, /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_7_apk.apk!/lib/x86, /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_8_apk.apk!/lib/x86, /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_slice_9_apk.apk!/lib/x86, /system/lib]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
        at com.amazonaws.AmazonWebServiceClient.<clinit>(AmazonWebServiceClient.java:55) 
        at myapp.service.AWSMessagingService.createEndpoint(AWSMessagingService.java:170) 
        at myapp.service.AWSMessagingService.registerWithSNS(AWSMessagingService.java:103) 
        at myapp.service.PushNotificationService.sendRegistrationToAWS(PushNotificationService.java:109) 
        at myapp.service.PushNotificationService.onNewToken(PushNotificationService.java:105) 
        at com.google.firebase.messaging.FirebaseMessagingService.zzd(Unknown Source:86) 
        at com.google.firebase.iid.zzg.run(Unknown Source:4) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at com.google.android.gms.common.util.concurrent.zza.run(Unknown Source:7) 
        at java.lang.Thread.run(Thread.java:764) 
2018-12-17 09:25:07.483 10291-10344/myapp E/AndroidRuntime:     Suppressed: java.io.IOException: No original dex files found for dex location /data/app/myapp-grqOb2dmxK1zDq9u44b9Rg==/split_lib_resources_apk.apk
        at dalvik.system.DexFile.openDexFileNative(Native Method)
        at dalvik.system.DexFile.openDexFile(DexFile.java:354)
        at dalvik.system.DexFile.<init>(DexFile.java:101)
        at dalvik.system.DexFile.<init>(DexFile.java:75)
        at dalvik.system.DexPathList.loadDexFile(DexPathList.java:394)
        at dalvik.system.DexPathList.makeDexElements(DexPathList.java:354)
        at dalvik.system.DexPathList.<init>(DexPathList.java:164)
        at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:74)
        at dalvik.system.BaseDexClassLoader.<init>(BaseDexClassLoader.java:65)
        at dalvik.system.PathClassLoader.<init>(PathClassLoader.java:64)
        at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:73)
        at com.android.internal.os.ClassLoaderFactory.createClassLoader(ClassLoaderFactory.java:88)
        at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:74)
        at android.app.ApplicationLoaders.getClassLoader(ApplicationLoaders.java:40)
        at android.app.LoadedApk.createOrUpdateClassLoaderLocked(LoadedApk.java:727)
        at android.app.LoadedApk.getClassLoader(LoadedApk.java:810)
        at android.app.LoadedApk.getResources(LoadedApk.java:1032)
        at android.app.ContextImpl.createAppContext(ContextImpl.java:2345)
        at android.app.ActivityThread.handleBindApplication(ActivityThread.java:5749)
        at android.app.ActivityThread.access$1100(ActivityThread.java:199)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1650)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

I found out that I can avoid the error if I don't exclude "commons-logging" from "com.amazonaws:aws-android-sdk-sns" in my build.gradle, so I replaced:

implementation 'com.amazonaws:aws-android-sdk-sns:2.2.0', {
    exclude module: 'commons-logging'
}

with:

implementation 'com.amazonaws:aws-android-sdk-sns:2.2.0'

The app works fine now but I can't build a signed APK because I get the error "DuplicatePlatformClasses: Duplicate Platform Classes" and my Lint Report says:

commons-logging defines classes that conflict with classes now provided by Android. Solutions include finding newer versions or alternative libraries that don't have the same problem (for example, for httpclient use HttpUrlConnection or okhttp instead), or repackaging the library using something like jarjar. There are a number of libraries that duplicate not just functionality of the Android platform but using the exact same class names as the ones provided in Android -- for example the apache http classes. This can lead to unexpected crashes.

To solve this, you need to either find a newer version of the library which no longer has this problem, or to repackage the library (and all of its dependencies) using something like the jarjar tool, or finally, rewriting the code to use different APIs (for example, for http code, consider using HttpUrlConnection or a library like okhttp). Note: This issue has an associated quickfix operation in Android Studio and IntelliJ IDEA. To suppress this error, use the issue id "DuplicatePlatformClasses" as explained in the Suppressing Warnings and Errors section.

So I ran "gradlew app:dependencies > dependencies.txt" in the terminal in my project folder and found out that "com.amazonaws:aws-android-sdk-sns:2.2.0" uses "commons-logging:commons-logging:1.1.1" but I can also find "commons-logging:commons-logging:1.2" which is "provided by Android" I guess?

So why does "com.amazonaws:aws-android-sdk-sns:2.2.0" not use "commons-logging:commons-logging:1.2" if I exclude "commons-logging:commons-logging:1.1.1" and how can I fix this issue?


Solution

  • I could solve the error by updating "com.amazonaws:aws-android-sdk-sns:2.2.0" to a newer version (in my case "com.amazonaws:aws-android-sdk-sns:2.9.1").

    The NoClassDefFoundError in Android 9 is also tracked in this issue: https://github.com/aws-amplify/aws-sdk-android/issues/476