Меню
Бесплатно
Главная  /  ПО  /  Java - редактирование - manifest android structure. Новый способ публикации приложений с помощью Android App Bundle Структура скомпилированной Android библиотеки

Java - редактирование - manifest android structure. Новый способ публикации приложений с помощью Android App Bundle Структура скомпилированной Android библиотеки

У меня есть проект, созданный с помощью Gradle в Android Studio v 0.3.2. Мой проект имеет зависимости от двух других модулей ( ная библиотека). Структура проекта хорошо определена с помощью файлов build.gradle. Проблема в том, что … когда я запускаю проект на Android-устройстве, я устанавливаю 3 на моем устройстве. Один из них – основной проект (единственный правильный), а два других – импортированные модули (эти два я не хочу устанавливать). Как я могу это достичь? Или что я делаю неправильно?

Структура проекта:

  • MyLibModule
  • MainProject
  • MainProject-> libraries-> MyOtherModule

Где MyLibModule находится на том же пути, что и основной проект, потому что мне также нужен этот модуль в другом проекте.

Просто чтобы быть ясным: вся сборка проекта в порядке , все зависимости в порядке, но почему я получаю 3 APK на моем устройстве?

После целого дня, борющегося с этой проблемой, я нашел причину этого странного поведения. Проблема заключалась в проявлении библиотечного модуля. Прежде чем я переключился на студию Android, я использовал Eclipse. И у меня была testActivity, объявленная в манифесте проекта библиотеки. Удаление всех тестовых действий из манифеста из моих библиотечных модулей решило проблему. Теперь Android Studio устанавливает только APK MainProject.

Некоторый код: манифест MyLibModule:

Изменился на:

…. И то же самое для MyOtherModule.

ПРИМЕЧАНИЕ. Пустой узел приложения должен оставаться в манифесте, чтобы избежать ошибок сборки.

Удалить фильтр намерений из запуска вашей библиотеки

Изменился на

Это потому, что ваши библиотеки определены в файлах build.gradle как приложения, а не библиотеки. Посмотрите на эту строку:

Apply plugin: "android"

И замените его на:

Apply plugin: "android-library"

Возможно, вам придется внести другие изменения в файл сборки, так как не все, что относится к приложениям, может быть указано в файле сборки библиотеки. См. http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Library-projects для получения дополнительной информации.

Введение

Комфорт среды программирования во многом зависит от количества второстепенных действий, не относящихся к программированию, которые требуется выполнять программисту, а также глубины изучения самой среды разработки для её правильной настройки под собственные нужды. В этом смысле идеалом, на мой взгляд, является среда Дельфи, заточенная как раз-таки на максимально простую и быструю разработку приложений для Windows (справедливости ради замечу, что с разработкой приложений под Android и другие системы там пока ещё не всё так гладко, как хотелось бы).

В этом смысле в царстве Android нет достаточно комфортных сред разработки, как это, впрочем, и полагается программам в мире бесплатных операционных систем. Ещё до недавнего времени центральным средством разработки считался Eclipse со специализированными плагинами. Однако летом 2013 года Google представил на суд общественности новую IDE — Android Studio , основанную на давнишнем конкуренте Eclipse — системе IntelliJ IDEA . Надо сказать, что несмотря на раннюю версию системы, не вошедшую ещё даже в стадию Beta, она уже превосходит удобством Eclipse.

Тем не менее, программистам всё ещё приходится вникать как в многочисленные нюансы настройки среды, так и в непривычные действия по формированию конечных файлов приложений, готовых к распространению. И это всё на фоне изучения тех специфичных классов, которые приходится использовать, чтобы заставить интерфейс должным образом работать с кодом.

После такого большого вступления, я всего лишь расскажу, как в Android Studio можно генерировать конечные apk-файлы, готовые к распространению, ибо есть нюансы. Надеюсь, моя статья хоть как-то облегчит жизнь начинающим пользователям этой, пожалуй, лучшей на сегодняшний день IDE для программирования под Android.

