web-dev-qa-db-ja.com

Android proguardを使用してアプリを難読化すると、ライブラリjarが難読化され続けます-またはそれですか?

私はProguardを使うのが初めてなので、たぶん初心者の間違いを犯しています。リリースビルド(Proguardを使用して難読化する)を実行すると、すぐにクラッシュするアプリがあります。私はそれが私の参照ライブラリを難読化しているように見えるという事実にそれを絞り込んだと信じています。私の場合、参照ライブラリを使用して、Google Protobuffersを使用して別のデバイスと通信するために使用しているメッセージクラスを定義しています。私は、antリリースを使用してビルドしています。私のプロガード構成は次のとおりです。

-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontpreverify
-verbose
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

-keep public class * extends Android.app.Activity
-keep public class * extends Android.app.Application
-keep public class * extends Android.app.Service
-keep public class * extends Android.content.BroadcastReceiver
-keep public class * extends Android.content.ContentProvider
-keep public class * extends Android.app.backup.BackupAgentHelper
-keep public class * extends Android.preference.Preference
-keep public class com.Android.vending.licensing.ILicensingService

-keepclasseswithmembernames class * 
 {
    native <methods>;
 }

-keepclasseswithmembernames class * 
 {
    public <init>(Android.content.Context, Android.util.AttributeSet);
 }

-keepclasseswithmembernames class * 
 {
    public <init>(Android.content.Context, Android.util.AttributeSet, int);
 }

-keepclassmembers enum * 
 {
    public static **[] values();
    public static ** valueOf(Java.lang.String);
 }

-keep class * implements Android.os.Parcelable 
 {
    public static final Android.os.Parcelable$Creator *;
 }

私のant build.xmlファイルには、次のものが定義されています。

<target name="-obfuscate" unless="do.not.compile">
    <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.
            -->
            <property name="Android.libraryjars" refid="Android.target.classpath"/>

            <!-- 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.jars.ref">
                <pathelement location="${preobfuscate.jar.file}" />
                <path refid="jar.libs.ref" />
            </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.
            -->
            <property name="project.jars" refid="project.jars.ref" />

            <mkdir  dir="${obfuscate.absolute.dir}" />
            <delete file="${preobfuscate.jar.file}" />
            <delete file="${obfuscated.jar.file}"   />
            <jar basedir="${out.classes.dir}" destfile="${preobfuscate.jar.file}" />
            <proguard>
                @${proguard.config}
                -injars ${project.jars}
                -outjars ${obfuscated.jar.file}
                -libraryjars ${Android.libraryjars}
                -dump ${obfuscate.absolute.dir}/dump.txt
                -printseeds ${obfuscate.absolute.dir}/seeds.txt
                -printusage ${obfuscate.absolute.dir}/usage.txt
                -printmapping ${obfuscate.absolute.dir}/mapping.txt
            </proguard>
        </then>
    </if>
</target>

<!-- Converts this project's .class files into .dex files -->
<target name="-dex" depends="compile, -post-compile, -obfuscate"
        unless="do.not.compile">
    <if condition="${manifest.hasCode}">
        <then>
            <dex-helper />
        </then>
        <else>
            <echo>hasCode = false. Skipping...</echo>
        </else>
    </if>
</target>

<!-- Puts the project's resources into the output package file
     This actually can create multiple resource package in case
     Some custom apk with specific configuration have been
     declared in default.properties.
     -->
<target name="-package-resources">
    <echo>Packaging resources</echo>
    <aapt executable="${aapt}"
            command="package"
            versioncode="${version.code}"
            debug="${build.packaging.debug}"
            manifest="AndroidManifest.xml"
            assets="${asset.absolute.dir}"
            androidjar="${Android.jar}"
            apkfolder="${out.absolute.dir}"
            resourcefilename="${resource.package.file.name}"
            resourcefilter="${aapt.resource.filter}">
        <res path="${resource.absolute.dir}" />
        <!-- <nocompress /> forces no compression on any files in assets or res/raw -->
        <!-- <nocompress extension="xml" /> forces no compression on specific file extensions in assets and res/raw -->
    </aapt>
</target>

<!-- Packages the application and sign it with a debug key. -->
<target name="-package-debug-sign" depends="-dex, -package-resources">
    <package-helper
            output.filepath="${out.debug.unaligned.file}" />
</target>

