从DEX中排除JAR

时间:2014-11-03 16:26:29

标签: android apk dex

我想在运行时将一些类从APK加载到已经运行的服务中,但是我收到以下错误:

11-03 16:51:13.570  20227-20240/com.somecompany.android.core W/dalvikvm﹕ Class resolved by unexpected DEX: Lcom/somecompany/android/core/db/DatabaseManager;(0x2ce11280):0x392d6000 ref [Lcom/somecompany/android/core/CoreModule;] Lcom/somecompany/android/core/CoreModule;(0x2cdb1d20):0x38f40000
11-03 16:51:13.570  20227-20240/com.somecompany.android.core W/dalvikvm﹕ (Lcom/somecompany/android/core/db/DatabaseManager; had used a different Lcom/somecompany/android/core/CoreModule; during pre-verification)
11-03 16:51:13.570  20227-20240/com.somecompany.android.core W/dalvikvm﹕ Unable to resolve superclass of Lcom/somecompany/android/core/db/DatabaseManager; (720)
11-03 16:51:13.570  20227-20240/com.somecompany.android.core W/dalvikvm﹕ Link of class 'Lcom/somecompany/android/core/db/DatabaseManager;' failed
11-03 16:51:13.570  20227-20240/com.somecompany.android.core W/dalvikvm﹕ threadid=11: thread exiting with uncaught exception (group=0x2c7dbfc0)
11-03 16:51:13.570  20227-20240/com.somecompany.android.core E/com.somecompany.android.core.CoreApplication﹕ Thread com.somecompany.android.core.CoreService-80000000 has crashed
11-03 16:51:13.570  20227-20240/com.somecompany.android.core E/com.somecompany.android.core.CoreApplication﹕ java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
            at dalvik.system.DexFile.defineClass(Native Method)
            at dalvik.system.DexFile.loadClassBinaryName(DexFile.java:211)
            at dalvik.system.DexPathList.findClass(DexPathList.java:315)
            at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:58)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
            at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
            at com.somecompany.android.core.CoreModuleLoader.loadRegisterModules(CoreModuleLoader.java:56)
            at com.somecompany.android.core.CoreModuleLoader.load(CoreModuldeLoader.java:110)
            at com.somecompany.android.core.CoreService$1.run(CoreService.java:148)
            at java.lang.Thread.run(Thread.java:856)

我认为问题在于Android自动生成的APK会将所有服务类打包到APK中,这在加载时会导致问题,因为服务中已存在这些相同的类。该服务在编译时作为JAR链接。

如何修改构建过程以使Service JAR不包含在结果APK中?提前谢谢。

编辑:APK中的classes.dex确实有服务类。

编辑:这是用于DEX JAR的build.xml节点。不幸的是,我不知道ANT如何配置这个部分,任何帮助表示赞赏。

<!-- Configurable macro, which allows to pass as parameters output directory,
     output dex filename and external libraries to dex (optional) -->
<macrodef name="dex-helper">
    <element name="external-libs" optional="yes" />
    <attribute name="nolocals" default="false" />
    <sequential>
        <!-- sets the primary input for dex. If a pre-dex task sets it to
             something else this has no effect -->
        <property name="out.dex.input.absolute.dir" value="${out.classes.absolute.dir}" />

        <!-- set the secondary dx input: the project (and library) jar files
             If a pre-dex task sets it to something else this has no effect -->
        <if>
            <condition>
                <isreference refid="out.dex.jar.input.ref" />
            </condition>
            <else>
                <path id="out.dex.jar.input.ref">
                    <path refid="project.all.jars.path" />
                </path>
            </else>
        </if>

        <dex executable="${dx}"
                output="${intermediate.dex.file}"
                dexedlibs="${out.dexed.absolute.dir}"
                nolocals="@{nolocals}"
                forceJumbo="${dex.force.jumbo}"
                disableDexMerger="${dex.disable.merger}"
                verbose="${verbose}">
            <path path="${out.dex.input.absolute.dir}"/>
            <path refid="out.dex.jar.input.ref" />
            <external-libs />
        </dex>
    </sequential>
</macrodef>

1 个答案:

答案 0 :(得分:1)

正如here所述,我创建了一个compile-libs/文件夹,并将服务JAR移到那里(将其从libs/中删除)。然后我创建了一个custom_build.xml并将此JAR仅用于编译(不适用于dexing)。

<?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>

这似乎解决了问题,因为生成的DEX没有来自Service JAR的类。

编辑:进一步测试证实它按预期工作。