Ручной способ

  1. В левом нижнем углу Android Studio есть маленькая кнопочка, управляющая отображением специальных ярлыков у краёв экрана. Ярлыки открывают различные вспомогательные окна. Кроме того, при простом наведении на эту кнопочку указателя мыши, появляется список всех этих окон для быстрого открытия нужного. Откроем окно Build Variants и напротив нашего модуля в поле Build Variant переключим режим сборки с debug на release.
  2. В основном меню открываем Build → Generate Signed APK. Возникает сообщение, которое, немного перефразируя, можно перевести примерно так: «Для проектов, собирающихся утилитой Gradle, информация о подписи и порядок подписывания apk-файлов должны быть прописаны в специальном сценарии. Настройте сценарий, как это описано в руководстве пользователя: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Signing-Configurations . Затем запустите "Gradle assembleRelease", и получите сгенерированный apk-файл в папке build/apk/ » Это сообщение как раз настоятельно рекомендует нам использовать второй способ создания apk-файла. Принимаем информацию к сведению, но продолжаем ручной способ, нажав OK.
  3. Открывается окно помощника генерации подписи для apk-файла. Мы уже знаем, что все распространяемые приложения для Android должны иметь цифровую подпись автора, иначе приложение не установится на устройства пользователей. Сгенерированная подпись должна храниться в специальном файле-хранилище, расположенном на вашем компьютере, откуда потом она будет извлекаться для подписания apk-файлов. При этом одно хранилище может хранить несколько подписей для разных apk-файлов. Кроме того, одна и та же подпись может использоваться для подписания разных apk-файлов. Итак, для создания хранилища нажимаем кнопку Create New… и заполняем открывшиеся в окне поля:
    1. Путь для размещения файла хранилища
    2. Пароль и подтверждение для доступа к хранилищу
    3. Имя подписи, по которому она будет вызываться
    4. Пароль и подтверждение для доступа к подписи
    5. Срок действия подписи (по умолчанию 25 лет, оставляем без изменений)
    6. Хотя бы одно из полей сертификата. Обычно заполняют имя и фамилию, город и страну (RU).
  4. Нажимаем OK. Окно закрывается, и мы видим, что все поля в предыдущем окне автоматически заполнились введёнными нами данными. Ставим галочку в поле Remember Password, чтобы каждый раз не набирать пароль, и нажимаем OK.
  5. В следующем окне контролируем путь и имя apk-файла. По умолчанию оно равно имени модуля. Включаем галочку Run ProGuard, чтобы наш файл был оптимизирован, и можем даже поменять файл конфигурации proguard-android.txt на proguard-android-optimize.txt для более жёсткой оптимизации (хотя это может быть чревато для некоторых экзотичных смартфонов). Нажимаем Finish и ждём, посматривая в строку состояния.
  6. Когда сборка проекта закончится, отобразится окошко с предложением открыть папку с полученным apk-файлом. Открываем её и видим наш файл.

Скажу сразу, что несмотря на то, что я ставлю галочку в поле Run ProGuard, он у меня почему-то не отрабатывает, и apk-файл остаётся неоптимизированным. Возможно, это пережитки ранней версии Android Studio (у меня версия 0.5.4 ). Но выйти из положения достаточно просто, включив эту галочку непосредственно в файле сценария утилиты ProGuard. Найдите в окне проекта внутри нашего модуля файл build.gradle. В секции android → buildTypes → release, отвечающей за генерацию релиза, поменяйте параметр runProguard с false на true.

Не забудьте после редактирования файла сценария синхронизировать с ним ваш проект. Для этого в панели инструментов нажмите кнопку Sync Project with Gradle Files (стрелочка вниз из зелёного кружка) или ссылку Sync Now во всплывшей в верхней части исходника жёлтой полосе сообщения. После синхронизации можно снова попробовать собрать apk-файл, начиная со второго пункта нашей инструкции. Только в этот раз вместо генерации нового хранилища используем уже созданное. Все наши пароли и настройки сохранились, поэтому нам только остаётся нажимать во всплывающих окнах OK-Next-Finish. Обратите внимание, что вновь сгенерированный apk-файл стал немного меньше, чем в прошлый раз.

Автоматический способ

Автоматический способ позволяет генерировать apk-файл без ввода паролей при каждом запуске приложения на выполнение, а также командой assembleRelease, добавленной в список конфигураций и выполняющейся той же кнопкой Run.

Для включения автоматического режима надо внести в уже знакомый нам файл сценария build.gradle новую секцию, содержащую в том числе информацию о подписи:


