I have two libaries in my app authorizationsdk.aar and iHealthSDK_2.9.6 and when run the app i got this error
Duplicate class a.a found in modules jetified-authorizationsdk-runtime (authorizationsdk.aar) and jetified-iHealthSDK_2.9.6 (iHealthSDK_2.9.6.jar)
do you have two classes with a different name but with the same package in the two different libraries? If that is the case you need to change the package. Different libs should use different packages otherwise after the obfuscation the two classes will end up having the same name and package
com.your.package.a.a
Related
I am using two sdk's in my app. My sdk is using a compiled obfuscated jar file which is causing conflict with other sdk when add together as dependency in an app.
Due to which I am getting a compile time error as follows
Duplicate class a.a found in modules module-core-31.2.5-runtime (com.random1.android.sdk:module-core:31.2.5) and random2-core-4.0.0-runtime (com.abc.xyz:random2-core:5.0.0)
Duplicate class b.a found in modules module-core-31.2.5-runtime (com.random1.android.sdk:module-core:31.2.5) and random2-core-4.0.0-runtime (com.abc.xyz:random2-core:5.0.0)
How to resolve this as this code comes from jar and these SDK's are already compiled?
Class names such as a.a or a.b look like identifiers generated by obfuscators.
If you're sure both SDKs use the very same JAR (in which case I don't see why this would happen), then there are generally two options:
Leave out this dependency from one of the SDKs:
https://docs.gradle.org/current/userguide/dependency_downgrade_and_exclude.html#sec:excluding-transitive-deps
Use a custom class loader based on the Bootstrap class loader to which you can add all unique resources found by the System class loader.
Given that it's a compile time error, you're probably left with the first option only.
I recently extracted some code from my Android application project into separate kotlin modules (the build.gradle files declare the "java-library" and "kotlin" plugins).
Now, the task ':app:minifyQaWithR8' is failing with the message:
AGPBI: {"kind":"error","text":"Type com.myapp.ext.models.AckResponse
is defined multiple times:
E:\projects\myapp\ext\build\.transforms\35656f2face08400c6d53844207373f0\jetified-ext.jar:com/myapp/ext/models/AckResponse.class,
E:\projects\myapp\app\build\tmp\kotlin-classes\qa\com\myapp\ext\models\AckResponse.class"}],"tool":"R8"}
I tried deleting each module's build folder, then invaldate cache/restart, then assemble, and got a similar result with a different class. But both times, the locations were the same: one was in .transforms\35656f2face08400c6d53844207373f0\jetified-ext.jar and one in app\build\tmp\kotlin-classes\qa
In a similar question a member of the R8 team suggests that one of these locations represents a dependency, and one represents the app code, however, I cannot find any instance of the class in question in my application code, nor any indication that my module is being imported more than once.
It may be relevant that two of my modules do have a lot of the same classes, however I'm using the following statement to only include one of them in the build:
if(api_version == "ext2") {
implementation project(":ext2")
}else{
implementation project(":ext1")
}
The packages in these modules do not appear in the main application code.
What other steps can I take to track down the root of this issue?
As it turns out, there were in fact duplicate classes in my project. I was just unable to find them at first because the package name in the file did not correspond to the folder where the file was located.
I'm using the #UninstallModules annotation in one of my test classes to change the actual dependencies with the mock ones. Therefore, I create duplicates of those modules in my testing package.
The problem however is that it causes confusion for the dagger compiler. I get the [Dagger/DuplicateBindings] error on every class if I don't uninstall the testing modules with #UninstallModules for all of them.
How can I make the dagger modules specific to one class?
I created two modules A(Client) and B(Server) and defined AIDL files to communicate among them.
Now I want to use both the modules in my App.
When I include both of them in my App it runs fine from Android Studio but when I try to build Apk it Fails..
Getting this error "Program type already present: my.package.BuildConfig"
Here the Buildconfig files are from the 2 modules A and B
Since the AIDL has to be same in both the modules and also the package has to be the same, it will generate the same files in Both the modules.
How do I build in this case by ignoring the duplicate files ?
Any pointer to solve this ?
As #Mark Keen suggested We can't have the same package name in both client and server module and include them in App.
I have changed one of them and able to build now.
Thanks #Mark Keen for the suggestion.
I created two aar-libraries: com.example:test1:1.0.0 and com.example:test2:1.0.0. I added these libs to my main app and after build Android-Studio throws error:
Duplicate class com.example.utils.a found in modules classes.jar (com.example:test1:1.0.0) and classes.jar (com.example:test2:1.0.0)
I find out that this error happens because both libraries have classes in same package (com.example.utils) and after obfuscation R8 creates classes (a.class) with same full name (I saw this in classes.jar of aar). If I disable R8 in properties of my libs this error has gone.
'a' is not library class: after obfuscation all library classe names remain unchanged and a.class was added in package additionaly by R8.
I read R8 documentation and found nothing about this problem.
Are there any ways to solve this issue without ranaming the package in one of my libs?
When creating two libraries it is best practice to use two different namespaces, as otherwise there will be the possibility of duplicate classes even without using R8 when "accidentally" a class with the same name is added to both. So in your case use com.example.test1 and com.example.test2.
Depending on you use case, it might also be a better option to not apply R8 to the libraries, but only apply R8 to the final app including the two libraries. Shrinking libraries are mainly to make distribution size smaller, and rename internals to avoid library users (accidentally or knowingly) depend on internals which might change between library versions.
When shrinking libraries you also want to consider the option -keeppackagenames to make sure that all renamed classes stay within the package of the library. Otherwise you might end up with class e.g. a.a.a.a.class in multiple libraries.
If this issue happens for libraries that you don't have control over tools like shadow can be used to relocate.
You should always prefix all of your code in Java or other JVM languages with unique packages to create a unique fully qualified name because any two classes with the exact same fully qualified name will cause a build error. This happens because the JVM only uses the fully qualified name string, saved initially in a single table, to instantiate all the classes and interfaces in the system. If the table will have more than one entry for a class/interface, it won't know which one to choose. You can read more about it here.
As I describe in my answer here, the best solution for obfuscation related collisions is to use -repackageclasses com.example:test#.ofs in the proguard-rules file of each library while replaceing # with 1 and 2 respectivly. This will move all the obfuscated classes into the com.example:test#.ofs package while all the non-obfuscated classes will remain in their original packages and you're guaranteed to have no collisions.
As the Proguard documentation states:
-repackageclasses [package_name]
Specifies to repackage all class files that are renamed, by moving them into the single given package.