【问题标题】:Android signing with Ant使用 Ant 进行 Android 签名
【发布时间】:2011-12-23 14:22:40
【问题描述】:

使用 Ant,我正在尝试以发布模式构建 Android 应用程序以进行分发。我的问题是在签名过程中。我已经使用导出 Android 应用程序向导通过 Eclipse 创建了一个密钥库和别名,如果通过 Eclipse 导出它,则该应用程序已正确签名。当我尝试通过 Ant 完成相同的过程时,我在 build.properties 文件中引用了我的密钥库和别名:

key.store=C:\\Users\\a512091\\.android\\release.keystore
key.alias=application
key.store.password=android
key.alias.password=android

构建过程成功,我得到一个 Application-release.apk 文件。我用 jarsigner 验证了这个 APK,所有文件都有“sm”标签。这是输出的尾部:

jar verified.
Warning:
This jar contains entries whose certificate chain is not validated.

当我尝试将此 APK 安装到模拟器或设备中时,我得到以下信息:

Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]

Logcat 显示我的 CSS 文件和图像资产的签名问题:

11-07 11:06:20.060: WARN/PackageParser(58): Exception reading assets/www/css/base.css in /data/app/vmdl48898.tmp
11-07 11:06:20.060: WARN/PackageParser(58): java.lang.SecurityException: META-INF/XXXXX.SF has invalid digest for assets/www/res/droidhdpi/favorite_off.png in /data/app/vmdl48898.tmp
11-07 11:06:20.060: WARN/PackageParser(58):     at java.util.jar.JarVerifier.verifyCertificate(JarVerifier.java:369)
11-07 11:06:20.060: WARN/PackageParser(58):     at java.util.jar.JarVerifier.readCertificates(JarVerifier.java:272)
11-07 11:06:20.060: WARN/PackageParser(58):     at java.util.jar.JarFile.getInputStream(JarFile.java:392)
11-07 11:06:20.060: WARN/PackageParser(58):     at android.content.pm.PackageParser.loadCertificates(PackageParser.java:337)
11-07 11:06:20.060: WARN/PackageParser(58):     at android.content.pm.PackageParser.collectCertificates(PackageParser.java:508)
11-07 11:06:20.060: WARN/PackageParser(58):     at com.android.server.PackageManagerService.installPackageLI(PackageManagerService.java:5885)
11-07 11:06:20.060: WARN/PackageParser(58):     at com.android.server.PackageManagerService.access$2100(PackageManagerService.java:134)
11-07 11:06:20.060: WARN/PackageParser(58):     at com.android.server.PackageManagerService$5.run(PackageManagerService.java:4743)
11-07 11:06:20.060: WARN/PackageParser(58):     at android.os.Handler.handleCallback(Handler.java:587)
11-07 11:06:20.060: WARN/PackageParser(58):     at android.os.Handler.dispatchMessage(Handler.java:92)
11-07 11:06:20.060: WARN/PackageParser(58):     at android.os.Looper.loop(Looper.java:123)
11-07 11:06:20.060: WARN/PackageParser(58):     at android.os.HandlerThread.run(HandlerThread.java:60)
11-07 11:06:20.069: ERROR/PackageParser(58): Package com.xxxxx.xxxxx has no certificates at entry assets/www/css/base.css; ignoring!

