Как подписать ваше гибридное мобильное приложение для размещения в Google Play
Итак, вы трудились много дней (а может и ночей), и вот ваше первое гибридное мобильное приложение готово. Оно достаточно стабильно, большинство критичных багов закрыто. Остались мелкие, но помня о том, что перфекционизм — зло, вы принимаете волевое решение выложить приложение. Необходимое условие для этого — наличие подписанного APK файла. Как подписать apk файл, вы узнаете из этой статьи.
Небольшое отступление
Когда мой pet project вплотную приблизился к релизу, я начал искать информацию о том, как быстро и без боли опубликовать приложение. Множество найденных инструкций выглядели простыми. Я выбрал инструкцию авторов фреймворка Ioniс, на котором и разработано приложение. Не все получилось с первого раза, есть несколько особенностей. Процесс подписывания описан в этой статье, важные моменты особо выделены.
Исходные данные
Я предполагаю, что у вас настроено все необходимое для разработки гибридных мобильных приложений с помощью Apache Cordova. Должно быть установлено:
Apache Cordova
Java Development Kit
Android SDK Tools
В качестве имени проекта и приложения используется lcf. Замените на имя своего проекта там, где это необходимо.
Поехали
Для начала нужно создать релизный билд вашего приложения. Но перед этим, давайте убедимся, что все лишние плагины удалены. Например, нам не нужен плагин, который выводит отладочную информацию в консоль. Удалим его:
$ cordova plugin rm cordova-plugin-console
Для генерации релизной сборки под Андроид используем команду build с флагом —release:
$ cordova build --release android
Эта команда создаст неподписанный APK файл в каталоге:
platforms/android/build/outputs/apk
Например, platforms/android/build/outputs/apk/android-release-unsigned.apk. Потом нам понадобится подписать этот файл и запустить утилиту zipalign для оптимизации и подготовки файла для Google Play. Для подписывания файла нужен сертификат. Создадим его с помощью утилиты keytool, которая включена в JDK:
Значение параметра -alias необходимо запомнить, а лучше записать. В примере выше он равен lcf (по первым буквам названия приложения Loyal Client Free). Детали здесь приводить не буду, если будет интересно, напишите в комментарии, я расскажу подробнее. Алиас используется каждый раз при подписывании* приложения. Чтобы было проще запомнить, в качестве алиаса используйте имя keystore файла, например:
* Подписывать приложение нужно при каждом выпуске обновлений Утилита keytool задает ряд вопросов. Всего их будет 8. Чтобы заранее иметь представление о вопросах и примерных ответах, все они приведены далее, под спойлером. Вопросы keytool и примерные ответы на них 1. Enter keystore password: Здесь необходимо ввести пароль для файла (не менее 6 символов). Введенный пароль нужно записать в надежном месте, он нужен всякий раз при подписывании приложения. 2. Re-enter new password: Повторный ввод пароля. 3. What is your first and last name? [Unknown]: Ivan Petrov Ваше имя и фамилия. Значение в квадратных скобках — это значение по умолчанию. 4. What is the name of your organizational unit? [Unknown]: IT Название подразделения вашей компании. Можно оставить пустым, я указываю IT. 5. What is the name of your organization? [Unknown]: 2developers Название вашей организации. Укажите, если есть. 6. What is the name of your City or Locality? [Unknown]: Moscow Название города 7. What is the name of your State or Province? [Unknown]: MO Название области 8. What is the two-letter country code for this unit? [Unknown]: RU Код страны. Я указываю RU. Далее будет предложено проверить введенную информацию: Is CN=Ivan Petrov, OU=IT, O=2developers, L=Moscow, ST=MO, C=RU correct? [no]: y Подтверждайте, если все верно или нажмите Enter, чтобы ввести еще раз. В конце появится сообщение об успешной генерации ключа. Будет предложено задать пароль для приватного ключа (если хотите оставить такой же, как и для сертификата — нажмите Enter):
Generating 2 048 bit RSA key pair and self-signed certificate (SHA256withRSA) with a validity of 10 000 days for: CN=Ivan Petrov, OU=IT, O=2developers, L=Moscow, ST=MO, C=RU Enter key password for (RETURN if same as keystore password): [Storing lcf.keystore]
В текущем каталоге будет создан файл lcf.keystore.Важно
Созданный файл нужно сохранить в надежном месте. Если вы используете закрытый репозиторий, то файл можно закоммитить вместе с исходными кодами приложения. В общем случае, сертификаты лучше хранить отдельно. В случае утери сертификата вы не сможете выпускать обновления приложения.
Осталось два шага, и вы получите готовый к распространению APK файл. Переходим непосредственно к подписыванию. Чтобы подписать ваш apk файл, используйте утилиту jarsigner, которая тоже включена в JDK.
Последний параметр — это имя файла, который вы будете загружать в Google Play.Важно.
Утилита zipalign это часть Android SDK Tools и может быть найдена здесь:
/path/to/Android/sdk/build-tools/VERSION/zipalign
Заключение
Теперь у вас есть готовый к распространению apk файл, который можно загрузить в Google Play. Заполняйте описание, определяйте рейтинг своего приложения и смело жмите “Опубликовать”. 7613,5k 76
В этом уроке:
— создаем ключи и подписываем приложение
Тема этого урока не относится непосредственно к программированию. И вполне себе можно кодить без этих знаний. Но для общего развития, думаю, об этом все-таки стоит поговорить. Данные знания пригодятся вам, например, когда будете делать приложение с гугл-картой, или когда будете выкладывать свое творение на маркет.
Подпись приложения
Вообще, в процессе подписи и верификации участвуют закрытый/открытый ключи и сертификат. Если кому интересно, то можете погуглить эти понятия и почитать подробнее. Я же, чтобы не усложнять урок, буду просто называть все это ключом. Для понимания темы урока этого будет достаточно.
Вы создали приложение и хотите его протестировать на реальном устройстве или эмуляторе. Для того, чтобы установить и запустить приложение, оно должно быть подписано. Если вы еще не публиковали на маркете свои приложения, то, скорее всего, про то, что приложение надо подписывать, вы слышите первый раз. И точно помните, что ни с какими подписями не возились. Создавали проект, кодили все, что нужно, сохраняли и запускали и все прекрасно работало. Так происходило, потому что Eclipse сам создавал ключ и сам подписывал приложение этим ключом, чтобы вам на первых порах не приходилось думать об этом. И когда ваше приложение устанавливалось, оно было уже подписанным. А если попытаться установить неподписанное приложение, то получим ошибку.
Итак, приложение обязательно должно быть подписанным, и Eclipse любезно берет это на себя. Он подписывает их debug-ключом. Раньше срок его действия был всего один год. Android проверяет срок действия ключа только при установке. Т.е. если вы установили приложение и срок действия ключа истек, вы все равно сможете использовать установленное приложение. А вот установить или обновить приложение, подписанное истекшим ключом, не получится. Система выдаст ошибку.
Сейчас срок debug-ключа равен 30 лет. Но приложение, подписанное debug-ключом, не получится опубликовать на маркете. А значит, нам надо будет создавать свой ключ и подписывать им приложение.
keytool
Для создания ключа нам понадобится утилита keytool. Ее можно найти по адресу bin. Она умеет создавать новые ключи и показывать информацию о уже существующих. Давайте сначала попробуем посмотреть информацию о существующем ключе. Для этого возьмем тот самый debug-ключ, который используется для подписи приложений по умолчанию. Узнать где он находится можно в настройках Eclipse: Window > Preferences >Android > Build.
Файл debug.keystore имеет расширение keystore. Это можно перевести как хранилище ключей. Это действительно так, один такой файл может содержать в себе несколько ключей. Для того чтобы обратится к конкретному ключу внутри хранилища используется alias (алиас, можно рассматривать его как имя ключа).
Посмотрим, какие ключи есть в хранилище debug.keystore. Используем команду list. С помощью параметров keystore и storepass укажем имя файла хранилища и пароль к хранилищу:
Мы видим, что здесь хранится один ключ с алиасом androiddebugkey, и создан он был 26.08.2012. Этот ключ и используется Eclipse-ом для подписи вашего приложения по умолчанию. Хранилище и ключ имеют одинаковый пароль — android.
Давайте создадим свой ключ. Для этого используем команду genkey и к ней идет куча параметров.
Именно эти вышеперечисленные параметры мы и задали в скрипте.
keystore — имя файла хранилищаstorepass — пароль к хранилищуalias — алиас создаваемого ключаkeypass — пароль к ключуdname — информация о владельце ключаvalidity — срок действия ключа (в днях)
dname задается в определенном формате. Я указал только имя, организацию и страну.
После выполнения этой команды в хранилище mykeys.keystore создался ключ с вышеуказанными параметрами. Если указанное хранилище не существует, то оно будет создано.
Теперь давайте снова используем команду list и поглядим на только что созданный ключ
Видим, что внутри все так, как мы и создавали — один ключ с алиасом mykey1.
Туда же можно поместить второй ключ. Но теперь запишем скрипт создания ключа в несколько урезанном виде. Мы не будем указывать пароли к хранилищу и ключу, и информацию о владельце.
и программа спросит нас о недостающих данных. Сначала пароль к хранилищу, затем данные о владельце ключа (я заполнял не все требуемые значения), затем пароль для создаваемого ключа и подтверждение пароля.
Функционально разницы нет, но при таком способе вам не надо знать формат ввода параметра dname (утилита все спросит сама), и посторонним не видны пароли, которые вы вводили.
Теперь в хранилище два ключа. Выполним list и убедимся.
keytool -list -keystore mykeys.keystore
Обратите внимание, что я не ввел пароль от хранилища (например, чтобы не «светить» его). Утилита спросит меня:
Видно, что был запрошен пароль и в хранилище сейчас два ключа.
Команду list можно еще выполнить с параметром v. Этот параметр добавляет информативности.
Теперь для каждого ключа виден не только алиас и дата создания, но и инфа о владельце, срок действия и пр.
Параметр v также можно использовать и с командой genkey. После создания ключа будет выведено немного информации о нем в консоль.
jarsigner
Итак, разобрались с keytool. Знаем, как создавать хранилище с ключами и как посмотреть инфу о существующих. Осталось узнать, как подписать приложение ключом. Для этого используется другая утилита — jarsigner.
Имена параметров нам знакомы по keytool: хранилище (keystore), пароль (storepass) к нему и пароль (keypass) к ключу. А последние два параметра – это имя APK-файла, который вы хотите подписать и алиас ключа из указанного хранилища, который вы хотите использовать для подписи.
После этого приложение будет подписано и система примет его к установке.
Ради интереса давайте попробуем установить неподписанный APK. Чтобы создать его надо щелкнуть правой кнопкой мыши на проекте в Eclipse и выбрать Android tools > Export Unsigned Application Package. Далее указываем путь, куда сохранить APK-файл. Eclipse создает приложение из проекта и сохраняет его в указанный каталог. После этого он выводит сообщение, что перед публикацией приложения необходимо его подписать и сжать (утилитой zipalign).
Попробуем установить приложение на эмулятор с помощью adb. Получаем ошибку Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES]:
Система обнаружила, что приложение не подписано.
Если же сначала закинуть APK на эмулятор и там запустить файловым менеджером, получим такое сообщение при установке:
Визард
Eclipse предоставляет визард, который позволяет реализовать все вышеописанные шаги по подготовке приложения к установке. Для этого надо на проекте в Eclipse щелкнуть правой кнопкой и выбрать Android tools > Export Signed Application Package.
Визард на всякий случай уточнит проект
Затем надо выбрать: использовать существующее хранилище или создавать новое. Если используем существующее, то выбираем его и вводим пароль к этому хранилищу.
Жмем Next, и визард спрашивает, какой из существующих ключей использовать, либо дает возможность создать новый.
Выбираем существующий ключ, вводим пароль к нему
Осталось указать путь и имя файла, куда Eclipse сохранит готовое, подписанное и сжатое приложение. Заодно он сразу показывает срок действия сертификата.
Жмем Finish и получаем готовое приложение, которое можно публиковать на маркете.
Если же у вас пока нет ключа, то визард поможет вам его создать, чтобы не надо было возиться с консолью и keytool.
В этом случае вы указываете, что хотите создать хранилище
Далее надо создать ключ
Здесь вы указываете алиас, пароль, срок действия (в годах) и инфу о владельце.
Ну и остается указать путь к создаваемому файлу
По идее, я мог бы сразу показать вам этот визард, который за вас все сделает, но я думаю, что вы не понимали бы значение всех его экранов и полей. А это не очень хорошая практика – пользоваться тем, чего не понимаешь. Поэтому я подробно расписал механизм ключей и подписи приложений, чтобы вы представляли себе, как устроен этот процесс и что делает визард.
По поводу срока действия ключа, в хелпе пишут, что рекомендуется ставить 25 лет. И что при публикации приложения на маркете, проверяется, что срок действия закончится позднее, чем 22 октября 2033. Думаю, эта дата будет периодически сдвигаться.
На следующем уроке:
— разбираемся, что такое Package для приложения
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме
Иногда некоторые приложения на Android чем-то не устраивают пользователя. В качестве примера можно привести назойливую рекламу. А то бывает и так — всем хороша программа, да только перевод в ней или кривой, или вовсе отсутствует. Или, например, программа триальная, а получить полную версию возможности нет. Как же изменить ситуацию?
В этой статье мы поговорим о том, как разобрать пакет APK с приложением, рассмотрим его внутреннюю структуру, дизассемблируем и декомпилируем байт-код, а также попробуем внести в приложения несколько изменений, которые могут принести нам ту или иную выгоду.
Чтобы сделать все это самостоятельно, потребуются хотя бы начальные знания языка Java, на котором пишутся приложения для Android, и языка XML, который используется в Android повсеместно — от описания самого приложения и его прав доступа до хранения строк, которые будут выведены на экран. Также понадобится умение обращаться со специализированным консольным софтом.
Итак, что же представляет собой пакет APK, в котором распространяется абсолютно весь софт для Android?
Декомпиляция приложений
В статье мы работали только с дизассемблированным кодом приложения, однако если в большие приложения вносить более серьезные изменения, разобраться в коде smali будет гораздо сложнее. К счастью, мы можем декомпилировать код dex в Java-код, который будет хоть и не оригинальным и не компилируемым обратно, но гораздо более легким для чтения и понимания логики работы приложения. Чтобы сделать это, нам понадобятся два инструмента:
dex2jar — транслятор байт-кода Dalvik в байт-код JVM, на основе которого мы сможем получить код на языке Java;
jd-gui — сам декомпилятор, позволяющий получить из байт-кода JVM читаемый код Java. В качестве альтернативы можно использовать Jad (www.varaneckas.com/jad); хоть он и довольно старый, но в некоторых случаях генерирует более читаемый код, нежели Jd-gui.
Использовать их следует так. Сначала запускаем dex2jar, указывая в качестве аргумента путь до apk-пакета:
% dex2jar.sh mail.apk
В результате в текущем каталоге появится Java-пакет mail.jar, который уже можно открыть в jd-gui для просмотра Java-кода.
Устройство APK-пакетов и их получение
Пакет приложения Android, по сути, является обычным ZIP-файлом, для просмотра содержимого и распаковки которого никаких специальных инструментов не требуется. Достаточно иметь архиватор — 7zip для Windows или консольный unzip в Linux. Но это что касается обертки. А что внутри? Внутри же у нас в общем случае такая структура:
META-INF/ — содержит цифровой сертификат приложения, удостоверяющий его создателя, и контрольные суммы файлов пакета;
res/ — различные ресурсы, которые приложение использует в своей работе, например изображения, декларативное описание интерфейса, а также другие данные;
AndroidManifest.xml — описание приложения. Сюда входит, например, список требуемых разрешений, требуемая версия Android и необходимое разрешение экрана;
classes.dex — компилированный байт-код приложения для виртуальной машины Dalvik;
resources.arsc — тоже ресурсы, но другого рода — в частности, строки (да-да, этот файл можно использовать для русификации!).
Перечисленные файлы и каталоги есть если не во всех, то, пожалуй, в абсолютном большинстве APK. Однако стоит упомянуть еще несколько не столь распространенных файлов/каталогов:
assets — аналог ресурсов. Основное отличие — для доступа к ресурсу необходимо знать его идентификатор, список asset’ов же можно получать динамически, используя метод AssetManager.list() в коде приложения;
lib — нативные Linux-библиотеки, написанные с помощью NDK (Native Development Kit).
Этот каталог используют производители игр, помещая туда движок игры, написанный на C/C++, а также создатели высокопроизводительных приложений (например, Google Chrome). С устройством разобрались. Но как же получить сам файл пакета интересующего приложения? Поскольку без рута с устройства забрать файлы APK не представляется возможным (они лежат в каталоге /data/app), а рутить не всегда целесообразно, имеется как минимум три способа получить файл приложения на компьютер:
расширение APK Downloader для Chrome;
приложение Real APK Leecher;
различные файлообменники и варезники.
Какой из них использовать — дело вкуса; мы предпочитаем использовать отдельные приложения, поэтому опишем использование Real APK Leecher, тем более что написан он на Java и, соответственно, работать будет хоть в винде, хоть в никсах.
После запуска программы необходимо заполнить три поля: Email, Password и Device ID — и выбрать язык. Первые два — e-mail и пароль твоего гуглоаккаунта, который ты используешь на устройстве. Третий же является идентификатором устройства, и его можно получить, набрав на номеронабирателе код ##8255## и затем найдя строку Device ID. При заполнении надо ввести только ID без префикса android-.