Duplicate files copied in APK Android - Can it be merged? - android

In my android project I have included two libraries as JARs into libs folder. And I add them to the build Gradle as below.
dependencies {
compile files('libs/siddhi-core-4.0.0-M13-SNAPSHOT.jar')
compile files('libs/siddhi-execution-math-4.0.2-SNAPSHOT.jar')
}
Those two jar files the have a file with the same name ("org.wso2.siddhi.annotation.Extension") but with different content. And both files are important for the project.
Since it has same name gradle won't build saying
Duplicate files copied in APK
How can I merge those two files into one single file with the same name?
Those two files are text files with a list of Class names. In two files they have two different lists. So I want to merge them into one list in a text file with same name.

Finally I found the answer. In the app build gradle you can specify to merge the conflicting files.
packagingOptions {
merge 'META-INF/annotations/org.wso2.siddhi.annotation.Extension'
}
for details look here https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.PackagingOptions.html

You can exclude the file from jar by unzip them first and copy the jar without those files,
After that compile that unZip copy file instead of the actual file, like this
task unzipJar(type: Copy) {
from zipTree('libs/siddhi-core-4.0.0-M13-SNAPSHOT.jar')
into ("$buildDir/libs/siddhi-core-4.0.0-M13-SNAPSHOT")
include "**/*.class"
exclude "org.wso2.siddhi.annotation.Extension"
}
dependencies {
compile files('libs/siddhi-execution-math-4.0.2-SNAPSHOT.jar')
compile files("$buildDir/libs/siddhi-core-4.0.0-M13-SNAPSHOT") {
builtBy "unzipJar"
}
}
Please check this, even I didn't get the chance to use it but it should work.

You can not as both files having same name resolution.(org.wso2.siddhi.annotation.Extension).
So it will not going to work .
Lets say some how you have included both the jars than how you are going to use one of them
ie. How runtime will uniquely identify the class as both class have same namespace as well as name.

try this one
dependencies {
compile files('libs/siddhi-execution-math-4.0.2-SNAPSHOT.jar')
compile files("$buildDir/libs/siddhi-core-4.0.0-M13-SNAPSHOT") {
builtBy "unzipJar"
}
}

Related

Avoid packaging jar dependencies into aar