<!-- Packages the application without signing it. -->
<target name="-package-release" depends="-dex, -package-resources">
    <package-helper
            output.filepath="${out.unsigned.file}"/>
</target>
    <target name="-set-release-mode">
        <!-- release mode is only valid if the manifest does not explicitly
             set debuggable to true. default is false.
             We actually store build.packaging.debug, not build.release -->
        <xpath input="AndroidManifest.xml" expression="/manifest/application/@Android:debuggable"
               output="build.packaging.debug" default="false"/>

        <!-- Enable proguard -->
        <property name="proguard.enabled" value="true"/>
        <property name="proguard.config" value="proguard.cfg"/>

        <!-- signing mode: release -->
        <property name="build.signing.debug" value="false" />

        <if condition="${build.packaging.debug}">
            <then>
                <echo>*************************************************</echo>
                <echo>****  Android Manifest has debuggable=true   ****</echo>
                <echo>**** Doing DEBUG packaging with RELEASE keys ****</echo>
                <echo>*************************************************</echo>
            </then>
            <else>
                <!-- property only set in release mode.
                     Useful for if/unless attributes in target node
                     when using Ant before 1.8 -->
                <property name="build.mode.release" value="true"/>
            </else>
        </if>
    </target>

    <target name="release"
            depends="-set-release-mode, -release-obfuscation-check, -package-release, -release-Prompt-for-password, -release-nosign"
                if="has.keystore"
                description="Builds the application. The generated apk file must be signed before
                            it is published.">
        <!-- Signs the APK -->
        <echo>Signing final apk...</echo>
        <signjar
                jar="${out.unsigned.file}"
                signedjar="${out.unaligned.file}"
                keystore="${key.store}"
                storepass="${key.store.password}"
                alias="${key.alias}"
                keypass="${key.alias.password}"
                verbose="${verbose}" />

        <!-- Zip aligns the APK -->
        <zipalign-helper in.package="${out.unaligned.file}"
                                   out.package="${out.release.file}" />
        <echo>Release Package: ${out.release.file}</echo>
    </target>

アイデアをいただければ幸いです。ほとんどのビルドとproguardの設定をオンラインテンプレートからコピーしましたが、実際にライブラリjarを難読化するようにProguardに指示しているのか、またはlisconfiguredがあります。ビルドの最後に、cmdウィンドウに次の出力が表示されます。

[proguard] Writing output...
[proguard] Preparing output jar [C:\Workspace\UI\MyApp\build\proguard\obfuscated.jar]
[proguard]   Copying resources from program jar [C:\Workspace\UI\MyApp\build\proguard\original.jar]
[proguard]   Copying resources from program jar [C:\Workspace\UI\MyApp\libs\libmessaging.jar]
[proguard] Warning: can't write resource [META-INF/MANIFEST.MF] (Duplicate Zip entry [libmessaging.jar:META-INF/MANIFEST.MF])
[proguard]   Copying resources from program jar [C:\Workspace\UI\MyApp\libs\protobuf-2.3.0.jar]
[proguard] Warning: can't write resource [META-INF/MANIFEST.MF] (Duplicate Zip entry [protobuf-2.3.0.jar:META-INF/MANIFEST.MF])
[proguard] Printing classes to [C:\Workspace\Riptide1_1_ptr_74\WPG_HAWKSBILL\UI\MyApp\build\proguard\dump.txt]...

ありがとう!

25
bursk

Proguard構成でライブラリjarディレクティブをコメントしました。
変化する:

# -libraryjars /libs/protobuf-2.3.0.jar
# -libraryjars /libs/libmessaging.jar

に:

-libraryjars /libs/protobuf-2.3.0.jar
-libraryjars /libs/libmessaging.jar

(そして、build.xmlでライブラリjarを定義する必要はありません)

編集:
Proguardでライブラリjarをそのままにする別の方法は、パッケージ名を保持するように依頼することでした。たとえば:

-keep class javax.** { *; }
-keep class org.** { *; }
-keep class Twitter4j.** { *; }
45
Caspar Harmer

ProGuardがjsoup libを暗号化したときに同様の問題が発生しました。 proguard-rules.txtに以下を追加して修正しました:

-keep class org.jsoup** {
    *;
}

build.gradleは次のセクションになります。

release {
    minifyEnabled true
    proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.txt'
}
2
Percy Vega