Редактирование файла манифеста android. Манифест приложения

Редактирование файла манифеста android. Манифест приложения

В корневой папке каждого приложения должен находиться файл AndroidManifest.xml (который именно так и называется). Файл манифеста содержит важную информацию о приложении, которая требуется системе Android. Только получив эту информацию, система может выполнить какой-либо код приложения. Среди прочего файл манифеста выполняет следующие действия:

  • Он задает имя пакета Java для приложения. Это имя пакета служит уникальным идентификатором приложения.
  • Он описывает компоненты приложения — операции, службы, приемники широковещательных сообщений и поставщиков контента, из которых состоит приложение. Он содержит имена классов, которые реализуют каждый компонент, и публикует их возможности (указывает, например, какие сообщения они могут принимать). На основании этих деклараций система Android может определить, из каких компонентов состоит приложение и при каких условиях их можно запускать.
  • Он определяет, в каких процессах будут размещаться компоненты приложения.
  • Он объявляет, какие разрешения должны быть выданы приложению, чтобы оно могло получить доступ к защищенным частям API-интерфейса и взаимодействовать с другими приложениями.
  • Он также объявляет разрешения, требуемые для взаимодействия с компонентами данного приложения.
  • Он содержит список классов , которые при выполнении приложения предоставляют сведения о профиле и прочую информацию. Эти объявления присутствуют в файле манифеста только во время разработки и отладки приложения и удаляются перед его публикацией.
  • Он объявляет минимальный уровень API-интерфейса Android, который требуется приложению.
  • Он содержит список библиотек, с которыми должно быть связано приложение.

Структура файла манифеста

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

. . . . . . . . .

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

Соглашения о компонентах файла

Ко всем элементам и атрибутам из файла манифеста применяется рад соглашений и правил:

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

Если в элементе и есть какое-то содержимое, то это другие элементы. Все значения задаются с помощью атрибутов, а не как символьные данные в элементе.

Элементы, находящиеся на одном уровне, обычно не упорядочиваются. Например, элементы , и можно указать в любой последовательности. (Элемент является исключением из этого правила. Он должен следовать за элементом , псевдонимом которого он является.)

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

За исключением некоторых атрибутов корневого элемента , имена всех атрибутов должны начинаться с префикса android: — например, android:alwaysRetainTaskState . Поскольку этот префикс является универсальным, в документации при указании атрибутов по имени он обычно опускается.

Объявление имен классов Многие элементы соответствуют объектам Java, в том числе элементы для самого приложения (элемент ) и основных его компонентов — операций (), служб (), приемников широковещательных сообщений () и поставщиков контента ().

Если вы определяете подкласс, а это практически всегда делается для классов компонентов ( , и ), выполняется это с помощью атрибута name . В состав имени должно входить полное обозначение пакета. Например, подкласс можно объявить следующим образом:

. . . . . .

Однако его можно укоротить. Если первым символом в строке указать точку, эта строка будет добавляться к имени пакета приложения (указанного атрибутом элемента ). Следующее назначение является таким же, как приведенное выше:

. . . . . .

При запуске компонента Android создает экземпляр подкласса, указанного по имени. Если подкласс не указан, система создает экземпляр базового класса.

Несколько значений Если можно указать несколько значений, элемент почти всегда приводится повторно. Делается это вместо перечисления нескольких значений в одном элементе. Например, в фильтре Intent может быть перечислено несколько действий: . . . Значения ресурсов Значения некоторых атрибутов могут отображаться на экране — например, метка и значок операции. Значения этих атрибутов следует локализовать, поэтому они должны задаваться в ресурсе или теме. Значения ресурсов выражаются в следующем формате:

@[пакет:]тип:имя

где имя пакета можно опустить, если ресурс находится в одном пакете с приложением, тип - это тип ресурса, — например "string" или "drawable", — а имя - это имя, определяющее ресурс. Например:

Значения из темы выражаются схожим образом, только в начале у них идет " ? ", а не " @ ":

?[пакет:]тип:имя

Строковые значения Когда значением атрибута является строка, следует использовать двойную обратную косую черту (" \\ ") для выделения управляющей последовательности символов, — например " \\n " для новой строки или " \\uxxxx " для символа Юникода.

Отображение функций в файле

В следующих разделах описано, как некоторые функции Android отображаются в файле манифеста.

Фильтры объектов Intent

Базовые компоненты приложения (его операции, службы и приемники широковещательных сообщений) активируются объектами Intent . Intent - это совокупность информации (объект ), описывающей требуемое действие, — в том числе в ней указаны данные, с которыми следует выполнить это действие, категория компонентов, которые должны выполнять это действие, и другие уместные инструкции. Система Android находит компонент, который отреагирует на объект Intent, запускает новый экземпляр компонента, если он требуется, и передает ему объект Intent.

Компоненты объявляют свои возможности — виды объектов Intent, на которые они могут реагировать, — с помощью фильтров Intent . Поскольку система Android должна узнать, какие объекты Intent может обрабатывать тот или иной компонент, до того как она его запустит, фильтры Intent указываются в файле манифеста как элементы . Компонент может иметь любое количество фильтров, каждый из которых описывает отдельную возможность компонента.

Объект Intent, в котором целевой компонент явно указан по имени, активирует этот компонент, и фильтр при этом не учитывается. Но объект Intent, в котором имя целевого компонента не указано, может активировать компонент, только если он может пройти через один из фильтров компонента.

Сведения о том, каким образом объекты Intent проверяются по фильтрам Intent, см. в отдельном документе .

Значки и метки

У ряда элементов есть атрибуты icon и label для небольшого значка и текстовой метки, которые могут отображаться на экране. У некоторых из них также есть атрибут description для более длинного описательного текста, который также может отображаться на экране. Например, элемент имеет все три таких атрибута, поэтому, когда пользователю задается вопрос, предоставить ли разрешение запросившему его приложению, на экране может отображаться значок, представляющий разрешение, имя разрешения и описание того, что оно за собой влечет.

В любом случае значок и метка, заданные в элементе-контейнере, становятся параметрами icon и label , используемыми по умолчанию для всех вложенных в этот контейнер дочерних элементов. Так, значок и метка, заданные в элементе , являются значком и меткой, используемыми по умолчанию для каждого компонента приложения. Точно так же, значок и метка, заданные для компонента, — например элемента , — являются параметрами, используемыми по умолчанию для каждого элемента компонента. Если в элементе задана метка, а в операции и ее фильтре Intent - нет, метка приложения будет считаться меткой и для операции, и для фильтра Intent.

