Google предлагает проекты библиотек Android в качестве способа управления повторно используемым кодом. В первой части этой серии из трех статей о проектах библиотек Android я познакомил вас с основами библиотечных проектов.
В этой статье я перехожу от теории к практичности, представляя полезный пример многократно используемого проекта библиотеки диалоговых окон.
Я использовал Android SDK Release 20 вместе с платформами Android 2.3.3 (API Level 10) и Android 4.1 (API Level 16) для разработки и тестирования кода этой статьи.
О диалоговом окне Android Library Project
Диалоговое окно about (также известное как info) является хорошим примером повторно используемого кода, который можно сохранить в проекте библиотеки Android. О диалоговых окнах обычно идентифицируют приложения (имена, номера версий, значки) и их авторов, предоставляют адреса электронной почты и другие ссылки для получения поддержки и посещения веб-сайтов авторов приложений, предлагают информацию о лицензии / отказе от ответственности и так далее.
Прежде чем я начал разрабатывать эту библиотеку, я размышлял над различными архитектурными вопросами. Каков минимальный уровень API библиотеки и имя пакета? Какие классы и другие ссылочные типы являются частью библиотеки? Я создаю экземпляры классов или отношусь к ним как к одиночкам? Что такое открытый интерфейс каждого типа? Храню ли я ресурсы и код? Если да, то какие ресурсы будут храниться? Я пришел к выводу со следующими ответами:
-
Минимальный уровень API равен 10, так что библиотека может использоваться Android 2.3.3 и выше. Имя пакета будет
ca.tutortutor.about
. - Библиотека будет состоять из одного класса с именем
About
. -
About
будет служить как синглтон (также известный как служебный класс). Я не буду создавать экземпляр этого класса, но буду вызывать статические методы. В конце концов, приложения обычно представляют одно диалоговое окно. -
About
будет отображать единственныйpublic static void show(Activity activity, String aboutText, String okButtonText)
. Этот метод будет использовать диспетчер пакетов Android для получения номера версии приложения, значка и имени. -
About
связан с ресурсом макета; других ресурсов нет. Я решил не включать строковые ресурсы, чтобы упростить локализацию. Я бы предпочел не обновлять проект библиотеки для поддержки дополнительных локалей. Вместо этого я считаю, что локализация должна происходить на уровне приложения; приложение должно передавать локализованный текст в диалоговое окно about.
Изучение исходного кода и ресурсов
Проект библиотеки диалогового окна about состоит из одного исходного файла ( About.java
) и одного файла ресурсов ( ca_tutortutor_about.xml
). В листинге 1 представлены About.java
.
package ca.tutortutor.about; import android.app.Activity; import android.app.AlertDialog; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.drawable.Drawable; import android.text.Html; import android.text.method.LinkMovementMethod; import android.view.InflateException; import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; public class About { public static void show(Activity activity, String aboutText, String okButtonText) { String versionNumber = "unknown"; Drawable icon = null; String appName = "unknown"; try { PackageManager pm = activity.getPackageManager(); versionNumber = pm.getPackageInfo(activity.getPackageName(), 0) .versionName; icon = pm.getApplicationIcon(activity.getPackageName()); ApplicationInfo ai = pm.getApplicationInfo(activity.getPackageName(), 0); appName = (String) pm.getApplicationLabel(ai); if (appName == null) appName = "unknown"; } catch (NameNotFoundException e) { } View about; TextView tvAbout; try { LayoutInflater inflater = activity.getLayoutInflater(); about = inflater.inflate(R.layout.ca_tutortutor_about, null); tvAbout = (TextView) about.findViewById(R.id.ca_tutortutor_aboutText); } catch(InflateException e) { about = tvAbout = new TextView(activity); } tvAbout.setText(Html.fromHtml(aboutText)); tvAbout.setMovementMethod(LinkMovementMethod.getInstance()); new AlertDialog.Builder(activity) .setTitle(appName+" "+versionNumber) .setIcon(icon) .setPositiveButton(okButtonText, null) .setView(about) .show(); } }
Листинг 1: About.java
В листинге 1 показан класс About
с public static void show(Activity activity, String aboutText, String okButtonText)
классом public static void show(Activity activity, String aboutText, String okButtonText)
:
-
activity
содержит ссылку на вызывающую активность, которая обычно является основной. -
aboutText
содержит текст диалогового окна about, который может включать теги HTML, такие как<b>
(полужирный),<i>
(курсив),<u>
(подчеркивание) и<p>
(абзац). Здесь вы можете указать свой веб-сайт для получения поддержки, предоставить информацию о лицензии / отказе от ответственности и т. Д. -
okButtonText
содержит текст, который появляется на кнопке, закрывающей диалоговое окно.
Этот метод сначала получает менеджер пакетов для доступа к номеру версии приложения, значку и имени. Диспетчер пакетов описывается классом PackageManager
, доступ к которому осуществляется путем вызова унаследованного PackageManager getPackageManager()
метода PackageManager getPackageManager()
.
PackageManager
объявляет PackageInfo getPackageInfo(String packageName, int flags)
для получения информации из пакета приложения. Пакет получается путем вызова унаследованного String getPackageName()
метода String getPackageName()
.
PackageInfo
объект PackageInfo
обеспечивает доступ к информации о пакете через его поля. Например, versionName
содержит строковое имя версии этого пакета (например, 1.0
), как указано в androidmanifest.xml
<manifest>
тега versionName
.
Drawable getApplicationIcon(String packageName)
позволяет получить значок приложения в виде экземпляра Drawable
. Этот метод вызывается с именем пакета действия в качестве аргумента.
getApplicationIcon()
ищет значок, указанный атрибутом icon
тега <application>
, возвращая значок по умолчанию, когда он не находит этот атрибут.
Название приложения теперь получено. Во-первых, ApplicationInfo getApplicationInfo (String packageName, int flags)
для возврата объекта ApplicationInfo
, соответствующего тегу <application>
манифеста. Затем этот объект передается в качестве аргумента в CharSequence getApplicationLabel(ApplicationInfo info)
, который возвращает значение атрибута метки тега <application>
или значение NULL, если этот атрибут отсутствует.
getPackageInfo()
и getApplicationInfo()
могут getApplicationInfo()
. Прежний метод вызывает это исключение, когда пакет с данным именем не может быть найден в системе. Последний метод вызывает это исключение, когда приложение с данным именем пакета не может быть найдено в системе. Из-за возможности этого исключения versionName
, icon
и appName
инициализируются значениями по умолчанию перед appName
этих методов.
Следующая основная задача в листинге 1 состоит в том, чтобы ca_tutortutor_about.xml
содержимое ca_tutortutor_about.xml
(описывается в ближайшее время) и получить доступ к его раздутому виджету textview. Он получает инфлятор компоновки, вызывая LayoutInflater getLayoutInflater()
, и использует этот метод для накачки XML-файла в представление about
. Затем он использует для доступа к виджету текстового представления этого представления. Обратите внимание на префикс ca_tutortutor_
в каждом из R.layout.ca_tutortutor_about
и R.id.ca_tutortutor_aboutText
чтобы избежать конфликтов ресурсов.
Виджет textview теперь настроен. Сначала содержимое aboutText
преобразуется из HTML в текст путем вызова метода класса Spanned fromHtml(String source)
Html
, и результат присваивается текстовому представлению для отображения. Во-вторых, этому виджету назначен метод перемещения ссылки, поэтому нажатие на ссылку приводит к тому, что пользователь попадает в пункт назначения ссылки. (В эмуляторе нажатие на ссылку электронной почты приводит к появлению диалогового окна « Неподдерживаемое действие ».)
Последняя задача — создать экземпляр AlertDialog
настроить и показать этот экземпляр. Для удобства я использую вложенный класс Builder
AlertDialog
для выполнения этих задач.
В листинге 2 представлен ca_tutortutor_about.xml
.
<?xml version="1.0" encoding="utf-8"?> <scrollview xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ca_tutortutor_aboutView" android:layout_width="fill_parent" android:layout_height="fill_parent"> <linearlayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" android:padding="5dp"> <textview android:id="@+id/ca_tutortutor_aboutText" android:layout_width="wrap_content" android:layout_height="fill_parent"></textview> </linearlayout> </scrollview>
Листинг 2: ca_tutortutor_about.xml
В листинге 2 описан макет, состоящий из вида scrollview, в который вложен линейный макет, в который вкладывается textview. Представление прокрутки присутствует, так что вы можете указать столько содержимого, сколько вам требуется для диалогового окна about, и разрешить пользователю доступ к этому содержимому с помощью прокрутки.
Каждому из scrollview и textview назначается идентификатор, чтобы к нему можно было получить доступ из About.java
show()
About.java
, о котором вы узнали ранее в этой статье. ca_tutortutor_
необходимы для избежания конфликтов ресурсов.
Создание и инициализация О
Давайте создадим и инициализируем этот библиотечный проект. Первым шагом является создание проекта. Я использовал следующую командную строку для выполнения этой задачи на моей платформе Windows:
android create lib-project -t 1 -p C:\prj\ap\About -k ca.tutortutor.about
Цель 1 идентифицирует Android 2.3.3 на моей платформе. (Выполните android list targets
чтобы получить эквивалентное число целей на вашей платформе.) Я храню этот проект в своем C:\prj\ap\About
. Наконец, имя пакета проекта — ca.tutortutor.about
.
Затем я создал иерархию подкаталогов ca\tutortutor\about
About\src
и скопировал файл About.java
содержащий содержимое листинга 1, в about
. Я также скопировал файл ca_tutortutor_about.xml
содержащий содержимое листинга 2, в файл About\res\layout
.
About\res\layout
также содержит файл main.xml
, который помещается в этот каталог при создании проекта библиотеки. Вы можете удалить этот файл или оставить его, потому что проекты вашего приложения, скорее всего, предоставляют свои собственные файлы main.xml
, которые переопределяют этот main.xml
.
Точно так же вы найдете каталог About\res\values
содержащий strings.xml
. Поскольку удаление этого файла не позволяет вам создавать About (для проверки любых изменений исходного кода на наличие ошибок), вы можете также оставить этот файл в покое — он переопределяется файлом strings.xml
проекта приложения.
На этом этапе вы можете убедиться, что проект библиотеки собирается правильно. Выполните эту задачу, выполнив следующую команду:
ant debug
Вы должны наблюдать сообщение BUILD SUCCESSFUL .
Вывод
Теперь, когда вы изучили исходный код и ресурсы, которые вносят вклад в проект библиотеки диалоговых окон about, и создали и инициализировали этот проект, вы захотите интегрировать его в свои собственные проекты приложений. В заключительной части этой серии я представляю проект приложения, который поддерживает диалоговое окно about через меню параметров.