среда, 30 марта 2011 г.

Введение в систему Android

* Приложения для Android состоят из одного или нескольких компонентов: Activities (Деятельности), Services (Службы), Content Providers (Поставщики данных), а также Broadcast Receivers (Получатели широковещательных сообщений).

* Каждый компонент выполняет свою роль в приложении и может быть активирован отдельно от других (причём активирован может быть даже сторонним приложением).

* В AndroidManifest.xml (файл манифеста) должны быть объявлены все компоненты приложения и системные требования, такие как необходимая минимальная версия Android или определённая аппаратная конфигурация.

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


Данный текст является переводом (хотя и немного вольным) статьи из официальной документации по Android.

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


Основы
Android-приложения написаны на языке программирования Java. Инструмент Android SDK (Software Development Kit — комплект разработки программного обеспечения) компилирует код вместе со всеми данными и файлами ресурсов в пакет Android - архивный файл с расширением .apk. Этот файл позволяет установить приложение на любом устройстве под управлением системы Android.

После установки на устройстве, каждое приложение живёт в своей собственной изолированной программной среде:
  • Операционная система Android является многопользовательской Linux-системой, в которой каждое приложение это отдельный пользователь.
  • По умолчанию, система присваивает каждому приложению уникальный идентификатор пользователя userid (который используется только системой). Система устанавливает разрешения для всех файлов приложения таким образом, чтобы только определённый пользователь (с определённым userid) мог получить к ним доступ.
  • Каждый процесс имеет свою собственную виртуальную машину, так что код приложения запускается изолированно от других приложений.
  • По умолчанию каждое приложение выполняется в отдельном процессе Linux. Android начинает процесс, когда одному из компонентов приложения необходимо запуститься, а затем завершает процесс, когда он больше не нужен или когда системе требуется память для других приложений.

Таким образом, система Android реализует принцип наименьших привилегий. То есть, каждое приложение по умолчанию имеет доступ только к компонентам, которые необходимы для его работы и не более того. Однако, существуют способы обмена данными между приложениями и получения доступа к системным сервисам:
  • Возможно раздать двум приложениям одинаковые идентификаторы пользователей (userid), в этом случае они могут получить доступ к файлам друг друга. Для экономии системных ресурсов приложения с тем же идентификатором также могут быть запущены в одном процессе и использовать одну виртуальную машину. Такие приложения должны быть подписаны на один и тот же сертификат.
  • Приложение может запросить разрешение на доступ к системным данным, таким как контакты пользователя, SMS сообщения, карточка хранения (SD), камера, Bluetooth и многое другое. Все запросы доступа должны быть разрешены пользователем во время установки.

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

Существуют четыре типа компонентов приложения. Каждый из них служит различным целям и имеет свой жизненный цикл, который определяет, как компонент создаётся и уничтожается.

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

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

Content provider (Поставщик данных)
Content provider управляет данными приложения. Данные можно хранить в файловой системе, базе данных SQLite, в Интернете или любом другом доступном для приложения месте хранения. Через Content providers другие приложения могут запрашивать или даже изменить данные (если на это есть права доступа). Например, в операционной системе Android существует Content provider, который управляет списком контактов пользователя. Таким образом, любое приложение, с соответствующими разрешениями могут запрашивать информацию о конкретном человеке для чтения или записи. Content provider также можно использовать для чтения и записи данных, которые доступны только для одного приложения.

Broadcast receivers (Получатель широковещательных сообщений)
Broadcast receiver - компонент, который позволяет принимать широковещательные сообщения операционной системы. Такими сообщениями являются, например, объявления о том, что экран выключился, батарея разряжена или был сделан фотоснимок. Такие сообщения также могут посылаться пользовательскими приложениями, например, уведомления о том, что некоторые данные были загружены и готовы к использованию. Хотя Broadcast receiver не имеют пользовательского интерфейса, он может создавать уведомления в строке состояния. Однако, чаще всего Broadcast receiver это просто "шлюз" для других компонентов, например, он может запускать Service для обработки определённых событий.

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

