page.title=Основы создания приложений @jd:body
Приложения для Android пишутся на языке программирования Java. Инструменты Android SDK (Software Development Kit – комплект разработки программного обеспечения) компилируют написанный вами код — и все требуемые файлы данных и ресурсов — в файл APK – программный пакет Android, который представляет собой файл архива с расширением {@code .apk}. В файле APK находится все, что требуется для работы Android-приложения, и он позволяет установить приложение на любом устройстве под управлением системы Android.
Каждое приложение Android, установленное на устройстве, работает в собственной "песочнице" (изолированной программной среде):
Таким образом система Android реализует принцип предоставления минимальных прав. То есть каждое приложение по умолчанию имеет доступ только к тем компонентам, которые ему необходимы для работы, и ни к каким другим. Благодаря этому формируется исключительно безопасная среда, в которой приложение не имеет доступа к недозволенным областям системы.
Однако у приложения есть варианты предоставления своих данных другим приложениям и доступа к системным службам:
Это основные сведения о том, каким образом приложение Android существует в системе. В остальной части этого документа раскрываются следующие темы:
Компоненты приложения являются кирпичиками, из которых состоит приложение для Android. Каждый компонент представляет собой отдельную точку, через которую система может войти в приложение. Не все компоненты являются точками входа для пользователя, а некоторые из них зависят друг от друга. При этом каждый компонент является самостоятельной структурной единицей и играет определенную роль — каждый из них представляет собой уникальный элемент структуры, который определяет работу приложения в целом.
Компоненты приложения можно отнести к одному из четырех типов. Компоненты каждого типа предназначены для определенной цели, они имеют собственный жизненный цикл, который определяет способ создания и прекращения существования компонента.
Четыре типа компонентов:
Операция относится к подклассу класса {@link android.app.Activity}. Подробные сведения об этом можно найти в руководстве для разработчиков в статье Операции .
Служба относится к подклассу класса {@link android.app.Service}. Подробные сведения об этом можно найти в руководстве для разработчиков в статье Службы .
Поставщики контента также используются для чтения и записи данных, доступ к которым внешним компонентам приложение не предоставляет. Например, в образце приложения Note Pad с помощью поставщика контента выполняется сохранение заметок.
Поставщик контента относится к подклассу класса {@link android.content.ContentProvider}. Он должен реализовывать стандартный набор API-интерфейсов, с помощью которых другие приложения будут выполнять транзакции. Подробные сведения можно найти в руководстве для разработчиков в статье Поставщики контента .
Приемник широковещательных сообщений относится к подклассу класса {@link android.content.BroadcastReceiver} , а каждое такое сообщение предоставляется как объект {@link android.content.Intent}. Подробные сведения изложены в руководстве, посвященном классу {@link android.content.BroadcastReceiver}.
Уникальной особенностью системы Android является то, что любое приложение может запустить компонент другого приложения. Например, если вы хотите дать пользователю возможность фотографировать, используя камеру устройства, то, поскольку наверняка имеется другое приложение, которое может выполнить это действие, вместо того чтобы разработать операцию фотографирования в своем приложении, вы можете вызвать такое приложение. Вам не нужно внедрять код из приложения для камеры или даже устанавливать на него ссылку. Вместо этого вы можете просто запустить операцию фотографирования из приложения для камеры. По завершении этой операции фотография будет возвращена в ваше приложение, и ее можно будет использовать. Для пользователя это будет выглядеть как одно приложение.
Когда система запускает компонент, она запускает процесс для этого приложения (если он еще не был запущен) и создает экземпляры классов, которые требуются этому компоненту. Например, если ваше приложение запустит операцию фотографирования в приложении для камеры, эта операция будет выполняться в процессе, который относится к этому стороннему приложению, а не в процессе вашего приложения. Поэтому, в отличие от приложений для большинства других систем, в приложениях для Android отсутствует единая точка входа (например, в них нет функции {@code main()}).
Поскольку система выполняет каждое приложение в отдельном процессе с такими правами доступа к файлам, которые ограничивают доступ в другие приложения, ваше приложение не может напрямую вызвать компонент из другого приложения. Это может сделать сама система Android. Поэтому, чтобы вызвать компонент в другом приложении, необходимо сообщить системе о своем намерении (Intent) запустить определенный компонент. После этого система активирует для вас этот компонент.
Компоненты трех из четырех возможных типов — операции, службы и приемники широковещательных сообщений — активируются асинхронным сообщением, которое называется Intent (намерение). Объекты Intent связывают друг с другом отдельные компоненты во время выполнения, будь то это компоненты вашего или стороннего приложения (эти объекты Intent можно представить себе в виде мессенджеров, которые посылают другим компонентам запрос на выполнение действий).
Объект Intent создается с помощью объекта {@link android.content.Intent}, который описывает запрос на активацию либо конкретного компонента, либо компонента конкретного типа — соответственно, намерение Intent может быть явным или неявным.
Для операций и служб Объект Intent определяет действие, которое требуется выполнить (например, просмотреть (view) или отправить (send) что-то), а также может указывать URI (Uniform Resource Identifier – унифицированный идентификатор ресурса) данных, с которыми это действие нужно выполнить (помимо прочих сведений, которые нужно знать запускаемому компоненту). Например, объект Intent может передавать запрос на выполнение операции "показать изображение" или "открыть веб-страницу". В некоторых ситуациях операцию можно запустить, чтобы получить результат. В этом случае операция возвращает результат также в виде объекта {@link android.content.Intent} (например, можно отправить сообщение Intent, чтобы дать пользователю возможность выбрать контакт и вернуть его вам — в ответном сообщении Intent будет содержаться URI, указывающий на выбранный контакт).
Для приемников широковещательных сообщений Intent просто определяет передаваемое объявление (например, широковещательное сообщение о низком уровне заряда аккумулятора содержит только строку "аккумулятор разряжен").
Компоненты четвертого типа – поставщики контента – сообщениями Intent не активируются. Они активируются по запросу от {@link android.content.ContentResolver}. Процедура определения контента (content resolver) обрабатывает все прямые транзакции с поставщиком контента, с тем чтобы этого не пришлось делать компоненту, который выполняет транзакции с поставщиком. Вместо этого он вызывает методы для объекта {@link android.content.ContentResolver}. Это формирует слой, абстрагирующий (в целях безопасности) поставщика контента от компонента, запрашивающего информацию.
Для активации компонентов каждого типа имеются отдельные методы:
Подробные сведения об использовании объектов Intent приведены в документе Объекты Intent и фильтры объектов Intent. Более подробная информация об активации определенных компонентов также приведена в следующих документах: Операции, Службы, {@link android.content.BroadcastReceiver} и Поставщики контента.
Для запуска компонента приложения системе Android необходимо знать, что компонент существует. Для этого она читает файл {@code AndroidManifest.xml} приложения (файл манифеста). В этом файле, который должен находиться в корневой папке приложения, должны быть объявлены все компоненты приложения.
Помимо объявления компонентов приложения, манифест служит и для других целей, среди которых:
Основная задача манифеста – это информировать систему о компонентах приложения. Например, файл манифеста может объявлять операцию следующим образом:
<?xml version="1.0" encoding="utf-8"?> <manifest ... > <application android:icon="@drawable/app_icon.png" ... > <activity android:name="com.example.project.ExampleActivity" android:label="@string/example_label" ... > </activity> ... </application> </manifest>
Атрибут {@code android:icon} в элементе <application>
указывает на ресурсы для значка, который обозначает
приложение.
Атрибут {@code android:name} в элементе <activity>
указывает полное имя класса подкласса {@link
android.app.Activity}, а атрибут {@code android:label} указывает строку,
которую необходимо использовать в качестве метки операции, отображаемой для пользователя.
Все компоненты приложения необходимо объявлять следующим образом:
<activity>
для операций;<service>
для служб;<receiver>
для приемников широковещательных сообщений;<provider>
для поставщиков контентаСистеме не видны операции, службы и поставщики контента, которые имеются в исходном коде, но не объявлены в манифесте, поэтому они не могут быть запущены. А вот приемники широковещательных сообщений можно либо объявить в манифесте, либо создать динамически в коде (как объекты {@link android.content.BroadcastReceiver}) и зарегистрировать в системе путем вызова {@link android.content.Context#registerReceiver registerReceiver()}.
Подробные сведения о структуризации файла манифеста для приложения см. в документе Файл AndroidManifest.xml .
Как уже говорилось в разделе Активация компонентов, с помощью объекта {@link android.content.Intent} можно запускать операции, службы и приемники широковещательных сообщений. Для этого в объекте Intent следует явно указать имя целевого компонента (с помощью имени класса компонента). Однако в полной мере возможности объектов Intent раскрываются при использовании концепции неявных Intent. В неявном сообщении Intent просто описывается тип действия, которое требуется выполнить (а также, хотя это и не обязательно, дата, в которую вы бы хотели выполнить это действие). Системе же предоставляется возможности найти на устройстве компонент, который может выполнить это действие, и запустить его. При наличии нескольких компонентов, которые могут выполнить действие, описанное в сообщении Intent, пользователь выбирает, какой из них будет использоваться.
Система определяет компоненты, которые могут ответить на сообщение Intent, путем сравнения полученного сообщения Intent с фильтрами объектов Intent, указанными в файле манифеста других приложений, имеющихся на устройстве.
При объявлении операции в манифесте своего приложения по желанию можно указать фильтры объектов Intent, которые указывают возможности операции, с тем чтобы она могла реагировать на сообщения Intent от других приложений. Чтобы объявить фильтр Intent для своего компонента, необходимо добавить элемент {@code <intent-filter>} в качестве дочернего для элемента объявления компонента.
Например, если вы создали приложение для работы с электронной почтой с операцией составления нового сообщения, вы можете объявить фильтр для ответа на сообщения Intent типа "send" (для отправки нового сообщения электронной почты) следующим образом:
<manifest ... > ... <application ... > <activity android:name="com.example.project.ComposeEmailActivity"> <intent-filter> <action android:name="android.intent.action.SEND" /> <data android:type="*/*" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> </application> </manifest>
Затем, если другое приложение создаст объект Intent с действием {@link android.content.Intent#ACTION_SEND} и передаст его в {@link android.app.Activity#startActivity startActivity()}, система сможет запустить вашу операцию, дав пользователю возможность написать и отправить сообщение электронной почты.
Подробные сведения о создании фильтров объектов Intent приведены в документе Объекты Intent и фильтры объектов Intent.
Существует огромное количество устройств, работающих под управлением Android, и не все они имеют одинаковые функциональные возможности. Чтобы ваше приложение не могло быть установлено на устройствах, в которых отсутствуют функции, необходимые приложению, важно четко определить профиль для типов устройств, поддерживаемых вашим приложением, указав требования к аппаратному и программному обеспечению в файле манифеста. Эти объявления по большей части носят информационный характер, система их не читает. Однако их читают внешние службы, например Google Play, с целью обеспечения фильтрации для пользователей, которые ищут приложения для своих устройств.
Например, если вашему приложению требуется камера и оно использует API-интерфейсы из Android 2.1 (уровень API 7), эти параметры следует объявить в файле манифеста в качестве требований следующим образом:
<manifest ... > <uses-feature android:name="android.hardware.camera.any" android:required="true" /> <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="19" /> ... </manifest>
Теперь ваше приложение нельзя будет установить из Google Play на устройствах, в которых нет камеры, а также на устройствах, работающих под управлением Android версии ниже 2.1.
Однако можно также объявить, что приложение использует камеру, но для его работы она не является непременно необходимой. В этом случае в приложении атрибуту {@code required} необходимо задать значение {@code "false"}, а во время работы оно должно проверять, имеется ли на устройстве камера, и при необходимости отключать свои функции, которые используют камеру.
Более подробные сведения об управлении совместимостью своего приложения с различными устройствами приведены в документе Совместимость устройств .
Приложение Android состоит не только из кода — ему необходимы такие существующие отдельно от исходного кода ресурсы, как изображения, аудиофайлы и все, что связано с визуальным представлением приложения. Например, необходимо определять анимацию, меню, стили, цвета и макет пользовательских интерфейсов операций в файлах XML. Используя ресурсы приложения, можно без труда изменять его различные характеристики, не меняя код, а, кроме того, —путем предоставления наборов альтернативных ресурсов — можно оптимизировать свое приложение для работы с различными конфигурациями устройств (например, для различных языков или размеров экрана).
Для каждого ресурса, включаемого в проект Android, инструменты SDK задают уникальный целочисленный идентификатор, который может использоваться, чтобы сослаться на ресурс из кода приложения или из других ресурсов, определенных в XML. Например, если в вашем приложении имеется файл изображения с именем {@code logo.png} (сохраненный в папке {@code res/drawable/}), инструменты SDK сформируют идентификатор ресурса под именем {@code R.drawable.logo}, с помощью которого на изображение можно будет ссылаться и вставлять его в пользовательский интерфейс.
Один из наиболее важных аспектов предоставления ресурсов отдельно от исходного кода заключается в возможности использовать альтернативные ресурсы для различных конфигураций устройств. Например, определив строки пользовательского интерфейса в XML, вы сможете перевести их на другие языки и сохранить эти переводы в отдельных файлах. Затем по квалификатору языка , добавленному к имени каталога ресурса (скажем {@code res/values-fr/} для строк на французском языке), и выбранному пользователем языку система Android применит к вашему пользовательскому интерфейсу строки на соответствующем языке.
Android поддерживает разные квалификаторы для соответствующих ресурсов. Квалификатор представляет собой короткую строку, которая включается в имена каталогов ресурсов с целью определения конфигурации устройства, для которой эти ресурсы следует использовать. В качестве другого примера можно сказать, что для своих операций следует создавать разные макеты, которые будут соответствовать размеру и ориентации экрана устройства. Например, когда экран устройства имеет книжную ориентацию (расположен вертикально), кнопки в макете можно также размещатьь по вертикали, а когда экран развернут горизонтально (альбомная ориентация), кнопки следует размещать по горизонтали. Чтобы при изменении ориентации экрана изменялся макет, можно определить два разных макета и применить соответствующий квалификатор к имени каталога каждого макета. После этого система будет автоматически применять соответствующий макет в зависимости от ориентации устройства.
Подробные сведения о различных видах ресурсов, которые можно включить в приложение, а также о том, как создавать альтернативные ресурсы для разных конфигурацией устройств, см. в разделе Предоставление ресурсов.