Дмитрий Мячин
Этим текстом я открою короткий цикл длинных статей о тестировании приложений под Android. Здесь теория, теория, теория, вперемешку с историями «из жизни», которые, конечно, наиболее ценны (для меня).
Все статьи буду идти от очень общего к частностям. Это поможет сначала разобраться с тем, как всё работает, как устроено, как называется, а затем — жонглировать этими теоретическими знаниями. Например в этой, открывающей статье, я сначала расскажу вскользь о компонентах приложений, затем расскажу о них подробно, а затем — добавлю понимания, где можно найти эти компоненты. Так будет построена каждая последующая статья, но, кроме того, каждая последующая будет сильно завязана на каждую предыдущую. Так что если уж решили подтянуть уровень понимания Android и исследовательского тестирования приложений под Android, стоит читать всё.
К чёрту, приступим!
Программный код пишется, в основном, на Java. То есть вы можете писать на чём угодно, хоть на той же Scala, да хоть на Python. Но тут есть свои подводные камни, очевидные и не очевидные. Можно писать и на C, и нативный код будет работать также быстро, как и Java (слова «быстро» и «Java» в одном предложении и даже нет слова «память», спешите видеть!), возможно даже быстрее, но это дороже в скорости разработки и затратах на сопровождение.
Итак, код пишется на Java. Далее Android SDK (Software Development Kit — набор средств для разработки) собирает код и все требуемые файлы ресурсов в файл APK (Android Application Package) — программный пакет Android, который по сути представляет собой zip файл с расширением .apk. То, что это zip, легко убедиться, посмотрев на заголовок, где мы увидим буквы PK:
Ну или «РК» — РосКом и многозначительное многоточие… Кстати, а кто помнит, какие буквы находятся в заголовках exe и dll файлов и что они означают? Это буквы MZ — инициалы Марка Зибовски, бывшего архитектора компании Microsoft, который был одним из создателей MS DOS. Он и разработал этот формат исполняемых файлов, который заменил собой устаревший .com. Пятиминутка бесполезных знаний!
Итак, в apk находится всё, что нужно приложению для работы. Его можно установить на любое устройство под Android, если это не противоречит объявленным программным и аппаратным требованиям (да и то эти ограничения «интересны» в основном самому Play Store и не играют особой роли при локальной установке apk). Здесь нужно ввести некоторые базовые понятия, которые очень нужны будут в будущем, особенно когда речь будет идти об ограничениях возможности приложений:
Android представляет собой, кроме прочего, многопользовательскую систему, где каждое приложение — это отдельный пользователь
Каждому такому пользователю назначается уникальный идентификатор пользователя, который используется только системой и не известен приложению (здесь и по всей статье я подразумеваю, что система не рутована). Всем файлам, которые были в пакете, устанавливаются права доступа таким образом, чтобы доступ к ним имело только это самое приложение. То есть одни пользователи-приложения не имеют доступа к файлам других пользователей-приложений
Каждому приложению выделяется собственная виртуальная машина, внутри которой это приложение и живёт. За пределы виртуальной машины выход строго контролируется и общение между приложениями в основном реализуется через пинки системы, а не прямыми доступами к данным друг друга
По умолчанию каждое приложение запускается в собственном процессе. Когда одному приложению требуется нечто, что предоставляет другое приложение (скажем, клиент ВК запускает фотокамеру, чтобы сделать фото для аватара), то сам Android запускает приложение, компонент которого запрашивается другим приложением. Когда Android решит, что пришло время убивать бездельников, он убьёт процесс приложения, который предоставлял фотокамеру, при условии, что его сейчас никто не использует, а пользователь устройства всё ещё взаимодействует клиентом ВКонтакте.
Всё это нужно для реализации принципа предоставления минимальных прав. То есть каждое приложение живёт только в своём мирке, имеет доступ только к своим файлам, не может получить доступа туда, куда лезть не следует, а для выполнения задач, которые не может выполнить само, просит помощи у других, обычно через систему.
Кроме такого общения через систему («сделайте вот эту задачу вместо меня»), есть и пара других возможностей иметь доступ не только к своим собственным данным.
Двум приложениям можно назначить один индикатор пользователя. И, соответственно, они будут иметь доступ к файлам друг друга, так как, с точки зрения разграничения прав, это один пользователь. Также, в целях экономии ресурсов, эти приложения могут находиться в одной песочнице и использовали одну виртуальную машину. Эти приложения должны быть подписаны одним сертификатом. Часто эту возможность используют, например, для добавления новых возможностей к существующим приложениям (плагины). Хотя это вовсе и не обязательно реализуется именно так
Другим способом общения с внешним миром является обращение к реальным данным там, где это, в целом, дозволено. Это доступ к данным на карте памяти (и распаянной на устройстве, и сменной), прямое обращение к камере, к bluetooth и прочее. Как правило, такие желания нужно объявлять в файле манифеста, в противном случае система просто не даст разрешения на доступ к устройствам и картам памяти.
Компоненты приложений
Выше я уже упомянул про компоненты приложений. Пришло время понять, что это за компоненты, какие они бывают.
Компоненты — это кирпичи, из которого всё приложение и состоит. Компоненты являются точками входа в приложения. Всего компонентов четыре вида, каждый из которых служит своей цели и имеет свой жизненный цикл — по-разному порождаются, по-разному завершаются.
Операции
Если вы произнесёте это слово, говоря про Android приложения, то, скорее всего, вас неправильно поймут другие участники беседы. Чаще всего используется оригинальное название — активити. Так вот активити (activity), они же операции — это, грубо говоря, то, на что смотрит пользователь, даже если он этого не видит того, на что смотрит, потому что эта активити полностью прозрачна. Активити — это экран с пользовательским интерфейсом, точнее даже экран для интерфейса.
То есть у нас есть Hello World с двумя экранами. На одном написано «Hello!» и есть кнопка, а второй появляется по нажатию на кнопку и на нём написано «Ваше устройство зашифровано, давайте ваши денежки». Скорее всего, это будут два разных активити со своим набором элементов интерфейса. Можно даже попытаться из другого приложения вызывать любое из этих активити в любом порядке, используя их как точки входа, если разработчиком приложения это было не запрещено явным образом.
Более реальный пример. Без труда можно вызвать тот активити в «Kaspersky Internet Security для Android», на котором написано, что лицензия добавлена в чёрный список и это никак не повлияет ни на продукт, ни на лицензию. Просто активити — это, как было сказано ранее, точка входа. Вот мы и вошли. Это как избушка на курьих ножках и Иван. У избы была куча разных активити, — четыре стены, крыша, днище. Иван вызывал нужную ему, используя документированную возможность: «к лесу задом, а ко мне — передом». Делал он это, кстати, явным намерением, о котором позже.
Понятное дело, что на одно активити можно забросать сотню кнопок, текстов, полей и скрывать и показывать всё, что нужно в каждый момент времени и тогда это будет одно активити на кучу разных вариантов интерфейсов. Если вы всерьёз рассматриваете такой подход к построению приложения, то я даже не знаю…
Раз уж упомянул про невидимые активити, приведу один из примеров. Если кто не знает, есть такой тип матрицы, который делают в основном в Samsung — AMOLED (Active Matrix Organic Light-Emitting Diode). Ну и куча его разновидностей, которые выходят по три раза в год. Одна и ключевых, одна из важнейших фишек AMOLED в том, что чёрный цвет — это, если всё правильно сделано, это отсутствие свечения. А одна из негативных сторон — эти экраны очень яркие. Ночью они настолько яркие, что даже минимальная яркость в Android всё равно выжигает глаза. Вот для таких случаев (минимальная яркость всё равно слишком велика) сделали приложения, которые показывают свою прозрачную активити поверх всех прочих. Пользователь настраивает затенение прозрачной активити, что воспринимается как ещё большее приглушение яркости, хотя по факту это уменьшение прозрачности. А благодаря другой ошибке, простите, фиче, приложение может пробрасывать тапы, которые пользователь делает по его активити, ниже, туда, куда пользователь реально целился. Называется эта «фича», кстати, Tapjacking. Её обратная сторона — можно снимать, к примеру, пин-коды, регистрируя координаты и последовательности тапов. И да, от этой штатной фичи есть не менее штатная защита.
Продолжение следует…