如何在android gradle构建文件中为从maven Central提取的库指定injars

Posted

技术标签:

【中文标题】如何在android gradle构建文件中为从maven Central提取的库指定injars【英文标题】:how to specify injars for proguard within android gradle build files for libraries that are pulled from maven central 【发布时间】:2013-08-29 22:30:16 【问题描述】:

有没有办法将从 maven Central 中提取的库作为 proguard 的 injars 传递?我希望他们被混淆。上下文:remove unused classes with proguard for android

【问题讨论】:

您找到解决方案了吗? 【参考方案1】:

我从未使用过 Maven,而我正在使用 Gradle,但无论是构建系统,我相信同样适用。而且我不认为你想要什么是可能的......

-injars 关键字特定于 ProGuard 配置文件,它是构建工具读取的文本文件。

我看到的唯一方法是,如果您构建某种脚本,它将为您服务。也就是说,读取所有 Maven 依赖项,创建适当的 ProGuard 配置文件,指定所有必需的 -injars 并将其传递给构建过程。不确定这对 Maven 是否可行。

使用 Gradle 应该不会太难。使用 Gradle,您可以轻松传递多个 ProGuard 配置文件,您只需在 build.gradle 文件中创建一个方法以从依赖项中获取所有 .jar 文件位置,并创建一个临时文本文件,然后将其传递到 ProGuard 配置中。

我假设同样的过程也适用于 Maven,但同样,我从未使用过它。

【讨论】:

【参考方案2】:

编辑:我现在看到 Gradle 专门提出的问题。我的回答是针对 Ant,但它可能会给你一些想法。

完整的解决方案包括以下步骤:

    创建自定义 build.xml 复制并修改“混淆”目标以使用 injars 使用 Maven 放置它们的目录中的 injars 自动化 Maven 以将 jar 放入目录中。 这就是我迷路的地方。 gradle/maven 经验不足。

详细步骤:

1。自定义 build.xml

在build.xml中,放入“custom”,如下:

<!-- version-tag: custom -->
<import file="$sdk.dir/tools/ant/build.xml" />

在此位之前,插入以下代码,或将其放入单独的文件 (general-build.xml) 并将其导入 build.xml。

2。目标

插入以下内容:

<!-- Obfuscate target
    This is only active in release builds when proguard.config is defined
    in default.properties.

    To replace Proguard with a different obfuscation engine:
    Override the following targets in your build.xml, before the call to <setup>
        -release-obfuscation-check
            Check whether obfuscation should happen, and put the result in a property.
        -debug-obfuscation-check
            Obfuscation should not happen. Set the same property to false.
        -obfuscate
            check if the property set in -debug/release-obfuscation-check is set to true.
            If true:
                Perform obfuscation
                Set property out.dex.input.absolute.dir to be the output of the obfuscation
