Глава 2. Android и MVC Настройка устройства для разработки Чтобы вы могли тестировать приложения на своем устройстве, необходимо на- строить его и разрешить установку приложений не из Google Play. На устройствах с Android 4.1 или ранее откройте меню Settings устройства и перейдите в раздел Applications . Убедитесь в том, что флажок Unknown sources установлен. На устройствах с Android 4.2 перейдите в раздел Settings Security и найдите флажок Unknown sources Также необходимо разрешить для устройства отладку USB. На устройствах с версиями Android до 4.0 откройте меню Settings Applications Development и найдите флажок USB debugging На устройствах с Android 4.0 или 4.1 откройте меню Settings Developer options В Android 4.2 флажок Developer options по умолчанию не отображается. Чтобы включить его, откройте меню Settings About Tablet/Phone и нажмите Build Number 7 раз. После этого вернитесь в меню Settings , найдите раздел Developer options и установите флажок USB debugging Как видите, настройки серьезно различаются между устройствами. Если у вас возникнут проблемы с включением отладки на вашем устройстве, обратитесь за помощью по адресу https://developer.android.com/tools/device.html. Запустите GeoQuiz так, как это делалось ранее. Eclipse предлагает выбор между запуском на виртуальном устройстве и физическом устройстве, подключенном к системе. Выберите физическое устройство; GeoQuiz запускается на выбранном устройстве. (Если вам не предлагается выбрать устройство, а GeoQuiz запускается в эмуляторе, проверьте описанную ранее процедуру и убедитесь в том, что устрой- ство подключено.) Добавление значка Приложение GeoQuiz работает, но пользовательский интерфейс смотрелся бы бо- лее привлекательно, если бы на кнопке Next была изображена стрелка, обращенная направо. Изображение такой стрелки можно найти в файле решений этой книги (https://www. bignerdranch.com/solutions/AndroidProgramming.zip ). Файл решений представляет собой набор проектов Eclipse — по одному для каждой главы. Загрузите файл и откройте каталог 02_MVC/GeoQuiz/res . Найдите в нем подкаталоги drawable-hdpi , res/drawable-mdpi и drawable-xhdpi Суффиксы имен каталогов обозначают экранную плотность пикселов устройства. mdpi Средняя плотность (
160 dpi) hdpi Высокая плотность (
240 dpi) xhdpi Сверхвысокая плотность (
320 dpi)
Добавление ресурсов в проект 65 (Также существует категория устройств низкой плотности ldpi , но устройства с такими экранами сейчас уже почти не встречаются.) Каждый каталог содержит два графических файла — arrow_right.png и arrow_left.png Эти файлы адаптированы для плотности пикселов, указанной в имени каталога. В полноценных приложениях важно включить в проект графику для разных плот- ностей пикселов, поскольку это приводит к сокращению артефактов от масштабиро- вания изображений. Вся графика в проекте устанавливается с приложением, а ОС выбирает наиболее подходящий вариант для конкретного устройства. Добавление ресурсов в проект Следующим шагом станет включение графических файлов в ресурсы приложения GeoQuiz. На панели Package Explorer откройте содержимое каталога res и найдите три подка- талога, имена которых соответствуют именам из файла решений. Скопируйте файлы из каждого каталога в соответствующий каталог Package Explorer Рис. 2.7. Изображения стрелок в каталогах drawable проекта GeoQuiz Если вы будете перетаскивать файлы мышью, на экране появляется окно, изобра- женное на рис. 2.8. Установите переключатель Copy Files , чтобы копировать файлы вместо создания ссылок на них.
66 Глава 2. Android и MVC Рис. 2.8. Копирование файлов (вместо создания ссылок) Процесс включения графики в приложение чрезвычайно прост. Любому файлу .png , .jpg или .gif , добавленному в папку res/drawable , автоматически назначается иден- тификатор ресурса. (Учтите, что имена файлов должны быть записаны в нижнем регистре и не могут содержать пробелов.) После того, как файлы будут скопированы, откройте файл gen/R.java и найдите новые идентификаторы ресурсов во внутреннем классе R.drawable . Таких идентификато- ров всего два: R.drawable.arrow_left и R.drawable.arrow_right Эти идентификаторы ресурсов не уточняются плотностью пикселов, так что вам не нужно определять плотность пикселов экрана во время выполнения; просто ис- пользуйте идентификатор ресурса в коде. При запуске приложения ОС определит изображение, подходящее для конкретного устройства. Система ресурсов Android более подробно рассматривается в главе 3 и далее. А пока давайте заставим работать нашу стрелку. Ссылки на ресурсы в XML Для ссылок на ресурсы в коде используются идентификаторы ресурсов. Но мы хо- тим настроить кнопку Next так, чтобы в определении макета отображалась стрелка. Как включить ссылку на ресурс в разметку XML? Да почти так же, только с немного измененным синтаксисом. Откройте файл activity_quiz.xml и добавьте два атрибута в определение виджета Button Листинг 2.12. Включение графики в кнопку Next (activity_quiz.xml) ... > ... >
В ресурсах XML вы ссылаетесь на другой ресурс по его типу и имени. Ссылка на строку начинается с префикса @string/ . Ссылка на графический ресурс начинается с префикса @drawable/ Имена ресурсов и структура каталогов res более подробно рассматриваются, на- чиная с главы 3. Запустите приложение GeoQuiz и насладитесь новым внешним видом кнопки. Протестируйте ее и убедитесь, что кнопка работает точно так же, как прежде. Впрочем, в программе GeoQuiz скрывается ошибка. Во время выполнения GeoQuiz нажмите кнопку Next , чтобы перейти к следующему вопросу, а затем поверните устройство. (Если программа выполняется в эмуляторе, нажмите Control+F12 / Ctrl+F12 .) После поворота мы снова видим первый вопрос. Почему это произошло и как ис- править ошибку? Ответы на эти вопросы связаны с жизненным циклом активности — этой теме по- священа глава 3. Упражнения Упражнения в конце главы предназначены для самостоятельной работы. Некото- рые из них просты и рассчитаны на повторение того, что уже делалось в материале главы. Другие, более сложные упражнения потребуют логического мышления и навыков решения задач. Трудно переоценить важность упражнений. Они закрепляют усвоенный материал, повышают уверенность в обретенных навыках и сокращают разрыв между изуче- нием программирования Android и умением самостоятельно писать программы для Android. Если у вас возникнут затруднения с каким-либо упражнением, сделайте перерыв, потом вернитесь и попробуйте еще раз. Если и эта попытка окажется безуспешной, обратитесь на форум книги forums.bignerdranch.com . Здесь вы сможете просмо- треть вопросы и решения, полученные от других читателей, а также опубликовать свои вопросы и решения. Чтобы избежать случайного повреждения текущего проекта, мы рекомендуем создать копию в Eclipse и практиковаться на ней. Щелкните правой кнопкой мыши на проекте в Package Explorer , выберите команду Copy , затем снова щелкните правой кнопкой мыши и вставьте скопированный проект.
68 Глава 2. Android и MVC Вам будет предложено ввести имя нового проекта, который появляется на панели Package Explorer готовым к работе. Упражнение. Добавление слушателя для TextView Кнопка Next удобна, но было бы неплохо сделать так, чтобы пользователь мог перей- ти к следующему вопросу простым нажатием на виджете TextView Подсказка. Для TextView можно использовать слушателя View.OnClickListener , который использовался с Button , потому что класс TextView также является про- изводным от View Упражнение. Добавление кнопки возврата Добавьте кнопку для возвращения к предыдущему вопросу. Пользовательский интерфейс должен выглядеть примерно так, как показано на рис. 2.9. Рис. 2.9. Теперь с кнопкой возврата! Это очень полезное упражнение. В нем вам придется вспомнить многое из того, о чем говорилось в двух последних главах. Упражнение. От Button к ImageButton Возможно, пользовательский интерфейс будет смотреться еще лучше, если на кнопках будут отображаться только значки.
Упражнения 69 Рис. 2.10. Кнопки только со значками Для этого оба виджета должны относиться к типу ImageButton (вместо обычного Button ). Виджет ImageButton является производным от ImageView — в отличие от виджета Button , производного от TextView наследование наследование наследование наследование Рис. 2.11. Диаграмма наследования ImageButton и Button Атрибуты text и drawable кнопки Next можно заменить одним атрибутом ImageView :
70 Глава 2. Android и MVC android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/next_question_button" android:drawableRight="@drawable/arrow_right" android:drawablePadding="4dp" android:src="@drawable/arrow_right" /> Конечно, вам также придется внести изменения в QuizActivity , чтобы этот класс работал с ImageButton После того как вы замените кнопки кнопками ImageButton , Eclipse выдаст пред- упреждение об отсутствии атрибута android:contentDescription . Этот атрибут обеспечивает доступность контента для читателей с ослабленным зрением. Строка, заданная этому атрибуту, читается экранным диктором (при включении соответ- ствующих настроек в системе пользователя). Наконец, добавьте атрибут android:contentDescription в каждый элемент Image- Button
Жизненный цикл Activity У каждого экземпляра Activity имеется жизненный цикл. Во время этого жизнен- ного цикла активность переходит между тремя возможными состояниями: выпол- нение, приостановка и остановка. Для каждого перехода у Activity существует метод, который оповещает актив- ность об изменении состояния. На рис. 3.1 изображен жизненный цикл активности, состояния и методы. Субклассы Activity могут использовать методы, пред- ставленные на рис. 3.1, для выполнения необходимых действий во время критических переходов жизненного цикла активности. Один из таких методов вам уже знаком — это метод onCreate(Bundle) . ОС вызывает этот метод после создания экземпляра активности, но до его отображения на экране. Как правило, активность переопределяет onCreate(…) для подготовки пользовательского интерфейса: заполнение виджетов и их вывод на экран (вызов setContentView(int) ); получение ссылок на заполненные виджеты; назначение слушателей виджетам для обработки взаимодействия с пользователем; подключение к внешним данным модели. Важно понимать, что вы никогда не вызываете onCre- ate(…) или другие методы жизненного цикла Activity в своих приложениях. Вы переопределяете их в суб- классах активности, а Android вызывает их в нужный момент времени. Завершает- ся или унич- тожается Выполнение (приложение видимо и находится на переднем плане) Приостановка (приложение видимо) Остановка (приложение невидимо) Приложение не существует Выходит на передний план Уходит с переднего плана Становится видимым для пользователя Перестает быть видимым Запуск Рис. 3.1. Диаграмма состояний Activity 3
72 Глава 3. Жизненный цикл Activity Регистрация событий жизненного цикла Activity В этом разделе мы переопределим методы жизненного цикла, чтобы отслеживать основные переходы жизненного цикла QuizActivity . Реализации ограничиваются регистрацией в журнале сообщения о вызове метода. Создание сообщений в журнале В Android класс android.util.Log отправляет журнальные сообщения в общий журнал системного уровня. Класс Log предоставляет несколько методов регистрации сообщений. Следующий метод чаще всего встречается в этой книге: public static int d(String tag, String msg) Имя «d» означает «debug» (отладка) и относится к уровню регистрации сообщений. (Уровни Log более подробно рассматриваются в последнем разделе этой главы.) Первый параметр определяет источник сообщения, а второй — его содержимое. Первая строка обычно содержит константу TAG , значением которой является имя класса. Это позволяет легко определить источник конкретного сообщения. В файле QuizActivity.java добавьте константу TAG в QuizActivity Листинг 3.1. Добавление константы TAG (QuizActivity.java) public class QuizActivity extends Activity { private static final String TAG = "QuizActivity"; } Включите в onCreate(…) вызов Log.d(…) для регистрации сообщения. Листинг 3.2. Включение команды регистрации сообщения в OnCreate(…) (QuizActivity.java) public class QuizActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG, "onCreate(Bundle) called"); setContentView(R.layout.activity_quiz); Если Eclipse выдаст ошибку, относящуюся к классу Log , нажмите Command+Shift+O ( Ctrl+Shift+O ) для проведения организации импорта. Eclipse предложит выбрать импортируемый класс; выберите android.util.Log Теперь переопределите еще пять методов в QuizActivity
Регистрация событий жизненного цикла Activity 73 Листинг 3.3. Переопределение методов жизненного цикла (QuizActivity.java) } // Конец onCreate(Bundle) @Override public void onStart() { super.onStart(); Log.d(TAG, "onStart() called"); } @Override public void onPause() { super.onPause(); Log.d(TAG, "onPause() called"); } @Override public void onResume() { super.onResume(); Log.d(TAG, "onResume() called"); } @Override public void onStop() { super.onStop(); Log.d(TAG, "onStop() called"); } @Override public void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy() called"); } } Обратите внимание на вызовы реализаций суперкласса перед регистрацией со- общений. Эти вызовы являются обязательными, причем реализация суперкласса должна вызываться до выполнения каких-либо критических операций в onCreate(…) ; в других методах порядок менее важен. Возможно, вы заметили аннотацию @Override . Она приказывает компилятору проследить за тем, чтобы класс действительно содержал переопределяемый метод. Например, компилятор сможет предупредить вас об опечатке в имени метода: public class QuizActivity extends Activity { @Override public void onCreat(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_quiz); }
74 Глава 3. Жизненный цикл Activity Класс Activity не содержит метод onCreat(Bundle) , поэтому компилятор выдает предупреждение. Это позволит вам исправить опечатку вместо того, чтобы случайно реализовать QuizActivity.onCreat(Bundle) Использование LogCat Чтобы просмотреть системный журнал во время работы приложения, используйте LogCat — программу, включенную в ин- струментарий Android SDK. Чтобы запустить LogCat, выполните ко- манду Window Show View Other... В папке Android найдите и выделите LogCat , затем щелкните на кнопке OK (рис. 3.2). LogCat открывается в правой половине экрана, а панель редактора становится слишком мелкой. Было бы удобнее, если бы панель LogCat размещалась в нижней части инструментального окна. Чтобы переместить панель, перетащите корешок панели LogCat на панель инстру- ментов в правом нижнем углу инструмен- тального окна (рис. 3.3). Панель LogCat закрывается, а ее значок появляется на панели инструментов. Щелкните на значке; LogCat открывается в нижней части окна. Инструментальное окно Eclipse должно выглядеть примерно так, как показано на рис. 3.4. Вы можете изменить размеры внутренних панелей LogCat, перетаскивая их границы мышью (это относится к любым панелям в инструментальном окне Eclipse). Запустите GeoQuiz; на панели LogCat начнут быстро появляться сообщения. Большинство из них генерируется системой. Прокрутите список и найдите свои сообщения. В столбце TAG панели LogCat выводится константа TAG , определенная для QuizActivity (Если никакие сообщения не выводятся, возможно, LogCat отслеживает не то устройство. Выполните команду Window Show View Other... и откройте панель De- vices . Выберите устройство, на котором работает программа, и вернитесь к LogCat.) Чтобы упростить поиск сообщений, можно отфильтровать вывод по константе TAG В LogCat щелкните на зеленом значке + в верхней части левой внутренней панели; эта кнопка создает фильтр сообщений. Введите имя фильтра QuizActivity и введите строку QuizActivity в поле by Log Tag: (рис. 3.5). Рис. 3.2. Поиск программы LogCat
Использование LogCat 75 Рис. 3.3. Перетаскивание корешка LogCat на панель инструментов в правом нижнем углу Рис. 3.4. Инструментальное окно Eclipse с панелью LogCat