Advanced Android - Excluding JARs from APK


Advanced development in Android (specially APKs as plugins) sometimes requires that you build an APK without including a certain JARs, but of course these JARs are needed for compiling. This is usually because this APK is going to be loaded on another VM that already contains these classes. If the class loader has 2 implementations for the same class, it will complain:

Class resolved by unexpected DEX: Lcom/somecompany/android/core/db/DatabaseManager;
0x2ce09600):0x392d6000 ref [Lcom/somecompany/android/core/CoreModule;]
Lcom/somecompany/android/core/CoreModule;(0x2cdb0160):0x38f40000
(Lcom/somecompany/android/core/db/DatabaseManager; had used a different
Lcom/somecompany/android/core/CoreModule; during pre-verification)
Unable to resolve superclass of Lcom/somecompany/android/core/db/DatabaseManager; (720)
Link of class 'Lcom/somecompany/android/core/db/DatabaseManager;' failed
thread exiting with uncaught exception (group=0x2c7dbfc0) 

So to avoid this problem, we can customize our build process to include this JAR in the compiling process but exclude it from the DEX-ing process. I will detail how to acheive this with ant, by including the conflicting JARs only during the compilation process and not during linkage. I assume your project is already configured to build with ant.
  1. Create a new folder for the JARs, which we'll call compile-libs, that you want to use to compile but not to include in APK. Move all JARs that are only for compilation there (remove them from any other directory).

  2. Create an XML in the root of your project (where build.xml is), call it custom_build.xml, and edit it with the following:

    <?xml version="1.0" encoding="UTF-8"?>
    <project name="custom_rules">

         <path id="java.compiler.classpath.path">
             <fileset dir="compile-libs" includes="*.jar" />
         </path>
         <property name="java.compiler.classpath" refid="java.compiler.classpath.path" />

    </project>

    As you can see, this will add all JARs in our compile-libs directory to the classpath of the Java compiler, but since these JARs are not in libs, they will not be included for dexing.
And that's it. Now you can run ant debug and check that the APK's classes.dex does not contain the excluded JARs (you can for example search for their class name with an hexadecimal editor).

I hope you found this helpful, any comments are welcome.

Comments

Popular Posts