I have an Android library project and an app, which uses that library project. In the app's build.gradle file I have ProGuard obfuscate the whole app including the library project code:
//from the app project
buildTypes{
release {
runProguard true
proguardFile 'proguard-project.txt'
}
debug{
runProguard false
}
}
All works well, the lib project and the app project both get obfuscated just fine.
However, I want to build my lib project "standalone", so I can distribute it without the app project. This of course means obfuscating the lib project on its own.
I cannot do this by using the buildTypes code in the lib-projects build.gradle and simply running proGuard, since this would break the app-project build, because then building the app would compile its code agains already-obfuscated lib-project code... :-)
What I need is a possibility to run ProGuard only if I build the lib-project in "standalone" mode, e.g. by passing a parameter, or executing a special task.
Can anyone point me in the right direction?
solved it myself. In the lib-project's build file I have two buildtypes and I publish them both:
publishNonDefault true
and the build types:
buildTypes {
debug {
debuggable true
runProguard false
}
release {
runProguard true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt'
}
}
this causes the debug and release APK to be created. In my app project's build file I then add an explicit dependency to the debug configuration by stating the dependency as follows:
dependencies{
compile project(path: ':FancyLibProject', configuration: 'debug')
//...
}
Of course in the app-project I also have two build types debug and release, which in turn invoke ProGuard in the same way as for the lib-project.
Note: I omitted the signing configs for the release build - without those the APK will cannot be installed!
Related
I'm trying to figure out why I can't get a release build to install correctly using Android Studio. This is my buildTypes block:
buildTypes {
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
release {
shrinkResources false
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
and these are my product flavors:
flavorDimensions "version"
productFlavors {
free {
applicationId "com.example.app.free"
dimension "version"
signingConfig signingConfigs.config
}
paid {
applicationId "com.example.app.paid"
dimension "version"
signingConfig signingConfigs.config
}
}
When I install the debug paid or free versions, all is fine and dandy. Nothing wrong at all. When I try to install the release versions (paid or free) I'm getting:
'Execution failed for task ':app:transformDexArchiveWithDexMergerForFreeRelease'. com.android.build.api.transform.TransformException: java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: ... Learn how to resolve the issue at https://developer.android.com/studio/build/dependencies#duplicate_classes. Program type already present: com.google.android.youtube.player.YouTubeApiServiceUtil'
My questions is this: Why is the duplicate class exception happening only during release, when I have nothing different defined between the release and debug buildTypes?
EDIT I've solved the issue by removing the YouTubePlayer Library dependency in gradle (b/c apparently my implementation of the google YT service was causing an internal library to be created, so depending on the imported one was redundant?). This still leaves my question valid. Why did the debug work, but not the release when nothing was declared differently?
I had the same issue when linking with another module when I added another (indirect) dependency on its assemble (it was Protobuf module which needs to generate Java files from .proto files before the app module can generate its JSON model). It seems that assembleRelease optimises the code in a way that it may generate slightly different class file depending on where it is called from and the Dex merger then cannot decide which of the class files to use. assembleDebug generates always the same (unoptimised) code which it can merge.
(For anyone having the same problem with Protobuf, the solution for that is to depend on :protobuf:GenerateProto instead of :protobuf:assemble.)
Android libraries, per the AAR file spec, includes a 'proguard.txt' file.
My understanding is that this file declares how the library correctly can be obfuscated and minified. In my case I need to preserve some API-classes.
How can I declare the library's proguard.txt file in the library's build.gradle? And will this file be automatically read when creating an application (APK) that uses my library?
I didn't find this information in Android's Gradle Plugin User Guide.
In your Gradle file's default configuration closure, specify your Proguard file with consumerProguardFiles instead of proguardFiles. For example:
defaultConfig {
consumerProguardFiles 'proguard.txt'
}
ProGuard artefact
[ProGuard workflow]
Artefact not minified, Consumer solve it
Library is open-sourced but as a library developer you can provide a ProGuard file which will be take into account by consumer(app) by demand(minifyEnabled true in consumer). consumerProguardFiles in you library build.gradle. It adds proguard.txt file(is the same as .pro) in an artefact
For example your library is open-source and application developer wants to minify all
android {
defaultConfig {
//consumerProguardFiles '<file_path>'
consumerProguardFiles 'proguard-rules.pro'
}
buildTypes {
release {
minifyEnabled false
}
}
//...
}
Artefact is minified
Library is closed-source - you are able to use the next possibility:
android {
buildTypes {
release {
minifyEnabled true
//proguardFiles project(':<project_name>').file('<file_path>')
proguardFiles 'proguard-rules.pro'
}
}
//...
}
*Please note that:
minifyEnabled true and proguardFiles project both should be set.
If you use single minifyEnabled true or <file_path> is wrong - classes.jar is empty.
If single proguardFiles project - no effect
As for build process on the example of library - application - all .class files will be merged into single archive with .dex extension
Android libraries, per the AAR file spec, includes a 'proguard.txt' file.
My understanding is that this file declares how the library correctly can be obfuscated and minified. In my case I need to preserve some API-classes.
How can I declare the library's proguard.txt file in the library's build.gradle? And will this file be automatically read when creating an application (APK) that uses my library?
I didn't find this information in Android's Gradle Plugin User Guide.
In your Gradle file's default configuration closure, specify your Proguard file with consumerProguardFiles instead of proguardFiles. For example:
defaultConfig {
consumerProguardFiles 'proguard.txt'
}
ProGuard artefact
[ProGuard workflow]
Artefact not minified, Consumer solve it
Library is open-sourced but as a library developer you can provide a ProGuard file which will be take into account by consumer(app) by demand(minifyEnabled true in consumer). consumerProguardFiles in you library build.gradle. It adds proguard.txt file(is the same as .pro) in an artefact
For example your library is open-source and application developer wants to minify all
android {
defaultConfig {
//consumerProguardFiles '<file_path>'
consumerProguardFiles 'proguard-rules.pro'
}
buildTypes {
release {
minifyEnabled false
}
}
//...
}
Artefact is minified
Library is closed-source - you are able to use the next possibility:
android {
buildTypes {
release {
minifyEnabled true
//proguardFiles project(':<project_name>').file('<file_path>')
proguardFiles 'proguard-rules.pro'
}
}
//...
}
*Please note that:
minifyEnabled true and proguardFiles project both should be set.
If you use single minifyEnabled true or <file_path> is wrong - classes.jar is empty.
If single proguardFiles project - no effect
As for build process on the example of library - application - all .class files will be merged into single archive with .dex extension
I am trying to export signed apk, obfuscated with proguard. But after process, I can see my code and my class names in decompiler tool. Spent 1 day , but can't understand what I missed.
In my gradle file I specified :
buildTypes {
release {
apply plugin: 'maven'
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
proguard-rules.pro is empty.
Should I specify anything else to enable proguarding ? After decompilation
Change minifyEnabled to true to enable proguard in your build configuration.
I am trying to integrate proguard into my project and in the build.gradle I have the following declaration for build type. When I try to compile I get the following error:
java.io.FileNotFoundException
/Users/admin/Desktop/enviornment/android/sdks/tools/proguard/proguard-project.txt
(No such file or directory).
Note: I have also tried "proguard-android.txt" and same error persists. Also I have looked in the 'tools' folder and there is no proguard folder, how can I include it properly and is there another location to point to?
buildTypes {
release {
runProguard true
proguardFiles getDefaultProguardFile('proguard-project.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}