3

I'm building a java application which uses Appium to automate a mobile app. I'm using Gradle to manage the dependencies.

The project compiles and builds the jar successfully but while obfuscating using gradle proguardtask, following errors are observed.

> Task :proguardTask
Note: there were 57 duplicate class definitions.
...
...
* Exception is:
org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':proguardTask'.
...
...
...
Caused by: org.gradle.api.UncheckedIOException: java.io.IOException: 
Can't write [/home/mmt/eclipse-workspace/MobileTest/build/libs/MobileTest-0.1-obfus.jar] 
(Can't read [/home/mmt/eclipse-workspace/MobileTest/build/libs/MobileTest-0.1.jar] 
(Duplicate jar entry [org/openqa/selenium/SearchContext.class]))

I tried excludeing the dependencies which are transitive with no luck.

Tried doing transitive = false and adding the transitive one manually still couldn't get the desired output.

Following is my build script.

build.gradle


    buildscript {
    repositories {
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath 'net.sf.proguard:proguard-gradle:6.1.1'
    }
    } plugins {
        id 'java'
        id 'maven-publish'
    }
    repositories {
        mavenLocal()
        maven {
            url = 'http://repo.maven.apache.org/maven2'
        }
    }
    dependencies {
        compile 'org.testng:testng:6.14.3'
        compile 'io.appium:java-client:6.1.0'
        compile 'org.apache.poi:poi:3.16'
        compile 'net.sourceforge.tess4j:tess4j:4.3.0'
        compile 'log4j:log4j:1.2.17'
        testCompile 'junit:junit:4.11'
    }

    group = 'com.mobile'
    version = '0.1'
    description = 'AppiumTest'
    sourceCompatibility = '1.8'

    publishing {
        publications {
            maven(MavenPublication) {
                from(components.java)
            }
        }
    }

    jar{
        from { configurations.compile.collect { zipTree(it) } }
        manifest {
            attributes 'Implementation-Title': 'Jar File with dependencies',  
                'Implementation-Version': version,
                'Main-Class': 'com.mobile.MobileTest.App'
        }
    }

    task proguardTask(type: proguard.gradle.ProGuardTask,dependsOn: jar) {
        configuration file('proguard.pro')
        injars 'build/libs/MobileTest-0.1.jar'
        outjars 'build/libs/MobileTest-0.1-obfus.jar'   
    }

    tasks.withType(JavaCompile) {
        options.encoding = 'UTF-8'
    }

    test {
        useTestNG()
    }

proguard.pro

-dontoptimize
-allowaccessmodification
-dontshrink
-dontwarn
-dontpreverify
-keepattributes Signature
-keepattributes Exceptions
-keep public class com.mobile.MobileTest.App {*;}
-keep class module-info{*;}

-keep public class com.beust.testng.**{*;}
-keep public interface com.beust.testng.**{*;}
-keep public enum com.beust.testng.**{*;}

-keep public class org.apache.log4j.**{*;}
-keep public interface org.apache.log4j.**{*;}
-keep public enum org.apache.log4j.**{*;}

-keep public class io.appium.java_client.**{*;}
-keep public interface io.appium.java_client.**{*;}
-keep public enum io.appium.java_client.**{*;}

-keep public class kobaltBuild.classes.**{*;}
-keep public interface kobaltBuild.classes.**{*;}
-keep public enum kobaltBuild.classes.**{*;}

-keep public class net.sourceforge.tess4j.**{*;}
-keep public interface net.sourceforge.tess4j.**{*;}
-keep public enum net.sourceforge.tess4j.**{*;}

-keep public class org.**{*;}
-keep public interface org.**{*;}
-keep public enum org.**{*;}

-keep public class scripts.**{*;}
-keep public interface scripts.**{*;}
-keep public enum scripts.**{*;}

-keep public class src.main.resources.**{*;}
-keep public interface src.main.resources.**{*;}
-keep public enum src.main.resources.**{*;}

-keep public class tessdata.**{*;}
-keep public interface tessdata.**{*;}
-keep public enum tessdata.**{*;}

-keep public class com.recognition.software.jdeskew.**{*;}
-keep public interface com.recognition.software.jdeskew.**{*;}
-keep public enum com.recognition.software.jdeskew.**{*;}

-keep public class bsh.**{*;}
-keep public interface bsh.**{*;}
-keep public enum bsh.**{*;}

-keep public class java.**{*;}
-keep public interface java.**{*;}
-keep public enum java.**{*;}

-keep public class javax.**{*;}
-keep public interface javax.**{*;}
-keep public enum javax.**{*;}

-keep public class org.**{*;}
-keep public interface org.**{*;}
-keep public enum org.**{*;}

Any pointer in the right direction is much appreciated.

Update

Find the repo here.

Purush Pawar
  • 4,263
  • 2
  • 29
  • 37
  • See if this helps https://stackoverflow.com/questions/29094573/androidstudio-gradle-build-proguard-duplicate-zip-entry-error and https://stackoverflow.com/questions/42889264/proguard-duplicate-zip-entry – Tarun Lalwani Jul 08 '19 at 06:39
  • I have to ask, why are you obfuscating your test code? You don't want test code packaged up in your APK/AAR anyway since it's extra size for no benefit. Test code should be readable so people understand what the tests are doing. – Ardesco Jul 08 '19 at 10:42
  • @TarunLalwani, already looked. Not much of help. – Purush Pawar Jul 08 '19 at 10:46
  • @Ardesco, I understand your concern. Here's the thing. I'm using Appium java client to create a jar to automate mobile applications. Not a particular application but any mobile application client throws at me. And hence it's a strict requirement at my end to obfuscate the jar. – Purush Pawar Jul 08 '19 at 10:46
  • Minimal git repo possible? – Tarun Lalwani Jul 08 '19 at 10:55
  • @TarunLalwani check the updated post. – Purush Pawar Jul 08 '19 at 12:10

1 Answers1

1

The jar task is allowing duplicate classes when packaging however progaurd does not allow that. Add the below to force the jar task to exclude duplicates:

jar {
    duplicatesStrategy = 'exclude'
    from { configurations.compile.collect { zipTree(it) } }
    ...
}

More info here: https://discuss.gradle.org/t/duplicated-classes-output-jar-with-gradle/17301

ahasbini
  • 6,761
  • 2
  • 29
  • 45