- Секретные коды, или как я писал свое приложение для android
- Вступление
- Часть первая. События в Android
- Часть вторая. Реагируем на код
- Часть третья. Ищем партизанов
- Часть последняя. Для самых терпеливых.
- Как устроен билд APK файла внутри
- Процесс создания APK и компиляции кода
- Рассматриваемые темы
- Архитектура процессоров и зачем нужна виртуальная машина
- Понимание Java виртуальной машины
- Андроид виртуальная машина
- Комплияция в .dex файл
- ART против Dalvik
- Каждый этап описанного процесса
- Source Code (Исходный код)
- Resource Files
- AIDL Files
- Library Modules
- AAR Libraries
- JAR Libraries
- Android Asset Packaging Tool
- resources.arsc
- D8 и R8
- Dex and Multidex
Секретные коды, или как я писал свое приложение для android
Думаю все, у кого есть устройство на базе ОС Android, хотя-бы краем уха слышали о «секретных кодах».
Однако поиск по Хабру показал что здесь нет ни одной статьи на данную тему. А ведь некоторые коды довольно могущественные: например один из кодов на моем Samsung Galaxy Tab позволяет настроить GPS что ускоряет поиск спутников, другой — жестко установить режим связи с сетью(GPRS, EDGE, 3G. ) что в местах с нестабильной связью позволяет хорошо сэкономить батарею на скачках между режимами.
Но повествование я поведу не сколько про возможности кодов а про исследование механизма запуска приложений по кодам в ОС Android, как найти все коды(и приложение в которое это всё вылилось). И еще немного про то, как сделать приложение которое будет отзываться на свой код.
Под катом 6 картинок, немного кода и много текста… Самых нетерпеливых прошу сразу в конец статьи помацать результаты а уж потом — читать технологию.
Вступление
Про коды в Android я слышал давно. Наиболее распространённый — *#*#4636#*#* — это информация о телефоне, батарее, состоянии сети и т.д.
Но недавно я установил себе программу Autostarts, сделал поиск по установленным приложениям и (О чудо!) увидел странное событие «Secret Code Entered». На него отвечала целая куча приложений! Этот факт подвигнул меня на более глубокий поиск на эту тему. Вот что я выяснил:
Часть первая. События в Android
Как известно, каждое приложение Android содержит в себе манифест. Это специально сформированный XML файл содержащий информацию какая целевая версия ОС, какие возможности разрешения требуются приложению для работы и т.д. Самое интересное в этом манифесте — секции описывающие BroadcastReceiver’ы. Это классы, которые реагируют на наступление определенных событий. Этих событий много, например: совершается исходящий звонок(android.intent.action.NEW_OUTGOING_CALL), изменилось состояние режима «полёт» (android.intent.action.ACTION_AIRPLANE_MODE_CHANGED)… Официальный список можно увидеть на сайте Android.
Однако список отнюдь не полон т.к. каждое приложение может создавать своё событие. Это вносит некоторый хаос в документацию при попытке выяснить на что может реагировать приложение.
Именно в этом хаосе удачно спряталось событие, которое представляет огромный интерес: android.provider.Telephony.SECRET_CODE
Как показало вскрытие исходных кодов штатной звонилки в Андроиде что при вводе чего-либо начинающегося на *#*# и заканчивающегося #*#* в номеронабирателе происходит поиск и передача сообщения тому BroadcastRecever’у который слушает именно этот код(то что между *#*# и #*#*)
Часть вторая. Реагируем на код
Теперь глянем что-же требуется от приложения что-бы среагировать на наступление данного события:
Как видно, добавить скрытые возможности в свои приложения Android очень даже просто.
Что делать в Receiver’е я умолчу, там уже ваш собственный путь, лично я — вызываю отладочное Activity.
Часть третья. Ищем партизанов
Теперь перейдем к поиску Receiver’ов, реагирующих на коды. Первой мыслью (и первой реализацией) был вот такой вот код:
for(int i=0;i
В точности код я не помню, он был затёрт за ненадобностью так как было найдено решение лучше. Данное же решение просто перебирает все коды с 0 до 10000, тот диапазон в котором находится значительная часть кодов. Но не все.
Именно это «не все» подвигло меня на более детальные поиски и привело к новому решению:
1) Берем список всех установленных приложений через PackageManager:
List pil = pm.getInstalledPackages(PackageManager.GET_DISABLED_COMPONENTS);
2) Из каждого пакета вытаскиваем его манифест:
AssetManager am = context.createPackageContext(p.packageName, 0).getAssets();
xml = assets.openXmlResourceParser(«AndroidManifest.xml»);
3) Простая магия с разбором манифеста и поиском нужных Receiver’ов, IntentFilter’ов, Action’ов.
4) Профит.
У этого метода есть всего один недостаток: он был замечен на приложении SuperUser от ChainsDD. Дело в том что данное приложение имеет кривой манифест который выглядит как-то так:
Как видите, в нем не указан код, на который следует реагировать и Receiver вызывается при вводе любого кода. Декомпилировав эту программу я убедился что сделано это по ошибке а не следуя желанию вести лог всех введенных кодов, т.к. в самом Receiver’е происходит проверка на равенство кода заданному значению и если код не равен заданному — то ничего не происходит 🙁 т.е. этот Receiver запускается при каждом вводе кода, чего можно было избежать указав какой именно код должен пробуждать Receiver.
Часть последняя. Для самых терпеливых.
Последнюю часть оставил для презентации результатов.
Результатом всех этих расследований стала замечательная(не побоюсь этого слова) программа, аналогов которой на маркете обнаружено не было: Секретные Коды
Кроме описанной выше возможности искать секретные коды программа также позволяет:
— Запускать найденные коды
— Комментировать/читать комментарии других пользователей о кодах. Это сделано что-бы люди которые боятся FactoryFormat’а могли удостоверится что код безопасен до его запуска, а бесшабашные экспериментаторы — написать что делает тот или иной код. Мной лично было запущенны ВСЕ доступные коды на Samsung Galaxy Tab 7″ и откомментированны все коды которые выводят хоть какую-то информацию. (Кстати успешно пережил FactoryFormat, т.к. заранее сделал backup всех приложений и данных.)
— Назначать кодам значки для большей наглядности списка кодов.
На закуску 6 ScreenShot’ов:
Главное Activity:
Activity поиска кодов:
Поиск кодов завершен:
Список кодов:
Activity кода:
Некоторые из доступных значков для обозначения кода:
P.S. на SreenShot’ах всего 3 кода т.к. они делались на эмуляторе. На моём Galaxy Tab’е их более 100-а.
P.P.S статья опубликована по просьбе Владислава Аксёнова ввиду отсутствия у него аккаунта (кому понравилась статья и не жалко инвайта, вот e-mail, высылайте: grafmailgraf@mail.ru).
Написал статью BlackSwan. Спасибо krovatti за инвайт!
Вот и QR-ка:
Источник
Как устроен билд APK файла внутри
Процесс создания APK и компиляции кода
Рассматриваемые темы
- Архитектура процессоров и необходимость для виртуальной машины
- Понимание Java виртуальной машины
- Компиляция исходного кода
- Виртуальная машина Андроид
- Процесс компиляции в .dex файл
- ART против Dalvik
- Описание каждой части билд процесса
- Исходный код
- Файлы ресурсов
- AIDL файлы
- Модули библиотек
- AAR библиотеки
- JAR библиотеки
- Android Asset Packaging Tool
- resources.arsc
- D8 и R8
- Dex и Multidex
- Подписывание APK файла
- Ссылки
Понимание флоу процесса билда APK файла, среда исполнения и компиляция кода
Этот пост нацелен быть отправной точкой для разработчиков, чтобы они ближе познакомились с билд процессом и созданием APK файла.
Архитектура процессоров и зачем нужна виртуальная машина
Андроид после того как вышел в 2007 году претерпел множество изменений связанный с билд процессом, средой исполнения и улучшениями производительности.
У андроида много удивительных характеристик и одна из них разные архитектуры процессоров такие как ARM64 и x86
Невозможно скомпилировать код, который поддерживает каждую архитектуру. Вот именно поэтому используется Java виртуальная машина.
Понимание Java виртуальной машины
JVM это виртуальная машина, позволяющая устройству запускать код, который скомпилирован в Java байткод
Используя JVM, вы избавляетесь от проблемы с разной архитектурой процессоров.
JVM предоставляет переносимость и она позволяет запускать Java код в виртуальной среде, вместо того, чтобы запускать его сразу «на железе»
Но JVM была создана для систем с большими мощностями по ресурсам, а наш андроид имеет сравнительно мало памяти и заряда батареи.
По этой причине Google создал адаптированную под андроид виртуальную машину, которая называется Dalvik.
Компилируем исходный код
Наш исходный Java код для андроида компилируется в класс файл .class с байткодом с помощью javac компилятора и запускается на JVM
Для котлина есть kotlinc компилятор, который делает совместимый с Java байткод.
Байткод — это набор инструкций, который выполняется на целевом устройстве.
Java байткод — это набор инструкций для Java виртуальной машины.
Андроид виртуальная машина
Каждое андроид приложение работает на своей виртуальной машине. С версий 1.0 до 4.4, это был Dalvik. В андроид 4.4, вместе с Dalvik, Google представил в качестве эксперимента новый андроид runtime, который назывался ART
Сгенерированный класс файл .class содержит JVM Java байткод.
Но у андроида есть свой собственный оптимизированный формат байткода, который называется Dalvik bytecode — это просто инструкции машинного кода для процессора также как и JVM байткод.
Комплияция в .dex файл
Во время компиляции происходит конвертация .class класс файл и .jar библиотеки в один classes.dex файл, который содержит Dalvik байткод.
Команда dx превращает все .class и .jar файлы в один classes.dex файл, который написан с форматом Dalvik байткода.
Dex — это аббревиатура с английского — Dalvik Executable.
ART против Dalvik
C версии 4.4 андроид мигрировал на ART. ART также работает с .dex файлом.
Преимущество ART над Dalvik проявляется в том, что приложения запускаются быстрее, потому что весь DEX байткод транслируется в машинный код во время установки, не нужно дополнительного времени на компиляцию в рантайме.
ART и Dalvik совместимы, так что приложения разработанные для Dalvik должны работать и на ART.
Компиляция Dalvik (JIT- just in time) имела такие минусы как — быстрая трата батареи, лаги в приложениях и плохой перформанс. В Dalvik трансляция происходит только когда это нужно. Мы открываем новый экран и только в этот момент происходит трансляция, за счет этого установка происходит быстрее, но при этом проседает перформанс.
Это причина по которой Google сделал Android Runtime (ART).
ART — основан на AOT (ahead of time) компиляции, она происходит до того как приложение запустится.
В ART компиляция происходит во время установки приложения. Это ведет к более долгому времени установки, но уменьшает трату батареи и избавляет от лагов, которые были на Dalvik.
Несмотря на то, что Dalvik был заменен на ART, .dex формат файлов еще используется
В андроид 7.0 JIT вернулся. Гибридная среда сочетает фичи как от JIT компиляции так и
от ART
Среда запуска байткода это очень важная часть андроида и она вовлечена в процесс запуска и установки приложения
Каждый этап описанного процесса
Source Code (Исходный код)
Это Java и Kotlin файлы в src пакете.
Resource Files
Файлы находящиеся в директории с ресурсами
AIDL Files
AIDL — аббревиатура Android Interface Definition Language, позволяет вам описать интерфейс межпроцессорного взаимодействия.
AIDL — может использоваться между любыми процессами в андроиде.
Library Modules
Модули библиотек содержат Java или Kotlin классы, компоненты андроида и ресурсы.
Код и ресурсы бибилотеки компилируются и пакуются вместе с приложением.
Поэтому модуль библиотеки может считаться компайл тайм артефактом.
AAR Libraries
Андроид библиотеки компилируются в AAR — android archive файл, который вы можете использовать как зависимость для вашего android app модуля.
AAR файлы могут содержать андроид ресурсы и файл манифеста, что позволяет вам упаковать туда общие ресурсы такие как layouts и drawables в дополнение к Java или Kotlin классам и методам.
JAR Libraries
JAR это Java библиотека и в отличие от AAR она не может содержать андроид ресурсы и манифесты.
Android Asset Packaging Tool
AAPT2 — аббревиатура (Android Asset Packaging Tool) — компилирует манифест и файлы ресурсов в один APK.
Этот процесс разделен на два шага компиляцию и линковку Это улучшает производительность так как если вы поменяете один файл, вам нужно компилировать только его и прилинковать к остальным файлам командой ‘link’
AAPT2 может компилировать все типы андроид ресурсов, таких как drawables и XML файлы.
При вызове AAPT2 для компиляции, туда передается по одному ресурсному файлу на каждый вызов
Затем APPT2 парсит файл и генерирует промежуточный бинарный файл с расширением .flat
Фаза линковки склеивает все промежуточные файлы сгенерированные в фазе компиляции и дает нам на выход один .apk файл. Вы также можете сгенерировать R.java файл и правила для proguard в это же время.
resources.arsc
Полученный на выходе .apk файл не включает в себя DEX файл, APK не подписан и не может быть запущен на устройстве.
APK содержит AndroidManifest, бинарные XML файлы и resources.arsc
resource.arsc содержит всю мета информацию о ресурсах, такую как индексы всех ресурсов в пакете
Это бинарный файл и APK который может быть запущен. APK который вы обычно создаете и запускаете не сжат и может быть использован просто посредством размещения в памяти.
R.java файл это выходной файл вместе с APK ему назначен уникальный id, который позволяет Java коду использовать ресурсы во время компиляции.
arsc это индекс ресурса который используется во время запуска приложения
D8 и R8
Начиная с андроид студии 3.1 и далее, D8 был сделан дефолтным компилятором.
D8 производит более маленькие dex файлы с лучшей производительностью, если сравнивать со старым dx.
R8 используется для компиляции кода. R8 это оптимизированная версия D8
D8 играет роль конвертера класс файлов в Dex файлы, а также производит дешугаринг функций из Java 8 в байткод, который может быть запущен на андроиде
R8 оптимизирует dex байткод. Он предоставляет такие фичи как оптимизация, обфускация, удаление ненужных классов.
Обфускация уменьшает размер вашего приложения укорачивая названия классов, методов и полей.
Обфускация имеет и другие преимущества для предотвращения реверс инжиниринга, но основная цель уменьшить размер.
Оптимизация уменьшает размер Dex файла путем переписывания ненужных частей кода и инлайнинга.
С помощью дешугаринга мы можем использовать удобные фичи языка Java 8 на андроиде.
Dex and Multidex
R8 дает на выходе один DEX файл, который называется classes.dex
Если количество методов приложения переваливает за 65,536, включая подключенные библиотеки, то произойдет ошибка при билде
Источник