Когда мы говорим о плагинах и модульных приложениях, то в первую очередь имеем в виду обычный пользовательский софт. Однако модульный дизайн может быть не менее полезен при разработке руткитов и бэкдоров. Обычными средствами обновлять такой софт слишком палевно, да и не всегда возможно, а вот незаметно подгрузить модуль с новой функциональностью по сети - это пожалуйста. А если вынести ключевую функциональность в модули и удалять их сразу после загрузки, то можно серьезно подпортить жизнь реверсеру.
В классической 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() . Обрати внимание на три момента:
Чтобы проверить данный код на работоспособность, создадим простейший модуль:
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 модулей с множеством методов, принимающих несколько параметров, нужно придумать что-то более удобное. Например, использовать заранее определенный интерфейс, который будет реализовывать каждый модуль.
Применив такой подход к приведенному выше примеру, мы получим следующие три файла:
Это все. Теперь мы можем работать с модулем, как с обычным объектом. Более того, система сама отбракует модули (классы), несовместимые с интерфейсом, еще на этапе загрузки, поэтому нам не придется задаваться вопросами, а есть ли в модуле нужный нам метод.
С одним модулем разобрались, но что, если их будет много? Как вести учет этих модулей и не потеряться среди них? На самом деле все просто - для этого можно использовать hashmap. Еще раз изменим загрузчик:
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score!
У меня есть проект, созданный с помощью Gradle в Android Studio v 0.3.2. Мой проект имеет зависимости от двух других модулей ( ная библиотека). Структура проекта хорошо определена с помощью файлов build.gradle. Проблема в том, что … когда я запускаю проект на Android-устройстве, я устанавливаю 3 на моем устройстве. Один из них – основной проект (единственный правильный), а два других – импортированные модули (эти два я не хочу устанавливать). Как я могу это достичь? Или что я делаю неправильно?
Структура проекта:
Где 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 для получения дополнительной информации.
Установленные плагины находятся в меню File | Settings... | Plugins . Кнопка Browse repositories... позволяет найти плагин в репозитории. Кнопка Install plugin from disk... позволяет установить плагин с диска, если вы его скачали самостоятельно.
"Радужные скобки" позволяют пометить каждую пару скобок своим индивидуальным цветом. Это помогает визуально видеть, где находится область кода.
Заменяет все индикаторы прогресса в студии на няшного котика. Если вы серьёзный программист, то просто обязаны установить плагин . Совместимо с другими средами разработки на основе IntelliJ IDEA: PhpStorm, WebStorm, PyCharm, RubyMine, AppCode, CLion, Gogland, DataGrip, Rider, MPS.
Появляется везде. Например, при загрузке проекта.
Во время работы при синхронизации чего-либо.
Удобный генератор готовых Java и Kotlin POJO классов из JSON: GSON, FastJSON, AutoValue (GSON), Logan Square, Jackson.
Плагин для Android Studio/Intellij IDEA для быстрых операций над приложением:
После установки эти команды можно найти через Tools | Android | ADB IDEA .
Также можно вызвать окно поиска действий через комбинацию клавиш Ctrl+Shift+A и с помощью символов ADB быстро найти конкретную команду.
Плагин удобен для проверки работоспособности приложения в разных состояниях. Например, вы ранее создали базу данных и решили посмотреть, как поведёт себя приложение при пустой базе. С помощью плагина вы быстро можете очистить данные и посмотреть на результат.
На недавно прошедшей Google I/O 2018 , среди множества нововведений, объявили также о добавлении нового формата приложений.
Этот формат получил название Android App Bundle и представляет собой улучшенный способ сборки вашего приложения. С его помощью можно легко оптимизировать размер приложения, при этом не нужно будет вносить какие-либо изменения в код. Android App Bundle включает весь скомпилированный код и ресурсы, отсеивая затем то, что не нужно конкретному устройству.
Важно! На данный момент Android App Bundle работает только в preview-версии Android Studio. Последняя версия Android Studio 3.2 Canary доступна .
Android App Bundle представляет собой файл (с расширением .aab ), который загружается в Google. Каждый бандл включает скомпилированный код и ресурсы для всех модулей приложения и поддерживаемых конфигураций устройств.
Проще говоря, бандлы это подписанные ZIP-файлы, которые упорядочивают код и ресурсы приложения в модули.
Из этих модулей Google Play генерирует различные APK, которые предоставляются пользователям, такие как: базовые APK, dynamic feature APK, конфигурационные APK и (для устройств, которые не поддерживают разделённые APK) мульти-APK. Каталоги, окрашенные в синий цвет, представляют собой код и ресурсы, которые Google Play использует для создания конфигурационного APK для каждого модуля.
Примечание: бандл нужно создавать для каждого уникального приложения или applicationID . То есть, если вы используете несколько product flavor в своём приложении для создания различных APK, и каждая из этих веток использует уникальный applicationID, то вам нужно будет создать отдельный бандл для каждой ветки.
Код и ресурсы для каждого модуля организованы аналогично стандартным APK, и это логично, поскольку каждый из этих модулей может быть сгенерирован как отдельный APK. Ниже можно увидеть более подробное описание некоторых файлов и каталогов Android App Bundle:
Создание бандла с помощью Android Studio очень похоже на создание APK. Для сборки достаточно выбрать в меню Build - Build Bundle(s)/APK(s) > Build Bundle(s)
и IDE создаст бандл для выбранного варианта сборки и разместит его в каталоге
Если создаётся бандл для debug-версии приложения, Android Studio автоматически подпишет бандл с помощью отладочного ключа подписи. Для загрузки бандла в Google Play он должен быть подписан.
После того, как Android Studio завершит создание подписанного бандла, его можно будет открыть и проанализировать. Анализ бандла позволяет проверить содержимое и работает аналогично APK Analyzer .
Для создания App Bundle IDE использует тот же инструмент с открытыми исходным кодом, называемый bundletool , который Google Play использует для последующего преобразования бандла в подписанные APK.
Прежде чем загрузить бандл в консоль Google Play, его нужно подписать. Чтобы создать подписанный App Bundle, нужно выполнить следующие действия:
После того, как Android Studio завершит создание подписанного бандла, его можно будет найти и проанализировать, выбрав соответствующую опцию во всплывающем уведомлении. Если был выбран экспорт ключа подписи, то к нему можно будет быстро перейти, щёлкнув по стрелке вниз в правом нижнем углу всплывающего уведомления, чтобы развернуть его, и затем выбрав Show Exported Key File .
После того, как бандл создан, его можно загрузить в Google Play для проверки, тестирования или публикации приложения. Прежде чем приступить к работе, следует соблюсти следующие условия:
Когда бандл загружен, Google Play автоматически генерирует разделённые APK и мульти-APK для всех конфигураций устройств, поддерживаемых приложением. В Play Console можно можно использовать App Bundle Explorer для просмотра всех вариантов APK, сгенерированных Google Play; анализа данных, таких как поддерживаемые устройства и экономия размера APK; загрузки созданных APK для тестирования.
После загрузки приложения в Play Console, для обновления приложения достаточно повысить код версии, а также создать и загрузить новый бандл. Затем Google Play сгенерирует обновлённые APK с новым кодом версии и будет предоставлять их по мере необходимости.
Использование Android App Bundle даёт большие преимущества для оптимизации APK приложений. С помощью этого способа мы обновили одно из наших приложений, "Менеджер паролей от Wi-Fi сетей ", заменив в нём стандартный APK на App Bundle. Таким образом, размер APK файлов уменьшился на целый мегабайт, что является очень хорошим результатом.
Кроме того, Google на данный момент тестирует дополнение к App Bundle, Dynamic feature modules, с помощью которого можно разбивать базовый APK на части, которые будут докачиваться при необходимости, пока что эта технология находится в бета-версии.
Возможно, единственным недостатком банлдов на данный момент назвать необходимость использовать preview-версию Android Studio, однако эта проблема временная.