Значок и метка, заданные для фильтра Intent, используются для обозначения компонента, когда он представляется пользователю, для указания функции, которую анонсирует фильтр. Например, фильтр с параметрами " android.intent.action.MAIN " и " android.intent.category.LAUNCHER " сообщает, что эта операция инициирует приложение, — то есть он обозначает ее как операцию, которая должна быть отображена в средстве запуска приложений. Отсюда следует, что значок и метка, заданные в фильтре, отображаются в средстве запуска.

Разрешения

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

Каждое разрешение обозначается уникальной меткой. Зачастую метка обозначает действие, выполнение которого ограничивается. Например, вот некоторые разрешения, определенные системой Android:

android.permission.CALL_EMERGENCY_NUMBERS
android.permission.READ_OWNER_DATA
android.permission.SET_WALLPAPER
android.permission.DEVICE_POWER

Функцию можно защитить не более чем одним разрешением.

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

Приложение также может защищать с помощью разрешений собственные компоненты (операции, службы, приемники широковещательных сообщений и поставщиков контента). Оно может использовать любые разрешения, определенные системой Android (они приведены в объекте ) или объявленные другими приложениями. Либо оно может определить разрешения самостоятельно. Новое разрешение объявляется с помощью элемента . Например, операцию можно защитить следующим образом:

. . . . . .

Обратите внимание, что в этом примере разрешение DEBIT_ACCT не только объявляется с помощью элемента , его использование также запрашивается с помощью элемента . Чтобы другие компоненты приложения запускали защищенную операцию, ее использование должно быть запрошено, даже несмотря на то, что защита наложена самим приложением.

В этом же примере: если атрибут permission был бы задан как разрешение, объявленное где-то еще (например, android.permission.CALL_EMERGENCY_NUMBERS), его бы не нужно было объявлять еще раз с помощью элемента . Однако все равно нужно было бы запрашивать его использование с помощью .

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

Библиотеки

Каждое приложение связывается с используемой по умолчанию библиотекой Android, в которой имеются базовые пакеты для построения приложений (со стандартными классами, например Activity, Service, Intent, View, Button, Application, ContentProvider и так далее).

Однако некоторые пакеты находятся в собственных библиотеках. Если ваше приложение использует код из одного из таких пакетов, оно должно в явном виде потребовать, чтобы его связали с этим пакетом. Файл манифеста должен содержать отдельный элемент для указания имени каждой библиотеки. (Имя библиотеки можно найти в документации по пакету.)

AndroidManifest.xml – это так называемый «паспорт» любого приложения для ОС Android. Данный файл полностью описывает структуру, составляющие приложения и его требования. «Манифест» нужен любому приложению и для создания любой программы под Android его нужно составить правильно.

Существует официальная документация с описанием структуры файла AndroidManifest. xml , однако она достаточно объемная и сложная для восприятия, кроме того – на английском языке, так что мы постараемся изложить всю необходимую информацию в удобоваримой форме.

Итак, AndroidManifest. xml находится в корневой директории приложения и всегда имеет именно такое имя. Всё содержимое данного файла в теге - это корневой тег «манифеста». Например:

package=»com.hello.world»

android:versionCode=»1″

android:versionName=»1.1 Beta»>

Package – название данного программного пакета.

VersionCode – версия приложения (значение может быть использовано для внутренних нужд).

VersionName – значение версии, которое показывается пользователю.

Все остальные теги находятся внутри тега , и основные из них мы сейчас и рассмотрим.

Тег Uses-sdk содержим параметры, которые указывают на необходимую для работоспособности приложения версию SDK. Возможны такие параметры:

minSDKVersion - минимально допустимая версия SDK, чтобы запустить программу.

targetSDKVersion – «целевая» версия SDK, проще говоря – на данной версии проводилось тестирование приложения.

maxSDKVersion – верхняя допустимая версия SDK для работы приложение. Если нет стопроцентной уверенности в том, что на более новых версиях SDK приложение не будет работать, то данный параметр лучше не использовать вовсе.

android:targetSdkVersion=»5″>

Как видно, минимальная версия SDK – четвертая, а тестирование проводилось на пятой.

Тег Uses-Configeration определяет компбинацию допустимых методов ввода для приложения. Возможны следующие параметры:

reqFiveWayNav – приложение будет требовать от устройства возможность навигации в четырех направлениях плюс нажатие (это, к примеру, оптический или пятипозиционный джойстик). Возможные значения: true, false.

reqHardKeyboard – приложение будет требовать обязательное наличие аппаратной клавиатуры. Возможные значения: true, false.

reqKeyboardType - требование приложения к типу клавиатуры, которое распространяется как на программную (сенсорную), так и на аппаратную клавиатуру. Значения:

undefined – значение по умолчанию, означает, что приложение не требует клавиатуру.

nokeys – аналогично предыдущему, приложение не требует клавиатуру.

twelvekey – приложение требует 12-символьную стандартную «телефонную» клавиатуру.

qwerty – приложение требует полную клавиатуру с раскладкой qwerty.

reqNavigation – требования приложения к возможным способам навигации на девайсе (трекбол, джойстик, колесико). Допустимые значения:

undefined – значение по умолчанию. У приложения к способу навигации требований нет.

nonav – у приложения к способу навигации требований нет.

dpad – приложению требуется D-pad для работы.

trackball – приложению нужен трекбол.

wheel – приложению требуется колесо навигации.

reqTouchScreen – обязательно наличие сенсорного экрана. Допустимые значения:

undefined – значение по умолчанию, наличие сенсорного экрана не требуется.

notouch – наличие сенсорного экрана не требуется.

stylus – необходим сенсорный экран резистивного типа (управляемый стилусом).

finger – необходим сенсорный экран емкостного типа (управляемый пальцем).