-->
<target name="-obfuscate">
    <if condition="$proguard.enabled">
        <then>
            <property name="obfuscate.absolute.dir" location="$out.absolute.dir/proguard" />
            <property name="preobfuscate.jar.file" value="$obfuscate.absolute.dir/original.jar" />
            <property name="obfuscated.jar.file" value="$obfuscate.absolute.dir/obfuscated.jar" />
            <!-- input for dex will be proguard's output -->
            <property name="out.dex.input.absolute.dir" value="$obfuscated.jar.file" />

            <!-- Add Proguard Tasks -->
            <property name="proguard.jar" location="$android.tools.dir/proguard/lib/proguard.jar" />
            <taskdef name="proguard" classname="proguard.ant.ProGuardTask" classpath="$proguard.jar" />

            <!-- Set the android classpath Path object into a single property. It'll be
                 all the jar files separated by a platform path-separator.
                 Each path must be quoted if it contains spaces.
            -->
            <pathconvert property="project.target.classpath.value" refid="project.target.class.path">
                <firstmatchmapper>
                    <regexpmapper from='^([^ ]*)( .*)$$' to='"\1\2"'/>
                    <identitymapper/>
                </firstmatchmapper>
            </pathconvert>

            <!-- Build a path object with all the jar files that must be obfuscated.
                 This include the project compiled source code and any 3rd party jar
                 files. -->
            <path id="project.all.classes.path">
                <pathelement location="$preobfuscate.jar.file" />
                <path refid="project.all.jars.path" />
            </path>
            <!-- Set the project jar files Path object into a single property. It'll be
                 all the jar files separated by a platform path-separator.
                 Each path must be quoted if it contains spaces.
            -->
            <pathconvert property="project.all.classes.value" refid="project.all.classes.path">
                <firstmatchmapper>
                    <regexpmapper from='^([^ ]*)( .*)$$' to='"\1\2"'/>
                    <identitymapper/>
                </firstmatchmapper>
            </pathconvert>

            <!-- Turn the path property $proguard.config from an A:B:C property
                 into a series of includes: -include A -include B -include C
                 suitable for processing by the ProGuard task. Note - this does
                 not include the leading '-include "' or the closing '"'; those
                 are added under the <proguard> call below.
            -->
            <path id="proguard.configpath">
                <pathelement path="$proguard.config"/>
            </path>
            <pathconvert pathsep='" -include "' property="proguard.configcmd" refid="proguard.configpath"/>


            <!--  INSERT SOME MAVEN STORAGE DIR BELOW -->
            <echo level="info">PROJECT.ALL.CLASSES.VALUE === $project.all.classes.value</echo>
            <echo level="info">PROJECT.TARGET.CLASSPATH.VALUE === $project.target.classpath.value</echo>
            <property name="project.all.classes.value2" value="$project.all.classes.value:/some-maven-dir"/>
            <echo level="info">PROJECT.ALL.CLASSES.VALUE2 === $project.all.classes.value2</echo>

            <mkdir   dir="$obfuscate.absolute.dir" />
            <delete file="$preobfuscate.jar.file"/>
            <delete file="$obfuscated.jar.file"/>
            <jar basedir="$out.classes.absolute.dir"
                destfile="$preobfuscate.jar.file" />
            <proguard>
                -include      "$proguard.configcmd"
                -include      "$out.absolute.dir/proguard.txt"
                -injars       $project.all.classes.value2
                -outjars      "$obfuscated.jar.file"
                -libraryjars  $project.target.classpath.value(!META-INF/MANIFEST.MF,!META-INF/NOTICE.txt,!META-INF/LICENSE.txt)
                -dump         "$obfuscate.absolute.dir/dump.txt"
                -printseeds   "$obfuscate.absolute.dir/seeds.txt"
                -printusage   "$obfuscate.absolute.dir/usage.txt"
                -printmapping "$obfuscate.absolute.dir/mapping.txt"
                -printconfiguration "$obfuscate.absolute.dir/used_config.txt"
            </proguard>
        </then>
    </if>
</target> 

另一种方法是仅在 jar 中临时复制(相同的技术用于不是 Android 库项目的常规 Java 项目依赖项):

<property name="lib.javalib1.project.dir" location="$basedir/../../some-maven-dir" />

<target name="-pre-build">
  <subant buildpath="$lib.javalib1.project.dir" target="package" failonerror="true" />
  <copy todir="$basedir/libs" failonerror="true" verbose="true">
      <fileset dir="$lib.javalib1.project.dir/bin">
          <filename name="general-api.jar"/>
      </fileset>
  </copy>
</target>
<target name="-post-package">
    <delete verbose="true">
        <fileset dir="$basedir/libs" includes="general-api.jar" />
    </delete>
</target>

但是它会一个一个地编译jar并复制它们,所以对于已经有jar的Maven来说,这是一个劣势。

3。 Maven 目录

“/some-maven-dir”是存放jar的目录。

4。 Maven 自动化

在这里我无能为力,但我对第一部分提出了建议。也许有人可以继续这样做。

【讨论】:

以上是关于如何在android gradle构建文件中为从maven Central提取的库指定injars的主要内容,如果未能解决你的问题,请参考以下文章

构建 Gradle 时出现问题(无法创建任务 ':path_provider_android:generateDebugUnitTestConfig')。在颤振中为 android

如何在 build.gradle 中为不同的 productFlavors 定义 android:label

可以在gradle中为每个ABI设置cmake参数吗?

如何在intelliJ IDEA中为我现有的Kotlin项目生成build.gradle文件

如何在Android Studio中为Gradle设置apk的应用名称

在 Android Gradle 构建中,如何从包含的 jar 文件中排除依赖项?