Для запуска любого компонента операционная система начинает новый процесс (если его ещё не было) и инициализирует классы, необходимые для компонента. Например, если в вашем приложении запускается Activity для работы с камеры (принадлежащая стороннему приложению), то она запускается в отдельном процессе, который принадлежит этому стороннему приложению, а не в процессе вашего приложения. Поэтому, в отличие от приложений на большинство других систем, приложений Android не имеют единую точку входа (нет функции main()).

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

Активация компонентов
Три из четырёх типов компонентов — Activity (деятельность), Service (сервис), а также Broadcast receivers (получатель широковещательных сообщений) — активируются с помощью асинхронного сообщения Intent (намерение). Intent связывает отдельные компоненты друг с другом во время выполнения, будь то компонент принадлежащий вашему приложению или другой.

Intent (намерение) создаётся с помощью класса Intent, который описывает запрос на активацию конкретного компонента или конкретного типа компонента, соответственно Intent может быть явным или неявным.

Для Activity и Service, Intent(намерение) определяет действие, которое надо выполнить (например, "Просмотреть" или "Отправить" что-то), и может указать URI (Uniform Resource Identifier — унифицированный идентификатор ресурса) данных необходимых для выполнения. Например, Intent может передать запрос Activity показать изображение или открыть веб-страницу.
Для broadcast receivers Intent просто определяет транслируемые сообщения (например, широковещательное сообщения о том, что аккумулятор разряжен содержит только строковую константу обозначающую "батарея разряжена").
Последний компонент - Content provider не активируется с помощью Intent. Хотя он и может вызывается, если Content provider запрашивает данные из ContentResolver.

Методы для активации каждого типа компонентов:
  • Для запуска Activity используются методы startActivity(Intent intent) или startActivityForResult(Intent intent) (если необходимо вернуть результат).
  • Для запуска Service вызывается метод startService (Intent service).
  • Для запуска Broadcast reciever — sendBroadcast(Intent intent), sendOrderedBroadcast(Intent intent, String receiverPermission), или sendStickyBroadcast(Intent intent).
  • Для формирования запроса для Content Provider используется метод query ()

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

Кроме этого манифест-файл выполняет другие функции:
  • Определяет пользовательские разрешения, такие как доступ в Интернет или чтение контактов.
  • Объявление минимального API уровня (версии Android), необходимого для приложения.
  • Объявление аппаратных и программных требований, такие как камера, Bluetooth, или мультитач экран.
  • API библиотек с которыми приложение будет связываться, например библиотеки Google Maps.

Но все же основная задача манифеста сообщить системе о компонентах приложения. Например, можно объявить Activity (деятельность) следующим образом:
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest ... >  
  3.     <application android:icon="@drawable/app_icon.png" ... >  
  4.         <activity android:name="com.example.project.ExampleActivity"  
  5.             android:label="@string/example_label" ... >  
  6.         </activity>  
  7.         ...  
  8.     </application>  
  9. </manifest>  

В элементе <application> атрибут Android:icon указывает на ресурсы для иконки приложения.

В элементе <activity> атрибут Android:name определяет полный путь на имя класса Activity (деятельности), а атрибут Android:label задаёт заголовок приложения.

Для определения компонентов используются:
<activity> для Activity (деятельности)
<service> для Service (сервисы)
<receiver> для Broadcast reciever (получатели широковещательных сообщений)
<provider> для Content providers (поставщики данных)

Activity (деятельность), Service (сервис) и Content provider (поставщики данных), которые существуют в исходниках, но не заявлены в манифесте не видны системе и, следовательно, не смогут запуститься. Однако, Broadcast provider (получатель широковещательных сообщений) может создаваться динамически в коде (как объекты BroadcastReceiver) и регистрироваться с помощью вызова registerReceiver ().