android:reqKeyboardType=[«qwerty»/>

android:reqNavigation=[«trackball»]

android:reqHardKeyboard=[«true»]

android:reqKeyboardType=[«twelvekey»]/>

Тег User-Feature определяет необходимые аппаратные и программные возможности устройства. Полный список всех допустимых требований приведен в официальной документации для AndroidManifest. xml - http://developer.android.com/guide/topics/manifest/uses-feature-element.html#features-reference .

Для примера, требование приложением обязательного наличия камеры в устройстве:

android:name=»android.hardware.camera» />

Данный тег определяет поддерживаемые приложением разрешения экрана. Можно указать несколько параметров в качестве допустимых разрешений экрана. Допустимые параметры:

smallScreens – приложение поддерживает нестандартные и малые разрешения дисплея (такие как HVGA, QVGA).

normalScreens – приложение поддерживает стандартные разрешения (такие как HVGA, WVGA, WQVGA).

largeScreens – приложение поддерживает устройства с высокой разрешающей способностью дисплея.

anyDensity – допустимо любое разрешение экрана.

Значения для всех параметров false или true.

android:normalScreens=[«true»]

android:largeScreens=[«true»]

android:anyDensity=[«false»] />

Тег Application – один из основных. Здесь описываются такие параметры приложения, как его название, иконка, ссылка на пользовательский интерфейс и много чего еще. Кроме того, данный тег – это контейнер для других тегов, которые описывают те или иные компоненты программы, в том числе Service, Activity, Content Provider и Broadcast Receiver. О .

android:theme=»@style/my_theme»

android:name=»MyApplication»

android:debuggable=»true»>

Тег создается для каждого имеющегося в приложении Activity. Кроме того, каждый Activity, в свою очередь, поддерживает тег , чтобы определить запускающий Activity Intent.

Тег нужен для описанию каждого имеющегося в приложении класса Services. Как и , тег поддерживает дочерний тег .

Тег Используется для описания каждого Content Provider в программе.

android:name=».MyContentProvider»

android:enabled=»true»

android:authorities=»com.paad.myapp.MyContentProvider»>

Тег необходим для объявления Broadcast Receivers, не запуская само приложение. То есть в теге могут описываться события, на которые приложение должно реагировать.

android:label=»My Intent Receiver»

android:name=».MyIntentReceiver»>

Раздел, в котором происходит описание всех необходимых для корректной работы приложения разрешений. Допустим, если приложению для работы необходимо соединение с интернетом, то это будет иметь следующий вид:

Полный список всех допустимых разрешений можно получить из официальной документации – http://developer.android.com/reference/android/Manifest.permission.html .

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

android:protectionLevel=»dangerous»

android:label=»Self Destruct»

android:description=»@string/detonate_description»>

Вот, в целом, и вся структура AndroidManifest. xml . Несмотря на сравнительную простоту, данный файл имеет ключевое значение в работоспособности любого приложения, а потому ему должно быть уделено должное внимание при собственноручном создании программного обеспечения для ОС Android.

AndroidManifest.xml - необходимый файл для каждого приложения Android. Он расположен в папке приложения и описывает глобальные значения для Вашего пакета, включая прикладные компоненты (действия, службы, и т.д), который пакет выставляет ‘внешнему миру’, какие данные каждое из Activity приложения может обработать, и как они могут быть начаты.

Важная вещь к упоминанию об этом файле - свой так называемый IntentFilters. Эти фильтры описывают где и когда Activity может быть начат. Когда Activity (или операционная система) хочет выполнить действие, такое, как открыть Web-страницу или открыть экран выбора, это создает объект Intent. Этот Intent может хранить информацию, описывающую, что Вы хотите сделать, какие данные необходимы, чтобы достигнуть этого и другую информацию. Андроид сравнивает информацию в объекте Intent с IntentFilters, выставленным каждым приложением, и находит Activity, соответствующие, чтобы обработать данные или действия, определенные вызывающей программой. Если есть больше чем одно приложение, способное к обработке этого Intent , пользователя спрашивают, каким приложением он предпочел бы обрабатывать это.

Помимо объявления Activity, Content Provider, Service и Intent Receivers Вашего приложения, Вы можете также определить разрешения в AndroidManifest.xml.

Основное

Очень простой AndroidManifest.xml выглядит следующим образом:

android:label="@string/app_name">

Почти каждый AndroidManifest.xml (так же как многие другой Андроид файлы XML) будет включать объявление пространства имен в его первый элемент. Это делает множество стандартных атрибутов Андроид доступным в файле, который будет использоваться, чтобы снабдить большинством данных для элементов в том файле.

Почти каждый AndroidManifest.xml включает единственный тэг, который непосредственно содержит несколько тэгов, описывающих Applications, IntentReceivers, и т.д., которые доступны в этом приложении.

Если Вы хотите сделать Activity запускаемым непосредственно через пользователя, то Вы должны будете прописать ему поддержку действия MAIN и категории LAUNCHER. Результат как показано здесь:

Напрямую запускаемый Activity.

Дальше следует, детальный разбор структуры файла AndroidManifest с описыванием всех доступных , с примером для каждого. (Примеры не везде, но я точно ничего не потерял. И фраза “для каждого” в англ. версии (“for each”) тоже была. Не знаю, где они потеряли эти примеры. – прим. переводчика). Кто чей потомок, можно определить по отступу:

Это корневой узел каждого AndroisManifest.xml. Он содержит пакета атрибутов, который указывает на какой-то конкретный пакет в Activity (Получилось не совсем по-русски, но, вообщем, фишка в том, что в коде есть пакет Activity, а вот параметры этого пакета описаны в этом теге. - прим. переводчика). Другой путь к Activities будет базироваться относительно его значения.

Описывает разрешения безопасности, которы нужно предоставить Вашему пакету. Количество не ограничено.

Объявляет разрешение безопасности, которое может использоваться, чтобы указать, какие приложения могут обратиться к компонентам или особенностям в этом пакете. Количество не ограничено.

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

< application >

Корневой элемент, содержащий объявления компонентов на уровне, содержится в пакете. Этот элемент может также включать глобальные и/или заданные по умолчанию атрибуты для приложения, такие как метка, значок, тема, требование разрешения, и т.д. Количество – от нуля до единицы.

Activity - первичная вещь для приложения, чтобы взаимодействовать с пользователем. Экраном, который пользователь видит, запуская приложение, является Activity, и большинство других экранов, которые они используют, будет осуществлено как отдельные действия, объявленные с дополнительными тэгами Activity.

Примечание: у Каждой Activity должен быть тэг в manifest, выставлено ли это миру или предназначено для использования только в пределах собственного пакета. Если у Activity не будет никакого тэга соответствия в manifest, то Вы не сможете использовать ее.

Объявляет, какие Intent компонент поддерживает. В дополнение к различным видам значений, которые могут быть определены под этим элементом, атрибуты могут быть даны здесь, чтобы поставлять уникальную метку, значок, и другую информацию для описываемого действия.

Тип действия, который компонент поддерживает. Пример:

< category >

Тип MIME, URI схема или URI путь поддержки компонента.

Вы можете также связаться 1+ части метаданных с Вашим Activity:

Добавляет новую часть метаданных к Activity, которую клиенты могут восстановить через ComponentInfo.metaData.

IntentReceiver позволяет приложению сообщать о замене данных или о действиях, которые происходят, даже если приложение не выполняется в настоящее время. Как и с тэгом activity, в этот тег Вы можете произвольно включить больше одного или , так же, как с .

Service - компонент, который работает на заднем плане произвольное количество времени. В этот тег, как с тэгом activity, Вы можете произвольно включить один или более или .

ContentProvider - компонент, который управляет постоянными (persistent) данными и открывает к ним доступ другим приложениям. Вы можете также произвольно присоединить один или более , как и в activity. тут нету.

Конечно, все <теги> должны быть или так , или так, <напрямую/>.



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

Файл AndroidManifest.xml задает конфигурацию приложения:

  • объявляет имя Java-пакета приложения, который служит уникальным идентификатором
  • объявляет минимальный и максимальный уровни API, необходимые для работы приложения
  • описывает компоненты приложения (Activiy, Service, Broadcast Receiver и Content Provider)
  • перечисляет любые библиотеки связанные с приложением (помимо библиотек Андроид, связанных по умолчанию)
  • объявляет разрешения, которые требуются для работы приложения (например, доступ в сеть, разрешение на отправку SMS и т.д.)
На рисунке ниже можно увидеть общую структуру файла манифеста и его элементов. Рисунок взят из книги Голощапова и не содержит некоторых элементов. Перевод описания недостающих элементов я сделал сам. Но их в принципе не так много.

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

Элемент является корневым элементом файла AndroidManifest.xml. По умолчанию мастер создания проекта Андроид в Eclipse создает этот элемент с четырьмя атрибутами:

Эти атрибуты обязательны для любого приложения Андроид и имеют следующее назначение:

xmins:android — определяет пространство имен Android. Это значение всегда неизменно для всех приложений.

package — определяет уникальное имя пакета приложения, которое вы задали при создании проекта.

Для чего нужно указывать package? Если вы захотите загрузить ваше приложение на Google Play, то он проверяет уникальность при приеме приложения, поэтому рекомендуется использовать свое имя для избежания конфликтов с другими разработчиками.

android:versionCode — по сути это версия вашего приложения. Выпуская новую версию вы указываете её в этом поле, оно должно быть целым числом.

Выше мы говори про уникальность пакета, так вот если вы ранее загрузили на Google Play ваше приложение, то когда вы решите загрузить обновленную версию приложения, то вам нужно придерживаться нескольких правил. Имя пакета должно совпадать с тем, что уже загружено Google Play и указать версию android:versionCode на порядок выше. Но это при условии что вы выпускаете новую версию приложения, в случае если вы хотите добавить немного исправленную версию, то это читайте ниже.

Изменив данный параметр и загрузив приложение на Google Play все пользователям вашего приложения будет предложено обновится до новой версии приложения.

android:versionName - указывает номер пользовательской версии. Если вы нашли несколько недоработок в вашем приложении и исправили их, то в этом случае можно указать для этого поля новую версию, что будет говорить Google Play, что это не новая версия приложения, а улучшенная. Для именования версии можно использовать строку или строковый ресурс.

Изменив данный параметр и загрузив приложение на Google Play все пользователям вашего приложения будет предложено обновится до модифицированной версии приложения.

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

Разрешения предоставляются во время установки приложения, а не во время его работы . имеет единственный атрибут с именем разрешения android:name . Это может быть разрешение, определенное в элементе данного приложения, разрешение определенное в другом приложении, или одно из стандартных системных разрешений, например:

android:name=’android.permission.CAMERA’ – доступ к камере устройства
android:name=’android.permission.READ_CONTACTS’ – доступ к базе данных контактов

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

Приложение может также защитить свои собственные компоненты (Activity, Service, Broadcast Receiver и Content Provider) разрешениями. Оно может использовать любое из системных разрешений, определенных Андроид (перечисленных в android.Manifest.permission) или объявленных другими приложениями, а так же может определить свои собственные разрешения. Новое разрешение должно быть объявлено в атрибуте android:name элемента следующим образом:

permisson android:name=”com.samples.custom_permission”

Кроме того используются дополнительные атрибуты:

android:label — имя разрешения, отображаемое пользователю
android:description — описание разрешения
android:icon — значок разрешения
android:permissionGroup — определяет принадлежность к группе разрешений
android:protectionLevel — уровень защиты

Элемент объявляет базовое имя для дерева разрешений. Этот элемент объявляет не само разрешение, а только пространство имен, в которое могут быть помещены дальнейшие разрешения.

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

Элемент объявляет объект Instrumentation, который дает возможность контролировать взаимодействие приложения с системой. Обычно используется при отладке и тестировании приложения и удаляется из release-версии приложения.

Элемент позволяет объявлять совместимость приложения с указанной версией (или более новыми версиями API) платформы Android. Уровень API, объявленный приложением, сравнивается с уровнем API системы мобильного устройства, на который инсталлируется данное приложение.

Основной используемый в элементе атрибут – android:minSdkVersion , определяет минимальный уровень API, требуемый для работы приложения. Система Android будет препятствовать тому, чтобы пользователь установил приложение, если уровень API системы будет ниже, чем значение, определенное в этом атрибуте. Желательно всегда объявлять этот атрибут, например:

Атрибут android:targetSdkVersion представлен начиная с API Level 4. Это целое число, обозначающее API Level, для которого приложение предназначено (target, что означает цель). Если этот атрибут не установлен, то его значение по умолчанию равно minSdkVersion.

Этот атрибут информирует систему, что Вы тестировали приложение с этим API Level, и система не должна позволять любое поведение совместимости (compatibility behaviors, т. е. эмуляцию вызовов API, обеспечивающих специальную дополнительную программную обработку некоторых вызовов API), чтобы поддержать прямую совместимость приложения с целевой версией системы. Приложение все еще может работать на более старых версиях (до версий, не меньших minSdkVersion).

Поскольку Android развивается с каждой новой версией, то некоторые поведения и даже внешний вид приложения может измениться. Однако, если API level платформы выше, чем версия, указанная в targetSdkVersion приложения, система может включить обработки совместимости (compatibility behaviors), чтобы обеспечить работоспособность Вашего приложения так, как Вы этого ожидали. Вы можете запретить такие обработки совместимости, если укажете targetSdkVersion равным API level платформы Android, на которой приложение работает. Например, установка этого значения в "11" или более высокое значение позволит системе установить новую тему оформления по умолчанию (Holo) для Вашего приложения при работе на Android 3.0 или более новой, и также запретит режим совместимости экрана, когда программа будет работать на больших экранах (потому что поддержка API level 11 неявно подразумевает поддержку больших экранов).

Имеется много разновидностей обеспечения совместимости (compatibility behaviors), которые система может разрешить, базируясь на значении этого атрибута. Некоторые из этих обработок (поведений, behaviors) описаны в соответствующей документации версии платформы, см. Build.VERSION_CODES .

Чтобы обеспечить соответствие Вашего приложения каждому новому релизу Android, Вы должны увеличивать значение этого атрибута, чтобы оно соответствовало последнему API level, и затем необходимо полностью протестировать поведение приложения на этой новой версии платформы.

Атрибут android:maxSdkVersion представлен начиная с API Level 4. Это целое число, обозначающее максимальный API Level, на котором приложение может работать.

На версиях Android 1.5, 1.6, 2.0 и 2.0.1 система проверяет значение этого атрибута, когда инсталлируется приложение, и когда приложение проверяется на совместимость после обновления системы. В любом случае, если атрибут приложения maxSdkVersion меньше API Level системы, то установка приложения будет запрещена. При проверке приложения на совместимость после обновления системы такой случай соответствует полному удалению приложения с устройства. Для иллюстрации того, как этот атрибут может повлиять на приложение после обновления системы, рассмотрим пример.

Приложение декларировало maxSdkVersion="5" в своем манифесте, и было опубликовано на Google Play. Пользователь устройства Android 1.6 (API Level 4) загрузил и установил это приложение. После нескольких недель пользователь принял сообщение от системы over-the-air с предложением обновить систему до уровня Android 2.0 (API Level 5). После установки этого обновления система проверила атрибут приложения maxSdkVersion, и разрешила дальнейшее использование этого приложения. Приложение после этого работало нормально. Однако через некоторое время устройство приняло другое обновление системы Android 2.0.1 (API Level 6). После обновления система не разрешает работу приложения, так как API Level системы (6) теперь выше, чем максимальный уровень, который может поддержать приложение (5). Система делает приложение невидимым для пользователя, и удаляет его из устройства.

Предупреждение: использование этого атрибута не рекомендуется. Во-первых, нет никакой потребности установить этот атрибут как средство блокирования развертывания Вашего приложения на новые версии платформы Android по мере их появления. Для Android декларируется полная обратная совместимость старых приложений для новых версий Android. Ваше приложение должно работать должным образом на всех новых версиях, если оно использует только стандартное API и следует лучшим правилам и практикам разработки. Во-вторых нужно помнить, что применение этого атрибута приведет к автоматическому удалению Вашего приложения с устройств пользователя, которые обновят свою систему на более высокий API Level, чем указано в атрибуте. Большинство устройств, на которых вероятно будет установлено Ваше приложение, получают периодические обновления системы на лету, по воздуху (over the air), так что Вы должны учитывать этот эффект перед тем, как установить этот атрибут для своего приложения.

Будущие версии Android (вне Android 2.0.1) больше не будут проверять maxSdkVersion и принудительно применять его значение при установке или проверке совместимости приложения. Однако Google Play продолжит использовать этот атрибут как фильтр при предоставлении приложений, доступных для закачки пользователям.

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

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

Вы можете задать любую комбинацию, содержаoe. следующие устройства

reqFiveWayNav - используйте значение true, если приложению требуется устройство ввода, поддерживающее навигацию вверх, вниз, влево, вправо, а также нажатие выделенного элемента. К таким устройствам относятся трекболы и D-pad. В принципе устарело
reqHardKeyboard - используйте значение true, если приложению нужна аппаратная клавиатура.
reqKeyboardType - позволяет задать тип клавиатуры: nokeys, qwerty, twelvekey, undefined
reqNavigation - укажите одно из значений: nonav, dpad, trackball, wheel или undefined, если требуется устройство для навигации
reqTouchScreen - если требуется сенсорный экран, то используйте нужное значение из возможных вариантов: notouch, stylus, finger, undefined. Сейчас практически все устройства содержат сенсорный экран, поэтому тоже устарело

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

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

android.hardware.camera.front — требуется аппаратная камера

android.hardware.camera.autofocus — требуется камера с автоматической фокусировкой

Все параметры можно посмотреть в альма-матер .

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

Для пущей наглядности приведу синтакс

Определяет размеры и плотности экранов совместимые с вашим приложением. Только один элемент может присутствовать в файле манифеста, но он может содержать множество элементов . Например:
... ...
Система Андроид не читает этот элемент в файле манифеста, ни во время установки ни во время запуска приложения. Этот элемент носит чисто информационный характер и используется только внешними сервисами такими как Google Play для фильтрации отображения вашего приложения в маркете. То есть если пользователь имеет параметры экрана отличные от указанных в этом элементе, то Google Play просто не покажет ему это приложение.

Как правило, вы не должны использовать этот элемент.

Этот элемент объявляет формат сжатия одной GL текстуры поддерживаемой вашим приложением. Если ваше приложение поддерживает несколько форматов сжатия текстур, то вам необходимо использовать несколько этих элементов. Например:

Все значения можно посмотреть по этой ссылке . На русском языке по этому параметру можно немного почитать .

Элемент имеет гораздо более сложную структуру, чем все перечисленные элементы. Структуру этого элемента я взял из книги Голощапова

Элемент один из основных элементов манифеста, содержащий описание компонентов приложения, доступных в пакете: стили, значок и др. Содержит дочерние элементы, которые объявляют каждый из компонентов, входящих в состав приложения. В манифесте может быть только один элемент .

Дочерний элемент объявляет компонент Activity. Если приложение содержит несколько Активностей, они должны быть объявлены в манифесте, создавая для каждой из них свой элемент . Если Активность не объявлена в манифесте, она не будет видна системе и не будет запущена при выполнении приложения или будет выводиться сообщение об ошибке. Пример объявления Активности:

Эти атрибуты элемента являются обязательными и определяют следующее:

android:name — имя класса. Имя должно включать полное обозначение пакета, но если имя пакета уже определено в корневом элементе , имя класса, реализующего Активность, можно записывать в сокращенном виде, опуская имя пакета.

android:label — текстовая метка, отображаемая пользователю в заголовке Активности.

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

При изменении языка, региона или аппаратной конфигурации Android прерывает работу всех приложений и затем запускает их повторно, перезагружая значения из ресурсов . Подобное поведение не всегда уместно и желательно. Например, некоторые изменения конфигурации (ориентация экрана в пространстве, доступность клавиатуры) могут произойти только лишь из-за того, что пользователь повернул устройство или выдвинул клавиатуру . Вы можете настраивать, каким образом ваше приложение будет реагировать на подобные изменения, обнаруживая их и выполняя собственные действия. Чтобы заставить Активность отслеживать изменения конфигурации при выполнении программы, добавьте в ее узел в манифесте атрибут android:configChanges , указав, какие именно события хотите обрабатывать.

Перечислим некоторые значения, с помощью которых можно описать изменения конфигурации:

оrientation — положение экрана изменено с портретного на альбомное (или наоборот);
keyboardHidden — клавиатура выдвинута или спрятана;
fontScale — пользователь изменил предпочтительный размер шрифта;
locale — пользователь выбрал новые языковые настройки;
keyboard — изменился тип клавиатуры; например, телефон может иметь 12-клавишную панель, при повороте которой появляется полноценная клавиатура;
touchscreen или navigation — изменился тип клавиатуры или способ навигации. Как правило, такие события не встречаются.

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

Наличие атрибута android:configChanges отменяет перезапуск приложения при заданных изменениях конфигурации . Вместо этого внутри Активности срабатывает метод onConfigurationChanged() . Переопределите его, чтобы появилась возможность обрабатывать изменения в конфигурации. Используйте переданный объект Configuration , чтобы получить новые значения. Не забудьте вызвать одноименный метод из родительского класса и перезагрузить измененные значения со всех ресурсов, которые используются внутри Активности.

@Override public void onConfigurationChanged(Configuration _newConfig) { super.onConfigurationChanged(_newConfig); [ ... Обновите пользовательский интерфейс, используя данные из ресурсов... ] if (_newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { [ ... Реакция на измененную ориентацию экрана... ] } if (_newConfig.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO) { [ ... Реакция на выдвигание/задвигание клавиатуры... ] } }
Любые изменения конфигурации, которые не были явно помечены для обработки внутри вашего приложения, приведут к перезапуску Активности, минуя вызов метода onConfigurationChanged .

Элемент поддерживает вложенные узлы . Элемент определяет типы намерений (Intent), на которые могут ответить Activity, Service или Broadcast Receidver. Фильтр намерений (intent-filter) предоставляет для компонентов-клиентов возможность получения намерений (Intent) объявляемого типа, отфильтровывая те, которые не значимы для компонента, и содержит дочерние элементы , , .


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

Это означает, что эта Активность приложения является главной и когда система пришлет Intent для запуска приложения, эта Активность откроется по умолчанию.


Элемент определяет категорию компонента, которую должно обработать намерение. Это строковые константы, определенные в классе intent, например:

Этот атрибут определяет, что это приложение будет добавлено в директорию приложений на Android-устройстве. И будет отображаться в окне запуска приложений Application Launcher мобильного устройства.


Элемент добавляет спецификацию данных к фильтру намерений. Спецификация может быть только типом данных (атрибут mimeType), URI или типом данных вместе с URI. Значение URI определяется отдельными атрибутами для каждой из его частей, т.е. URI делится на части: android:scheme, android:host, android:port, android:path или android:pathPrefix, android:pathPattern.


Элемент определяет пару "имя-значение" для элемента дополнительных произвольных данных, которыми можно снабдить родительский компонент. Составляющий элемент может содержать любое число элементов .


Элемент — это псевдоним для Activity, определенной в атрибуте targetActivity. Целевая Активность должна быть в том же самом приложении, что и псевдоним, и должна быть объявлена перед псевдонимом деятельности в манифесте . Псевдоним представляет целевую деятельность как независимый объект . У псевдонима может быть свой собственный набор фильтров намерений, определяющий, какие намерения могут активизировать целевую Активность и как система будет обрабатывать эту Активность. Например, фильтры намерений на псевдониме Активности могут определить флаги android:name="android.intent.action.MAIN" и android:name="android.intent.category.LAUNCHER", заставляя целевую Активность загружаться при запуске приложения даже в том случае, когда в фильтрах намерений на целевой деятельности эти флаги не установлены.

Элементы , и Объявляют соответственно компоненты Service, Broadcast Receiver и Content Provider. Не забывайте, что компоненты которые не были объявлены не будут обнаружены системой и ни когда не будут запущены. Эти элементы имеют много атрибутов, определяющих имя, доступность, разрешения, процесс и т.д.


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


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


Элемент объявляет контент-провайдера (источник данных) для управления доступом к базам данных. Все контент-провайдеры, которые являются частью приложения, должны быть представлены в элементах В файле манифеста. Если они не объявлены, они не будут работать, т. к. система их не сможет увидеть. Элемент Содержит свой набор дочерних элементов для установления разрешений доступа к данным:
  • ;
  • ;
Этот элемент имеет много атрибутов, определяющих имя, доступность, разрешения, процесс и т. д.


Элемент является дочерним элементом для . Он определяет, для кого можно предоставить разрешения на подмножества данных контент-провайдера. Предоставление разрешения является способом допустить к подмножеству данных, предоставляемым контент-провайдером, клиента, у которого нет разрешения для доступа к полным данным. Если атрибут granturiPermissions контент-провайдера имеет значение true, то разрешение предоставляется для любых данных, поставляемых контент-провайдером. Однако, если атрибут поставлен в false, разрешение можно предоставить только подмножествам данных, которые определены этим элементом. Контент-провайдер может содержать любое число элементов .


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


Элемент определяет общедоступную библиотеку, с которой должно быть скомпоновано приложение. Этот элемент указывает системе на необходимость включения кода библиотеки в загрузчик классов для пакета приложения. Каждый проект связан по умолчанию с библиотеками Android, в которые включены основные пакеты для сборки приложений (с классами общего назначения типа Activity, Service, Intent, View, Button, Application, ContentProvider и т. д.). Однако некоторые пакеты (например, maps и awt) находятся в отдельных библиотеках, которые автоматически не компонуются с приложением. Если же приложение использует пакеты из этих библиотек или других, от сторонних разработчиков, необходимо сделать явное связывание с этими библиотеками и манифест обязательно должен содержать отдельный элемент .

Тут все было описано очень кратко. Более подробно читаем в альма-матер.

Иногда некоторые приложения на 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-.

После заполнения и сохранения нередко выскакивает сообщение «Error while connecting to server». Оно не имеет отношения к Google Play, поэтому смело его игнорируй и ищи интересующие тебя пакеты.

Просмотр и модификация

Допустим, ты нашел интересующий тебя пакет, скачал, распаковал… и при попытке просмотра какого-нибудь XML-файла с удивлением обнаружил, что файл не текстовый. Чем же его декомпилировать и как вообще работать с пакетами? Неужели необходимо ставить SDK? Нет, SDK ставить вовсе не обязательно. На самом деле для всех шагов по распаковке, модификации и упаковке пакетов APK нужны следующие инструменты:

  • архиватор ZIP для распаковки и запаковки;
  • smali - ассемблер/дизассемблер байт-кода виртуальной машины Dalvik (code.google.com/p/smali);
  • aapt - инструмент для запаковки ресурсов (по умолчанию ресурсы хранятся в бинарном виде для оптимизации производительности приложения). Входит в состав Android SDK, но может быть получен и отдельно;
  • signer - инструмент для цифровой подписи модифицированного пакета (bit.ly/Rmrv4M).

Использовать все эти инструменты можно и по отдельности, но это неудобно, поэтому лучше воспользоваться более высокоуровневым софтом, построенным на их основе. Если ты работаешь в Linux или Mac OS X, то тут есть инструмент под названием apktool . Он позволяет распаковывать ресурсы в оригинальный вид (в том числе бинарные XML- и arsc-файлы), пересобирать пакет с измененными ресурсами, но не умеет подписывать пакеты, так что запускать утилиту signer придется вручную. Несмотря на то что утилита написана на Java, ее установка достаточно нестандартна. Сначала следует получить сам jar-файл:

$ cd /tmp $ wget http://bit.ly/WC3OCz $ tar -xjf apktool1.5.1.tar.bz2

$ wget http://bit.ly/WRjEc7 $ tar -xjf apktool-install-linux-r05-ibot.tar.bz2

$ mv apktool.jar ~/bin $ mv apktool-install-linux-r05-ibot/* ~/bin $ export PATH=~/bin:$PATH

Если же ты работаешь в Windows, то для нее есть превосходный инструмент под названиемVirtuous Ten Studio , который также аккумулирует в себе все эти инструменты (включая сам apktool), но вместо CLI-интерфейса предоставляет пользователю интуитивно понятный графический интерфейс, с помощью которого можно выполнять операции по распаковке, дизассемблированию и декомпиляции в несколько кликов. Инструмент этот Donation-ware, то есть иногда появляются окошки с предложением получить лицензию, но это, в конце концов, можно и потерпеть. Описывать его не имеет никакого смысла, потому что разобраться в интерфейсе можно за несколько минут. А вот apktool, вследствие его консольной природы, следует обсудить подробнее.


Рассмотрим опции apktool. Если вкратце, то имеются три основные команды: d (decode), b (build) и if (install framework). Если с первыми двумя командами все понятно, то что делает третья, условный оператор? Она распаковывает указанный UI-фреймворк, который необходим в тех случаях, когда ты препарируешь какой-либо системный пакет.

Рассмотрим наиболее интересные опции первой команды:

  • -s - не дизассемблировать файлы dex;
  • -r - не распаковывать ресурсы;
  • -b - не вставлять отладочную информацию в результаты дизассемблирования файла dex;
  • —frame-path - использовать указанный UI-фреймворк вместо встроенного в apktool. Теперь рассмотрим пару опций для команды b:
  • -f - форсированная сборка без проверки изменений;
  • -a - указываем путь к aapt (средство для сборки APK-архива), если ты по какой-то причине хочешь использовать его из другого источника.

Пользоваться apktool очень просто, для этого достаточно указать одну из команд и путь до APK, например:

$ apktool d mail.apk

После этого в каталоге mail появятся все извлеченные и дизассемблированные файлы пакета.

Препарирование. Отключаем рекламу

Теория - это, конечно, хорошо, но зачем она нужна, если мы не знаем, что делать с распакованным пакетом? Попробуем применить теорию с пользой для себя, а именно модифицируем какую-нибудь софтину так, чтобы она не показывала нам рекламу. Для примера пусть это будет Virtual Torch - виртуальный факел. Для нас эта софтина подойдет идеально, потому что она под завязку набита раздражающей рекламой и к тому же достаточно проста, чтобы не потеряться в дебрях кода.


Итак, с помощью одного из приведенных способов скачай приложение из маркета . Если ты решил использовать Virtuous Ten Studio, просто открой APK-файл в приложении и распакуй его, для чего создай проект (File -> New project), затем в контекстном меню проекта выбери Import File. Если же твой выбор пал на apktool, то достаточно выполнить одну команду:

$ apktool d com.kauf.particle.virtualtorch.apk

После этого в каталоге com.kauf.particle.virtualtorch появится файловое дерево, похожее на описанное в предыдущем разделе, но с дополнительным каталогом smali вместо dex-файлов и файлом apktool.yml. Первый содержит дизассемблированный код исполняемого dex-файла приложения, второй - служебную информацию, необходимую apktool для сборки пакета обратно.

Первое место, куда мы должны заглянуть, - это, конечно же, AndroidManifest.xml. И здесь мы сразу встречаем следующую строку:

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

$ apktool b com.kauf.particle.virtualtorch

В каталоге com.kauf.particle.virtualtorch/build/ появится результирующий APK-файл. Однако установить его не получится, так как он не имеет цифровой подписи и контрольных сумм файлов (в нем просто нет каталога META-INF/). Мы должны подписать пакет с помощью утилиты apk-signer. Запустили. Интерфейс состоит из двух вкладок - на первой (Key Generator) создаем ключи, на второй (APK Signer) подписываем. Чтобы создать наш приватный ключ, заполняем следующие поля:

  • Target File - выходной файл хранилища ключей; в нем обычно хранится одна пара ключей;
  • Password и Confirm - пароль для хранилища;
  • Alias - имя ключа в хранилище;
  • Alias password и Confirm - пароль секретного ключа;
  • Validity - срок действия (в годах). Значение по умолчанию оптимально.

Остальные поля, в общем-то, необязательны - но необходимо заполнить хотя бы одно.


WARNING

Чтобы подписать приложение с помощью apk-signer, ты должен установить Android SDK и указать полный путь до него в настройках приложения.

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

Теперь этим ключом можно подписать APK. На вкладке APK Signer выбираем только что сгенерированный файл, вводим пароль, алиас ключа и пароль к нему, затем находим файл APK и смело жмем кнопку «Sign». Если все пройдет нормально, пакет будет подписан.

INFO

Так как мы подписали пакет нашим собственным ключом, он будет конфликтовать с оригинальным приложением, а это значит, что при попытке обновить софтину через маркет мы получим ошибку.

Цифровая подпись необходима только стороннему софту, поэтому если ты занимаешься модификацией системных приложений, которые устанавливаются копированием в каталог /system/app/, то подписывать их не нужно.

После этого скидываем пакет на смартфон, устанавливаем и запускаем. Вуаля, реклама пропала! Вместо нее, однако, появилось сообщение, что у нас нет интернета или отсутствуют соответствующие разрешения. По идее, этого могло бы и хватить, но сообщение выглядит раздражающе, да и, если честно, нам просто повезло с тупым приложением. Нормально написанная софтина, скорее всего, уточнит свои полномочия или проверит наличие интернет-соединения и в противном случае просто откажется запускаться. Как быть в этом случае? Конечно, править код.

Обычно авторы приложений создают специальные классы для вывода рекламы и вызывают методы этих классов во время запуска приложения или одной из его «активностей» (упрощенно говоря, экранов приложения). Попробуем найти эти классы. Идем в каталог smali, далее com (в org лежит только открытая графическая библиотека cocos2d), далее kauf (именно туда, потому что это имя разработчика и там лежит весь его код) - и вот он, каталог marketing. Внутри находим кучу файлов с расширением smali. Это классы, и наиболее примечателен из них класс Ad.smali, по названию которого нетрудно догадаться, что именно он выводит рекламу.

Мы могли бы изменить логику его работы, но гораздо проще будет тупо убрать вызовы любых его методов из самого приложения. Поэтому выходим из каталога marketing и идем в соседний каталог particle, а затем в virtualtorch. Особого внимания здесь заслуживает файл MainActivity.smali. Это стандартный для Android класс, который создается Android SDK и устанавливается в качестве точки входа в приложение (аналог функции main в Си). Открываем файл на редактирование.

Внутри находится код smali (местный ассемблер). Он довольно запутанный и трудный для чтения в силу своей низкоуровневой природы, поэтому мы не будем его изучать, а просто найдем все упоминания класса Ad в коде и закомментируем их. Вбиваем строку «Ad» в поиске и попадаем на строку 25:

Field private ad:Lcom/kauf/marketing/Ad;

Здесь создается поле ad для хранения объекта класса Ad. Комментируем с помощью установки знака ### перед строкой. Продолжаем поиск. Строка 423:

New-instance v3, Lcom/kauf/marketing/Ad;

Здесь происходит создание объекта. Комментируем. Продолжаем поиск и находим в строках 433, 435, 466, 468, 738, 740, 800 и 802 обращения к методам класса Ad. Комментируем. Вроде все. Сохраняем. Теперь пакет необходимо собрать обратно и проверить его работоспособность и наличие рекламы. Для чистоты эксперимента возвращаем удаленную из AndroidManifest.xml строку, собираем пакет, подписываем и устанавливаем.

Наш подопытный кролик. Видна реклама

Оп-па! Реклама пропала только во время работы приложения, но осталась в главном меню, которое мы видим, когда запускаем софтину. Так, подождите, но ведь точка входа - это класс MainActivity, а реклама пропала во время работы приложения, но осталась в главном меню, значит, точка входа другая? Чтобы выявить истинную точку входа, вновь открываем файл AndroidManifest.xml. И да, в нем есть следующие строки:

Они говорят нам (и, что важнее, андроиду) о том, что активность с именем Start должна быть запущена в ответ на генерацию интента (события) android.intent.action.MAIN из категории android.intent.category.LAUNCHER. Это событие генерируется при тапе на иконку приложения в ланчере, поэтому оно и определяет точку входа, а именно класс Start. Скорее всего, программист сначала написал приложение без главного меню, точкой входа в которое был стандартный класс MainActivity, а затем добавил новое окно (активность), содержащее меню и описанное в классе Start, и вручную сделал его точкой входа.

Открываем файл Start.smali и вновь ищем строку «Ad», находим в строках 153 и 155 упоминание класса FirstAd. Он тоже есть в исходниках и, судя по названию, как раз и отвечает за показ объявлений на главном экране. Смотрим дальше, идет создание экземпляра класса FirstAd и интента, по контексту имеющего отношение к этому экземпляру, а дальше метка cond_10, условный переход на которую осуществляется аккурат перед созданием экземпляра класса:

If-ne p1, v0, :cond_10 .line 74 new-instance v0, Landroid/content/Intent; ... :cond_10

Скорее всего, программа каким-то случайном образом вычисляет, нужно ли показывать рекламу на главном экране, и, если нет, перескакивает сразу на cond_10. Ок, упростим ей задачу и заменим условный переход на безусловный:

#if-ne p1, v0, :cond_10 goto:cond_10

Больше упоминаний FirstAd в коде нет, поэтому закрываем файл и вновь собираем наш виртуальный факел с помощью apktool. Копируем на смартфон, устанавливаем, запускаем. Вуаля, вся реклама исчезла, с чем нас всех и поздравляем.

Итоги

Эта статья лишь краткое введение в методы вскрытия и модификации Android-приложений. За кадром остались многие вопросы, такие как снятие защиты, разбор обфусцированного кода, перевод и замена ресурсов приложения, а также модификация приложений, написанных с использованием Android NDK. Однако, имея базовые знания, разобраться во всем этом - лишь вопрос времени.



© 2024 beasthackerz.ru - Браузеры. Аудио. Жесткий диск. Программы. Локальная сеть. Windows