【问题讨论】:

    标签: android ant


    【解决方案1】:

    如果您(像我一样)被 1.8.3 和 Java 7 之前的 Ant 版本卡住,这里有一个解决方法:

    <exec executable="${java.bin.path}/jarsigner">
      <arg value="-signedjar"/>
      <arg value="signed-${app.apk.name}"/>
      <arg value="-keystore"/>
      <arg value="my.keystore"/>
      <arg value="-storepass"/>
      <arg value="passwd"/>
      <arg value="-sigalg"/>
      <arg value="MD5withRSA"/>
      <arg value="-digestalg"/>
      <arg value="SHA1"/>
      <arg value="${app.apk.name}"/>
      <arg value="my_keystore"/>
    </exec>
    
    <!-- Where old version was: -->
    
    <signjar
      alias="my_keystore" keystore="my.keystore"
      storepass="passwd"
      preservelastmodified="true"
      signedjar="signed-${app.apk.name}">
      <path>
      <fileset dir="." includes="${app.apk.name}" />
      </path>
    </signjar>
    

    【讨论】:

      【解决方案2】:

      使用Ubuntu 14.04 (Trusty Tahr) 和 Windows,创建一个“.keystore”文件。

      这个文件需要生成,可以用Java自带的keytool命令来完成。它通常可以在“C:\Program Files\Java\jre7\bin”中找到。这也必须添加到您的 PATH 变量中。

      转到项目的根目录并使用以下命令:

      生成 .keystore 文件:

      $ keytool -genkey -v -keystore key-name.keystore -alias alias-name -keyalg RSA -keysize 2048 -validity 10000
      

      在“platforms/android/”文件夹中创建一个名为 ant.properties 的文件 ant.properties。

      key.store=D:\\path\\to\\the\\project\\keyname.keystore
      key.alias=alias-name
      

      创建构建 APK 文件:

      $ cordova build android --release
      

      【讨论】:

        【解决方案3】:

        根据Android developer documentation,您应该将这些属性放在 ant.properties 文件中:

        $ cat ant.properties
        key.store=C:\\Users\\a512091\\.android\\release.keystore
        key.alias=application
        key.store.password=android
        key.alias.password=android
        

        【讨论】:

          【解决方案4】:

          如果您的 Ant 版本 ant -version),请尝试使用此方法解决 JDK 7 的问题(基于之前的答案):

          1. 将signjarjdk7添加到ANDROID_SDK\tools\ant\build.xml

            <macrodef name="signjarjdk7">
                <attribute name="jar" />
                <attribute name="signedjar" />
                <attribute name="keystore" />
                <attribute name="storepass" />
                <attribute name="alias" />
                <attribute name="keypass" />
                <attribute name="verbose" />
                <sequential>
                    <exec executable="jarsigner" failonerror="true">
                        <!-- Magic key, always verbose -->
                        <arg line="-verbose -digestalg SHA1 -sigalg MD5withRSA" />
                        <arg line="-keystore @{keystore} -storepass @{storepass} -keypass @{keypass}" />
                        <arg line="-signedjar &quot;@{signedjar}&quot;" />
                        <arg line="&quot;@{jar}&quot; @{alias}" />
                    </exec>
                </sequential>
            </macrodef>
            
          2. 将同一 build.xml 中 'release' 目标中的 'signjar' 替换为 'signjarjdk7'

          注意:您必须为您的项目定义 'key.store.password''key.alias.password' 属性(在 project.properties 或本地.properties)。

          更新 1:

          如果您安装了 Ant 1.8.3(或更高版本),您有更好的解决方案:

          打开您的 ANDROID_SDK\tools\ant\build.xml 并在原始“signjar”调用中添加两个新参数 - sigalg 和 digestalg:

          <signjar
              sigalg="MD5withRSA"
              digestalg="SHA1"
              jar="${out.packaged.file}"
              signedjar="${out.unaligned.file}"
              keystore="${key.store}"
              storepass="${key.store.password}"
              alias="${key.alias}"
              keypass="${key.alias.password}"
              verbose="${verbose}" />
          

          更新 2: 在最新版本的 Android SDK 工具中将“signjar”替换为“signapk”后,似乎不推荐使用此答案。

          【讨论】:

          • 应该如何考虑verbose属性?现在总是设置详细标志。
          • "verbose" 只需要轻松替换原来的 'signjar' 目标。
          • 您能否提供有关您的 1.8.3+ 解决方案的更多信息。这些变量是什么?我从哪里得到他们的价值观?
          • @Guy,您应该更新标准 ANDROID_SDK\tools\ant\build.xml 中现有的“signjar”目标。此值在“ant debug”或“ant release”期间在内部初始化。我已经更新了我的答案。
          • 我正在使用 ant-1.8.4 但在 build.xml 中我没有找到“signjar”目标。我应该在哪里添加这个?我应该从哪里调用这个目标?
          【解决方案5】:

          长期解决方案是修补 Ant 的 signjar 任务:

          https://issues.apache.org/bugzilla/show_bug.cgi?id=52344

          新属性已添加到 Ant 1.8.3 中的 signjar 中,但尚未修改 Android 的构建脚本(截至 r19)以使用它们:

          http://code.google.com/p/android/issues/detail?id=19567

          与此同时,“presetdef”可能会提供一种解决方法:

           <presetdef name="signjar">
            <signjar sigalg="MD5withRSA" digestalg="SHA1" />
           </presetdef>
          

          【讨论】:

          • 抱歉重复评论。试图增加我得到答复的几率。这让我很困惑,因为在developer.android.com/tools/publishing/app-signing.html#signapp 他们说要使用-sigalg SHA1withRSA -digestalg SHA1。为什么我们使用 MD5withRSA?
          • 解决方法 -sigalg=MD5withRSA 指定了 Java 6 中 jarsigner 的 RSA 默认值。此默认值在 Java 7 中更改为 SHA256withRSA,但是,Android 不支持此设置。 SHA1withRSA 是一个更安全的选项,(显然)在 Android 上受支持,因此更可取。
          【解决方案6】:

          听起来您可能正在使用 JDK 7 (1.7.0),因此请尝试在使用 jarsigner 签名时添加这些选项:

          -digestalg SHA1 -sigalg MD5withRSA
          

          【讨论】:

          • 是的,我使用的是 JDK 7,所以我尝试了您的选项,并且签名过程完美完成。谢谢!我假设这个参数也与 JDK 6 兼容,对吗?
          • 不好的是 ANT 中的 signjar 任务不支持 'args' 属性,因此签名必须使用 exec 或 java 任务完成,我认为这不太干净。
          • 是的,我认为这些参数也存在于 JDK 6 中。
          • 抱歉重复评论。试图增加我得到答复的几率。这让我很困惑,因为在developer.android.com/tools/publishing/app-signing.html#signapp 他们说要使用-sigalg SHA1withRSA -digestalg SHA1。为什么我们使用 MD5withRSA?
          猜你喜欢
          • 1970-01-01
          • 2011-04-07
          • 1970-01-01
          • 1970-01-01
          • 2022-01-10
          • 1970-01-01
          • 2018-10-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多