Объявление возможностей компонента
Как уже говорилось в разделе «Активация компонентов», для вызова Activity (деятельность), Service (сервис) и Broadcast receiver (получатель широковещательных сообщений) можно использовать класс Intent. Сделать это можно явно, задав конкретное имя компонента, или не явно, а этом случае описывается только тип действия, который нужно выполнить (и, возможно, данные, необходимые для него). Система сама находит компонент устройства, который может выполнить действия и запускает его. Если найдено несколько подходящих компонентов, то пользователь выбирает, какой из них использовать.

Система определяет компоненты, которые могут реагировать на намерение путём сравнения полученного Intent (намерения), с Intent filters (фильтр намерений), определённых в файлах манифеста других приложений.

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

Например, приложение электронной почты с Activity (деятельностью) для создания новых сообщений может объявить Intent filter (фильтр намерения) в своём файле манифеста запускаться на запрос "send" (отправить). Activity (деятельность) в стороннем приложении создаёт Intent (намерение) с типом действия "send" (ACTION_SEND), которое система сопоставит с приложением электронной почты и запустит нужную Activity (деятельность).

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

Например, если приложение требует камеру и использует API, введённые в Android версии 2.1 (API уровень 7), надо записать эти требования в файл манифеста. Таким образом, устройства, которые не имеют камеру или с версией Android ниже, чем 2.1 не смогут установить приложение из Android Market.

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

При проектировании и разработке приложения, необходимо учитывать:

Размер экрана и плотность
Android определяет две характеристики экрана для устройства: размер экрана (физические размеры экрана) и плотность (плотность пикселей на экране, или dpi (dots per inch - точек на дюйм). Для упрощения Android обобщает их в отдельных группы

Размер: small (маленький), normal (средний), large (большой), and extra large (очень большой).
Плотность: low density (низкая), medium density (средняя), high density (высокая), and extra high density (очень высокая).

По умолчанию, приложение совместимо со всеми размерами экрана, так как система Android делает необходимые изменения пользовательского интерфейса и изображений. Однако, лучше создать специализированные макеты и изображения для определённых размеров и плотностей и объявить в манифесте, какие именно размеры экрана приложение поддерживает в элементе <supports-screens>.

Средства ввода
Устройства могут иметь различные средства для ввода, такие как аппаратная клавиатура, трекбол или джойстик. Если приложение требует определённое оборудование для ввода, то необходимо объявить это в манифесте в элементе <uses-configuration>. Однако, в большинстве случаев приложения поддерживают любое средство ввода.

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

Версия платформы
Устройства работают на разных версиях платформы Android. Каждая последующая версия часто включает в себя дополнительные интерфейсы API, которые не доступны в предыдущей версии. Для того, чтобы указать, какой набор API-интерфейсов доступен, каждой версии платформы соответствует API уровень (например, Android 1.0 — 1 уровень API, Android 2.3 — 9 уровень). Если в приложении используются API, которые были добавлены к платформе после определённой версии, необходимо объявить минимальный уровень API с помощью элемента <uses-sdk>.

Ресурсы приложения
Приложения Android состоят не только из исходного кода, но также из ресурсов для визуального представления, такие как изображения или звуковые файлы. Для приложения необходимо определить меню, стили, цвета и разметку пользовательского интерфейса в файлах XML. Использование ресурсов даёт возможность изменять некоторые части приложения без модификации исходного кода, а также позволяет оптимизировать приложение для различных устройств (с различным языком интерфейса или размером экрана).

Для каждого ресурса, включённого в проект Android, SDK определяет уникальный идентификатор (целое число), которое можно использовать для ссылки на ресурс из кода или из других ресурсов определённых в XML. Например, если приложение содержит изображение с именем logo.png (сохранённое в директории res/drawable), SDK сгенерирует идентификатор ресурса R.drawable.logo, которое можно использовать для ссылки на изображение.

Главным достоинством отдельного хранения исходного кода и ресурсов является возможность создать разные ресурсы для разных аппаратных конфигураций. Например, строки интерфейса для разных языков можно определять в различных xml файлах (они хранятся например в директории res/values-fr/ для французского языка). В зависимости от выбранного пользователем языка система Android подставляет нужные строки в интерфейс.

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

Комментариев нет:

Отправить комментарий