signingConfigs { release { storeFile file("C:\\Users\\ИмяПользователя\\KEYSTORE.jks") storePassword "ПарольХранилища" keyAlias "ИмяПодписи" keyPassword "ПарольПодписи" } buildTypes { release { minifyEnabled true signingConfig signingConfigs.release proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } }

Вместо файла настроек "proguard-android.txt" можно вписать файл ещё более оптимизированных настроек "proguard-android-optimize.txt". Это позволит ещё немного сократить объём apk-файла.

Для внесения этой секции в настройки откроем файл build.gradle, расположенный внутри нашего модуля и закомментируем секцию buildTypes. Вместо неё вставим вышеприведённую секцию. Не забудьте поменять путь к вашему файлу ключей, который вы создали в первой части статьи при ручном создании apk-файла, а также вписать правильное имя подписи и оба пароля.

После внесения изменений в файл нажимаем в панели инструментов кнопку Sync Project with Gradle Files (стрелочка вниз из зелёного кружка) или ссылку Sync Now во всплывшей вверху жёлтой информационной полосе, чтобы синхронизировать изменённые настройки с проектом. Всё, автоматический режим настроен!

Теперь, чтобы иметь возможность генерировать apk-файл без запуска приложения, добавим отдельную команду запуска генерации apk-файла в список конфигураций (комбо-бокс в панели инструментов). Откроем окошко Gradle Tasks, нажав на ярлык Gradle у правого края экрана, или выбрав его во всплывающем списке кнопки, расположенной в левом нижнем углу Android Studio. В секции All tasks раскрываем список задач для нашего модуля и правой кнопкой щёлкаем по задаче assembleRelease. В появившемся контекстном меню выбираем пункт Create… и выбранная задача добавится в список конфигураций.

Теперь мы можем генерировать релиз и без запуска программы на выполнение, просто выбрав в списке конфигураций команду assembleRelease и нажав кнопку Run. Результат автоматического создания apk-файла будет находится в папке build/apk/. Там будут два файла: ИмяМодуля-release-unaligned.apk и ИмяМодуля-release.apk. Первый файл — это полуфабрикат. Он уже подписан но ещё не выровнен. Второй файл — уже выровненный. Это и есть наш конечный apk-файл, который мы уже можем переименовать и свободно распространять.

Замечу, что выравнивание файла гарантирует, что все несжатые данные будут начинаться с позиции, кратной 4 байтам по отношению к началу файла. Это обеспечит оптимизацию производительности программы на устройстве. Когда файл выровнен, Android способен читать информацию из файла по мере необходимости, а не загружать в память весь пакет целиком. В итоге уменьшается объем оперативной памяти, потребляемой запущенным приложением.

Установленные плагины находятся в меню File | Settings... | Plugins . Кнопка Browse repositories... позволяет найти плагин в репозитории. Кнопка Install plugin from disk... позволяет установить плагин с диска, если вы его скачали самостоятельно.

Rainbow Brackets

"Радужные скобки" позволяют пометить каждую пару скобок своим индивидуальным цветом. Это помогает визуально видеть, где находится область кода.

Заменяет все индикаторы прогресса в студии на няшного котика. Если вы серьёзный программист, то просто обязаны установить плагин . Совместимо с другими средами разработки на основе IntelliJ IDEA: PhpStorm, WebStorm, PyCharm, RubyMine, AppCode, CLion, Gogland, DataGrip, Rider, MPS.

Появляется везде. Например, при загрузке проекта.

Во время работы при синхронизации чего-либо.

RoboPOJOGenerator

Удобный генератор готовых Java и Kotlin POJO классов из JSON: GSON, FastJSON, AutoValue (GSON), Logan Square, Jackson.

ADB Idea

Плагин для Android Studio/Intellij IDEA для быстрых операций над приложением:

  • Uninstall App - удалить приложение из устройства
  • Kill App - убить приложение (удалить из памяти)
  • Start App - запустить приложение
  • Restart App - перезапустить приложение
  • Clear App Data - очистить данные
  • Clear App Data and Restart - очистить данные и перезапустить

После установки эти команды можно найти через Tools | Android | ADB IDEA .

Также можно вызвать окно поиска действий через комбинацию клавиш Ctrl+Shift+A и с помощью символов ADB быстро найти конкретную команду.

Плагин удобен для проверки работоспособности приложения в разных состояниях. Например, вы ранее создали базу данных и решили посмотреть, как поведёт себя приложение при пустой базе. С помощью плагина вы быстро можете очистить данные и посмотреть на результат.

Когда мы говорим о плагинах и модульных приложениях, то в первую очередь имеем в виду обычный пользовательский софт. Однако модульный дизайн может быть не менее полезен при разработке руткитов и бэкдоров. Обычными средствами обновлять такой софт слишком палевно, да и не всегда возможно, а вот незаметно подгрузить модуль с новой функциональностью по сети - это пожалуйста. А если вынести ключевую функциональность в модули и удалять их сразу после загрузки, то можно серьезно подпортить жизнь реверсеру.

Вместо введения

В классической Java есть класс под названием java.lang.ClassLoader . Его задача - загружать байт-код указанного класса (файл с расширением.class) в виртуальную машину во время исполнения приложения. Затем можно создать объект этого класса и вызывать его методы с помощью рефлексии. Такой вот способ динамической загрузки кода, который можно использовать для написания приложений с расширяемой функциональностью, или, попросту говоря, поддержкой плагинов.

В Android нет виртуальной машины Java и нет класса ClassLoader, но есть его аналог DexClassLoader, выполняющий ровно ту же функцию, но в отношении байт-кода Dalvik (и файлов.dex вместо.class соответственно). И, в отличие от настольной Java, где проще положить нужный jar-файл в CLASSPATH и не возиться с динамической загрузкой, в Android такой подход дает действительно много преимуществ, главное из которых в том, что функциональность приложения можно расширять и обновлять незаметно для пользователя и ни о чем его не спрашивая. В любой момент твое приложение может скачать файл с классом с сервера, загрузить, а затем удалить файл.

Кроме этого, классы можно хранить прямо в пакете APK и загружать во время старта приложения. Профит здесь в том, что код загружаемых классов будет отделен от кода самого приложения и находиться в APK «не по адресу»; инструменты типа apktool, которыми так любят пользоваться реверсеры, их просто не увидят. С другой стороны, это скорее защита от дурака, так как нормальный реверсер быстро смекнет, что к чему.

Как бы там ни было, динамическая загрузка классов - очень полезная штука при написании не совсем «белых» приложений, поэтому любой security-специалист должен знать, как этот механизм работает и как он используется в троянах.

Простейший пример

// Путь до jar-архива с нашим классом String modFile = "/sdcard/myapp/module.jar"; // Путь до приватного каталога приложения String appDir = getApplicationInfo().dataDir; // Подгружаем файл с диска DexClassLoader classLoader = new DexClassLoader(modFile, appDir, null, getClass().getClassLoader()); // Загружаем класс, создаем объект и пробуем вызвать метод run() с помощью рефлексии try { Class c = classLoader.loadClass("com.example.modules.simple.Module"); Method m = c.getMethod("run", null); m.invoke(c.newInstance(), null); } catch (Exception e) { e.printStackTrace(); }

В целом здесь все просто: код загружает jar-архив /sdcard/myapp/module.jar с нашим классом, загружает из него класс com.example.modules.simple.Module , создает объект и вызывает метод run() . Обрати внимание на три момента:

  • DexClassLoader умеет загружать как «просто» файлы.dex , так и jar-архивы, последние предпочтительнее из-за сжатия и возможности использовать цифровую подпись;
  • второй аргумент конструктора DexClassLoader - это каталог, который он использует для сохранения оптимизированного байт-кода (odex), для простоты мы указываем приватный каталог самого приложения;
  • в качестве аргумента метода loadClass всегда необходимо указывать адрес класса вместе с именем пакета.

Чтобы проверить данный код на работоспособность, создадим простейший модуль:

Package com.example.modules.simple.Module; import android.util.Log; public class Module { public void run() { Log.d("Module", "I am alive!!!"); } }

Не торопись создавать новый проект в Android Studio, можешь накидать этот код в блокноте и собрать его в jar-архив прямо из командной строки:

Javac -classpath /путь/до/SDK/platforms/android-23/android.jar Module.java /путь/до/SDK/build-tools/23.0.3/dx --dex --output=module.jar Module.class

Удостоверься, что каталоги platforms/android-23 и build-tools/23.0.3 существуют, в твоем случае их имена могут отличаться.

Если все пройдет гладко, на выходе ты получишь файл module.jar . Останется только добавить код загрузчика в приложение, положить module.jar на карту памяти, собрать и запустить приложение.

Долой рефлексию

Рефлексия - хорошая штука, но в данном случае она только мешает. Один метод без аргументов с ее помощью вызвать нетрудно, однако, если мы хотим, чтобы наше приложение имело развитый API модулей с множеством методов, принимающих несколько параметров, нужно придумать что-то более удобное. Например, использовать заранее определенный интерфейс, который будет реализовывать каждый модуль.

Применив такой подход к приведенному выше примеру, мы получим следующие три файла:

  1. Файл ModuleInterface.java с описанием API: package com.example.modules; public interface ModuleInterface { public void run(); }
  2. Файл Module.java с реализацией нашего модуля: package com.example.modules.simple.Module; import android.util.Log; public class Module implements ModuleInterface { public void run() { Log.d("Module", "I am alive!!!"); } }
  3. Новый загрузчик модуля (помести в свое приложение): String modFile = "/sdcard/myapp/module.jar"; String appDir = getApplicationInfo().dataDir; DexClassLoader classLoader = new DexClassLoader(modFile, appDir, null, getClass().getClassLoader()); // Загружаем класс и создаем объект с интерфейсом ModuleInterface ModuleInterface module; try { Class class = classLoader.loadClass("com.example.modules.simple.Module"); module = (ModuleInterface) class.newInstance(); } catch (Exception e) { e.printStackTrace(); } module.run()

Это все. Теперь мы можем работать с модулем, как с обычным объектом. Более того, система сама отбракует модули (классы), несовместимые с интерфейсом, еще на этапе загрузки, поэтому нам не придется задаваться вопросами, а есть ли в модуле нужный нам метод.

Когда модулей много

С одним модулем разобрались, но что, если их будет много? Как вести учет этих модулей и не потеряться среди них? На самом деле все просто - для этого можно использовать hashmap. Еще раз изменим загрузчик:

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «сайт», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score!



Android Studio: модуль не будет отображаться в «Редактирование конфигурации» (13)

Иногда ошибки существуют в Android-манифесте из-за того, что есть крест, как изображение через конфигурацию запуска / отладки, поэтому попробуйте просмотреть, если Android-манифест имеет какие-либо ошибки в одном случае.

Я импортировал проект в Android Studio с несколькими подпроектами.

Я хочу запустить подпроект.

Я успешно сделал это подпроекты build.gradle как модуль.

Чтобы запустить его, я перешел в меню «Выполнить»> «Редактирование конфигураций»> «Приложение Android».

Проблема. Когда я пытаюсь выбрать модуль, ни один из них не отображается в раскрывающемся списке.

Почему это?

EDIT: он отображается как модуль под Groovy, но не в приложении Android. Как я могу получить его в Android-приложении?

goto Android >> Gradle Scripts >> Build Gradle (Module: app)

убедитесь, что первая строка этого файла похожа на это.

Apply plugin: "com.android.library"

Для меня это было исправлено, просто перезапустив Android Studio .. Как и старые добрые времена Eclipse

Для моего случая, новичок я взревел свой проект, не уверен, как, но он больше не будет работать и жаловался на манифест, R, все. Я понял, что некоторые, как в моих настройках. Gradle не include ":app" только я добавил это, я снова был в пути.

Наконец, я выяснил, почему модуль не отображается, когда я добавляю конфигурацию для AndroidTests для модуля com.android.library .

Если вы build.gradle свой библиотечный модуль в build.gradle приложения следующим образом:

Compile project(":yourlibrary")

Поскольку для библиотечного модуля по умолчанию он скомпилирован с режимом release , вы не можете запустить Android Tests для него, поэтому он не будет отображаться в списке модулей. Я исправил его с помощью следующей модификации:

Добавьте следующую конфигурацию в build.gradle вашего библиотечного модуля:

PublishNonDefault true

build.gradle следующие изменения, вы можете debug компиляцию своей библиотеки, редактируя build.gradle вашего прикладного модуля, например:

Compile project(":yourlibrary") + debugCompile project(path: ":yourlibrary", configuration: "debug") + releaseCompile project(path: ":yourlibrary", configuration: "release")

Затем синхронизируйте его, и вы найдете его в списке.

Похоже, что разные решения работают для людей с разницей, поскольку я просто закрываю проект, а импорт его снова разрешил проблему.

У меня была аналогичная проблема, когда я выбрал родительский каталог моего проекта, я разрешил Close Project -> Удалить проект из Android Studio -> Import Project , выбрав файл right build.gradle .

Убедитесь, что вы выбрали правильный файл build.gradle во время импорта.

Убедитесь, что ваш build.gradle

Apply plugin: "com.android.application"

После того, как вы изменились, повторите синхронизацию.

Это происходит, главным образом, при копировании проекта библиотеки и его создании. Решением было бы добавить

Apply plugin: "com.android.application"

в файле build.gradle, вместо

Apply plugin: "com.android.library"

Затем выполните градиентную синхронизацию

orderEntry type = "library" exported = "" name = "appcompat-v7-19.1.0" level = "project" />

Я исправил это, добавив грани в настройки модуля . Они пропали без вести. > открыть Настройки модуля > Границы > Добавить грани (знак «+» вверху)> Android . После добавления граней у вас будут модули.

ОБНОВИТЬ:

Для последней версии градиента Facets были удалены , теперь вы можете напрямую добавлять модули. щелкните правой кнопкой мыши по проекту > откройте настройки модуля > Добавить модуль (вверху знака «+»)> Приложение «Телефон и планшет» (теперь вы можете создать новый модуль и настроить его).

добавьте ваш moudle в свои приложения. iml-файл вроде: orderEntry type = "module" module-name = "yourmoudlename" exported = ""