I'm developing an android library for work and we're using some jars that are not available in maven repositories. However, we are not legally allowed to package these jars into our library, the consumer must get those jars themselves in addition to our library.
My problem is that I can't seem to require the consumer of our library to provide these jars (I'm using a test app that includes the aar). I tried the solutions for this similar question to no avail.
I have tried setting them to provided instead of compile in my gradle file:
// Neither of these seem to fix the problem
compile files('libs/externalDep.jar')
provided files('libs/externalDep.jar')
I also tried excluding them in packaging options:
packagingOptions { exclude 'libs/externalDep.jar }`
I can exclude them by adding this to the android tag in my build.gradle:
android.libraryVariants.all { variant ->
variant.outputs.each { output ->
def packageLib = output.getPackageLibrary()
packageLib.exclude('libs/externalDep.jar')
}
They're not added to the aar but building the test app gives me:
com.android.build.api.transformTransformException:
com.android.builder.packaging.DuplicateFileException:
Duplicate files copied in APK VERSION.txt
File1: path/to/jar/in/test/app/project/externalDep.jar
File2: path/to/build/intermediates/exploded-aar/.../jars/classes.jar
To clarify, I'm not concerned at all with maven repo dependencies, those are working fine. I just want whoever uses the library to have to get and add those jars we're using too.
Surely there's a less convoluted way to specify this?
The jar file must be moved up one level, from mymodule/libs/ to mymodule/ as per this answer.
Then in the build.gradle file, change:
compile file('libs/externalDep.jar')
to
provided file('externalDep.jar')
That's it.
It won't be copied into the aar and clients using the aar must provide the jar file themselves.
App projects using the aar can specify compile file('lib/externalDep') as normal.

How can I exclude non-class files contained in library JARs from release APKs?

I'm building APK files using gradle and let proguard shrink and obfuscate my code. One external library that I use contains some *.so files that I do not need but that end up in my final APK file.
I guess it should be possible to tell proguard to ignore those files, but how?
The documentation of proguard (http://proguard.sourceforge.net/manual/usage.html#filters) explains how to use filters, for example this is how to avoid errors with duplicate MANIFEST files:
-injars in1.jar
-injars in2.jar(!META-INF/MANIFEST.MF)
-injars in3.jar(!META-INF/MANIFEST.MF)
-outjars out.jar
And we can also filter based on filenames and patterns:
-injars in.jar(!images/**)
-outjars out.jar
This would be perfect, let's assume I wanted to do exactly as in the second example and strip everything in an 'images' directory from one of my jars.
The problem is, when using proguard in a gradle build for an Android project, we don't specify the input and output ourselves as in these examples. Instead probably gradle tells proguard which JARs to work on and where to write the results to. So there is no place in the config file to put the
(!images/**)
statement.
What I would expect to work is an option similar to this one:
-stripfiles !images/**
Okay, finally found a solution through this question:
Android Gradle plugin 0.7.0: "duplicate files during packaging of APK"
Arbitrary files can be excluded from being packaged into the APK by adding
android {
packagingOptions {
exclude 'path/to/file/to/be/ignored.so'
}
}
to the build.gradle file.
Unfortunately, it doesn't seem to support regular expressions though.
If you have the following files in the libs folder:
app/libs
├─ library-1.0.jar
├─ library-1.0-sources.jar
└─ library-1.0-javadoc.jar
Then the library-1.0-sources.jar and library-1.0-javadoc.jar will be included in the built APK (at the top-level root).
You should exclude them like this, in the app/build.gradle file:
dependencies {
compile fileTree(include: ['*.jar'], exclude: ['*-sources.jar', '*-javadoc.jar'], dir: 'libs')
}
See also: How to attach javadoc or sources to jars in libs folder?

Gradle reference to external archive directly

How can we refer an archive file ( aar for android or jar in general) from the build.gradle.
eg : compile files('https://--artifactoryonline.com-url--Debug.aar')
Background/Root Cause :
Android Library project has multiple flavors to be supported.
productFlavors {
flavor1 {
// Add any falvor1 flavor specific details here
}
flavor2 {
// Add any flavor2 specific details here
}
}
While the flavors are working fine and aar is generated and uploaded to the articfactory, reference from the maven is not getting resolved as POM files are not generated for library flavors. which in turn leads to maven-metadata.xml not being updated.
This seems to be an issue - Reference :How to upload multiple android archives (one for each flavor)
So to circumvent the situation wanted to get the archive files as they are generated correctly.
Any help would be greatly appreciated!

Exclude class from resulting dex file

I have a problem. I have a structure of project looking like this:
P
|-SubP1
|-SubP2
There are two stub classes android.media.IRemoteDisplay in both packages. They differ in implementation, but that's not the matter - they will be replaced by system classes when I'll run the app on Android.
However, there is a problem - I can't build the project because dexMerger fails - it says there are two conflicting classes. I can understand that error - after all, there are really two conflicting classes :)
But when I try to exclude these files in build.gradle like this:
sourceSets {
main {
java {
srcDir 'src'
exclude '**/android/media/**'
}
}
}
The compilation fails because it can't find android.media.IRemoteControlDisplay class(and it's nested classes).
How can I still use these classes, but exclude them from resulting DEX file?
Please DON'T question if it's right to exclude the class from compiled project - it's the right thing to do, I already did it, but manually - by pre-compiling SubP1 and SubP2 to jars and then manually removing IRemoteController.class from these jar files and then including those jars in P.
I'll also be satisfied with that solution:
1. Build SubP1
2. Remove IRemoteControlDisplay.class from SubP1.jar
3. Build SubP2
4. Remove IRemoteControlDisplay.class from SubP2.jar
5. Add SubP1.jar and SubP2.jar as dependencies to P
6. Build P
If that's possible, please let me know.
Finally, I've been able to do it.
What I needed was a runtime dependency instead of compilation-time dependency. So, I've created submodule for SubP1 called SubSubP1(for example) moved the android.media.IRemoteDisplay into the SubSubP1, and created submodule SubSubP2 for SubP2, and did the same with stub class. Then I've declared the dependency as following for SubP1 and SubP2:
dependencies {
provided project(':SubP1:SubSubP1')
}
and
dependencies {
provided project(':SubP2:SubSubP2')
}
And that did the trick! Instead of compiling the classes, Gradle assumed that they will be loaded at runtime.

Adding .so files to jniLibs in Android Studio: duplicate files during packaging of APK

Following various sets of instructions, it seems that I should add native libraries to app/src/main/jniLibs and they'll be linked up automagically. However when I do this (for OpenCV) I get the following:
Error:duplicate files during packaging of APK /.../app/build/outputs/apk/app-debug-unaligned.apk
Path in archive: lib/armeabi/libopencv_java.so
Origin 1: /.../app/src/main/jniLibs/armeabi/libopencv_java.so
Origin 2: /.../build/intermediates/exploded-aar/AppName/.libraries/opencv/unspecified/jni/armeabi/libopencv_java.so
You can ignore those files in your build.gradle:
android {
packagingOptions {
exclude 'lib/armeabi/libopencv_java.so'
}
}
Error:Execution failed for task ':app:packageDebug'.
> Duplicate files copied in APK lib/armeabi/libopencv_java.so
File 1: /.../app/src/main/jniLibs/armeabi/libopencv_java.so
File 2: /.../app/src/main/jniLibs/armeabi/libopencv_java.so
Adding the exclude section doesn't work. There's only one copy of the file, but somehow it's being referenced twice, and it seems the second (build) include is something auto-generated. What can I do?
In case of duplicate libraries (*.so) files, exclude option will not help as we cannot completely exclude the native binaries. There is one more option in packagingOptions. It is 'pickFirst'. We can avoid duplicate files error and include the first one the compiler encounters.
packagingOptions {
pickFirst 'lib/armeabi/libopencv_java.so'
}
ndk-build was generating duplicates of all of the packages from OpenCV. I removed all of the .so libraries from my app, apart from my actual app library, and then it packaged up fine.
I also had this issue. It seems it's because the documentation and various conversation threads on setting up OpenCV for Android say to put the JNI libraries at the path /src/main/jniLibs or /src/main/libs. The problem is that the /src/ folder is for source code, not libraries. The solution is to move the /main/ folder out of /src/ and into the project root, which is how Google documents this project structure: https://developer.android.com/tools/projects/index.html
I also have the following settings in build.gradle:
android {
sourceSets {
main {
jni.srcDirs = [] //disable automatic ndk-build call
jniLibs.srcDir 'main/libs'
}
}
}

Categories

Resources