Подписание Android с помощью Ant
Используя Ant, я пытаюсь создать приложение Android в режиме выпуска для распространения. Моя проблема заключается в процессе подписания. Я создал keystore и alias через Eclipse с помощью мастера экспорта приложений для Android, и приложение правильно подписано, если экспортировать его через 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. Я использовал этот APK с jarsigner, и все файлы имеют "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!
Ответы
Ответ 1
Если у вас есть Ant version < 1.8.3 (ant -version
) попробуйте этот подход для проблемы с JDK 7 (на основе предыдущего ответа):
-
Добавить 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 "@{signedjar}"" />
<arg line=""@{jar}" @{alias}" />
</exec>
</sequential>
</macrodef>
-
Замените 'signjar'
на 'signjarjdk7'
в 'release'
target в том же файле build.xml.
ПРИМЕЧАНИЕ. Вам необходимо определить 'key.store.password' и 'key.alias.password' для вашего проекта (в project.properties или в локальном .properties).
ОБНОВЛЕНИЕ 1:
Если вы установили Ant 1.8.3 (или более поздней версии), у вас есть лучшее решение:
Откройте файл ANDROID_SDK\tools\ ant\build.xml и добавьте два новых параметра - sigalg и digestalg - в исходном вызове signjar:
<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:
Кажется, этот ответ устарел после того, как "signjar" был заменен на "signapk" в последней версии инструментов Android SDK.
Ответ 2
Звучит так, как вы можете использовать JDK 7 (1.7.0), поэтому попробуйте добавить эти параметры при подписании с jarsigner:
-digestalg SHA1 -sigalg MD5withRSA
Ответ 3
Per Документация разработчика Android, вы должны поместить эти свойства в файл 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 signjar:
https://issues.apache.org/bugzilla/show_bug.cgi?id=52344
Новые атрибуты были добавлены в signjar в Ant 1.8.3, но Android build script (начиная с r19) еще не был изменен для их использования:
http://code.google.com/p/android/issues/detail?id=19567
Тем временем "presetdef" может обеспечить обходное решение:
<presetdef name="signjar">
<signjar sigalg="MD5withRSA" digestalg="SHA1" />
</presetdef>
Ответ 5
Используя Ubuntu 14.04 (Trusty Tahr) и Windows, создайте файл .keystore.
Этот файл должен быть сгенерирован, что может быть сделано с помощью команды keytool, которая поставляется с Java. Его обычно можно найти в папке "C:\Program Files\Java\jre7\bin". Который также должен быть добавлен к вашей переменной PATH.
Перейдите в корень вашего проекта и используйте следующую команду:
Создание файла .keystore:
$ keytool -genkey -v -keystore key-name.keystore -alias alias-name -keyalg RSA -keysize 2048 -validity 10000
Создайте файл с именем ant.properties в папке "platform/android/"
ant.properties.
key.store=D:\\path\\to\\the\\project\\keyname.keystore
key.alias=alias-name
Создайте файл APK сборки:
$ cordova build android --release
Ответ 6
Если вы застряли (как я) с версией Ant старше 1.8.3 и Java 7, обходной путь:
<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>