<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="http://wiki2.linuxformat.ru/skins/common/feed.css?97"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title>LXF130:Android - История изменений</title>
		<link>http://wiki2.linuxformat.ru/index.php?title=LXF130:Android&amp;action=history</link>
		<description>История изменений этой страницы в вики</description>
		<language>ru</language>
		<generator>MediaWiki 1.11.1</generator>
		<lastBuildDate>Wed, 13 May 2026 23:38:43 GMT</lastBuildDate>
		<item>
			<title>Crazy Rebel: Новая: : '''Android''' Создаем приложения для открытой мобильной платформы  ==Android: И так далее==  {{Цикл/Android}}  : Во вто...</title>
			<link>http://wiki2.linuxformat.ru/index.php?title=LXF130:Android&amp;diff=11842&amp;oldid=prev</link>
			<description>&lt;p&gt;Новая: : '''Android''' Создаем приложения для открытой мобильной платформы  ==Android: И так далее==  {{Цикл/Android}}  : Во вто...&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая статья&lt;/b&gt;&lt;/p&gt;&lt;div&gt;: '''Android''' Создаем приложения для открытой мобильной платформы&lt;br /&gt;
&lt;br /&gt;
==Android: И так далее==&lt;br /&gt;
&lt;br /&gt;
{{Цикл/Android}}&lt;br /&gt;
&lt;br /&gt;
: Во второй части учебника по программированию для платформы Android '''Джульетта Кемп''' объяснит, как улучшить приложение и опубликовать его.&lt;br /&gt;
&lt;br /&gt;
Месяц назад мы настроили среду разработки Android и написали основной код программы для составления списка. Сделаем программу немного более полезной, добавив возможность указать текст записи и создав пункт меню для удаления списка. Потом мы посмотрим, как поделиться этой программой с другими.&lt;br /&gt;
&lt;br /&gt;
{{Врезка|Содержание=[[Изображение:LXF130_80_1.jpg|300px]] Воспользуемся приложением из предыдущей статьи и удалим элементы из созданного списка.|Ширина=300px}}&lt;br /&gt;
&lt;br /&gt;
Важная особенность архитектуры Android – модульность приложений, и в одной программе можно использовать участки другой, если та это разрешает. А значит, незачем каждый раз разрабатывать собственные компоненты: гораздо эффективнее пустить в ход готовые. Поэтому в приложениях для Android нет единой точки входа – например, в отличие от других программ на ''Java'' здесь нет метода '''main()'''. Вместо этого программы строятся из компонентов. У вашей программы будет стартовая точка по умолчанию (указанная в файле '''AndroidManifest.xml'''), но она может выполняться и начиная с других точек, в зависимости от того, откуда вызвана. Структура программы – занятия, намерения и представления.&lt;br /&gt;
&lt;br /&gt;
Android – удивительная платформа с быстро растущим сообществом разработчиков. Начать разрабатывать для нее нетрудно, потому что программы почти полностью пишутся на ''Java''. Освоив это, вы сможете заняться массой интересных и новых вещей. &lt;br /&gt;
&lt;br /&gt;
===Занятия, Намерения и Представления===&lt;br /&gt;
&lt;br /&gt;
Существует четыре основных типа компонентов, но в этой программе используется только первый из них – Занятия:&lt;br /&gt;
* '''Занятия (Activity)''' Каждое Занятие – визуальный интерфейс для определенного действия пользователя в приложении. У нас есть Занятие '''List''' – отображение списка элементов, и другое Занятие (мы создадим его сегодня), добавление элемента. Занятий может быть столько, сколько необходимо вашему приложению. У Занятия есть окно поумолчанию, полноэкранное либо всплывающее, а содержимое этого окна поставляется Представлениями. Каждое Представление управляет некоторым прямоугольником в окне и наследуется от базового класса '''View'''. Представления могут откликаться на действия пользователя в «подведомственной» области.&lt;br /&gt;
* '''Сервисы (Service)''' У сервиса нет визуального интерфейса, но он работает в фоне (например, воспроизводит музыку). Обычно он продолжает работать после того, как пользователь покинул приложение.&lt;br /&gt;
* '''Широковещательные приемники (Broadcast Receiver)''' Они принимают и реагируют на широковещательные оповещения, обычно от самой системы. В ответ на некоторые системные оповещения широковещательный приемник может выполнить действие.&lt;br /&gt;
* '''Контент-провайдеры (Content Provider)''' Предоставляют данные приложения в доступ другим программам. Здесь нам это не понадобится, но наше приложение можно будет расширить, сделав его базу данных доступной другим приложениям.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Первые три типа компонентов активируются '''Намерениями''' [Intent], которые представляют собой объекты, содержащие сообщение. Сообщение может состоять из запроса действия и некоторых данных – мы воспользуемся ими позже на данном уроке.&lt;br /&gt;
&lt;br /&gt;
Удаление элемента – более простое из двух изменений, которые мы собираемся внести в код примера с прошлого урока. Мы воспользуемся контекстным меню: оно появляется, если щелкнуть по элементу и придержать кнопку мыши. В методе '''onCreate''' уже есть вызов, регистрирующий контекстное меню:&lt;br /&gt;
&lt;br /&gt;
 registerForContextMenu(getListView());&lt;br /&gt;
&lt;br /&gt;
Теперь создадим контекстное меню – точно так же, как создавали обычное. Добавьте следующий метод:&lt;br /&gt;
&lt;br /&gt;
{{Врезка|Содержание=[[Изображение:LXF130_82_1.jpg|300px]] Эмулятор Android — отличный способ тестировать свои программы перед выпуском прямо на рабочем столе Linux.|Ширина=300px}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=java&amp;gt;&lt;br /&gt;
 public void onCreateContextMenu(Menu menu, View view,&lt;br /&gt;
 ContextMenuInfo info) {&lt;br /&gt;
 super.onCreateContextMenu(menu, view, info);&lt;br /&gt;
 menu.add(0, DELETE_ID, 0, R.string.menu_delete);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''DELETE_ID''' нужно определить в начале:&lt;br /&gt;
&lt;br /&gt;
 private static final int DELETE_ID = ADD_ID + 1;&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что элементы добавляются в различные меню, вам понадобится использовать разные значения для двух констант, иначе элемент меню не отобразится должным образом. Вам также понадобится задать строку '''menu_delete''' в '''res/values/strings.xml'''. Как мы обсуждали на прошлом уроке, наборы строк и другие данные приложения лучше хранить в разделе '''resources''', а не смешивать с кодом.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;string name=”menu_delete”&amp;gt;Delete item&amp;lt;/string&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь напишем метод, обрабатывающий события при выборе пункта меню. Создайте метод из файла '''snippet1.txt''' в каталоге '''Magazine/Android''' нашего DVD. Опять же, в выражении '''switch''' есть только одна ветвь. Обратите внимание на разницу имен этого метода и метода '''onMenuItemSelected()''', который мы написали в предыдущей статье. Эти методы предоставляет Android: сразу после создания меню методы с такими именами будут автоматически использованы для обработки его пунктов. Больше ничего делать не нужно.&lt;br /&gt;
&lt;br /&gt;
Так как это контекстное меню, оно автоматически связывается с определенным элементом списка. Метод получает информацию о выбранном элементе, вызывает обработчик базы данных для удаления записи и снова получает данные из базы, так что изменение немедленно отображается на экране. Наконец, нам потребуется метод удаления данных в базе в '''ListDbAdapter.java''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=java&amp;gt;&lt;br /&gt;
 public boolean deleteItem(long rowId) {&lt;br /&gt;
 return mDb.delete(DB_TABLE, DB_ROWID + “=” +&lt;br /&gt;
 rowId, null) &amp;gt; 0;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Он использует переданный идентификатор строки '''rowId''' и удаляет указанный элемент. Данный идентификатор передается из метода '''onContextItemSelected()''', в котором он извлекается из базы данных.&lt;br /&gt;
&lt;br /&gt;
Если вы не используете ''Eclipse'', придется вручную импортировать классы в начале файла '''List.java''' – см. код на DVD.&lt;br /&gt;
&lt;br /&gt;
===Добавляем элемент с заголовком===&lt;br /&gt;
&lt;br /&gt;
До настоящего времени все новые элементы списка получали один и тот же стандартный текст, но на практике толку от этого мало. Сделаем так, чтобы пользователь мог ввести то, что сочтет нужным.&lt;br /&gt;
&lt;br /&gt;
Для этого создадим еще одно Занятие – ‘'''ListAdd'''’. Это будет класс '''ListAdd''', который будет жить в файле '''ListAdd.java'''. Как говорилось выше, Занятие – нечто выполняемое внутри приложения, и у него обычно есть собственные установки экрана, оно обрабатывает собственные Представления и т. д.&lt;br /&gt;
&lt;br /&gt;
Прежде всего нам понадобится код, вызывающий '''ListAdd''' из главного Занятия '''List'''. Измените метод '''createItem()''' в '''List.java''' таким образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=java&amp;gt;&lt;br /&gt;
 private void createItem() {&lt;br /&gt;
  Intent i = new Intent(this, ListAdd.class);&lt;br /&gt;
  startActivityForResult(i, ITEM_ADD);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Намерение — способ реализации обмена информацией между Занятиями. В него мы передаем текущий контекст [this] и имя класса, которому мы собираемся передать объект '''Intent'''. Затем мы вызываем класс методом '''startActivityForResult()''', передавая ему полученный объект Намерения и код, которым он воспользуется для идентификации результата. Вам также потребуется установить его значение в начале файла – подойдет любое:&lt;br /&gt;
&lt;br /&gt;
 private static final int ITEM_ADD=0;&lt;br /&gt;
&lt;br /&gt;
Вместо '''startActivityForResult()''' вы можете воспользоваться '''startActivity()''', но его имя подсказывает, что '''startActivity()''' не возвращает ничего из Занятия, которое он запускает. Здесь это не подходит, так как мы хотим получить строку и обработать ее. В общем, метод '''startActivityForResult()''' более удобен.&lt;br /&gt;
&lt;br /&gt;
Далее обработаем строку, возвращаемую из действия '''ListAdd'''. Добавьте метод '''onActivityResult()''' – он выглядит следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=java&amp;gt;&lt;br /&gt;
 @Override protected void onActivityResult(int requestCode,&lt;br /&gt;
 int resultCode, Intent i) {&lt;br /&gt;
 super.onActivityResult(requestCode, resultCode, i);&lt;br /&gt;
 if (resultCode == RESULT_CANCELED) {&lt;br /&gt;
 return;&lt;br /&gt;
 }&lt;br /&gt;
 Bundle extras = i.getExtras();&lt;br /&gt;
 switch(requestCode) {&lt;br /&gt;
 case ITEM_ADD:&lt;br /&gt;
 String label = extras.getString(ListDbAdapter.DB_ITEM);&lt;br /&gt;
 mDb.createItem(label);&lt;br /&gt;
 getData();&lt;br /&gt;
 break;&lt;br /&gt;
 }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Этот метод обрабатывает все результаты всех Занятий, которые вызывает '''List''': поэтому мы и передаем код идентификации. Здесь у нас единственное доступное значение, но если бы вы захотели делать что-то еще, например, редактировать элементы списка, потребовалось бы больше.&lt;br /&gt;
&lt;br /&gt;
Сперва проверим, была ли операция отменена – тогда делатьничего не нужно. Значение переменной '''RESULT_CANCELED''' устанавливается в главном классе Занятия '''Activity''', так что это глобальное возвращаемое значение. В классе '''ListAdd''' мы свяжем этот результат с кнопкой '''Cancel''' [Отмена].&lt;br /&gt;
&lt;br /&gt;
Если Занятие не было отменено, мы берем связку ('''Bundle'''), ассоциированную с возвращенным Намерением. Она используется для получения карты дополнительных данных ('''extras'''), которая хранится внутри Намерения (мы заполним ее в классе '''ListAdd''' позже) и связывает строки с другими типами данных: это нечто вроде хэша, который возвращает данные по ключу. Как видите, в секции '''ITEM_ADD''' оператора '''switch''' мы получаем значение '''label''' (имя элемента, который будет добавлен в список) из '''extras''' по ключу '''ListDbAdapter.DB_ITEM'''. Для ключа понадобится статическая переменная (вы будете обращаться к ней из нескольких классов), и неплохо использовать существующую и релевантную статическую строку. В данном случае, это столбец базы данных, где будут храниться данные. Затем вызывается метод обработчика базы данных, и метод '''getData()''' обновляет данные на экране.&lt;br /&gt;
&lt;br /&gt;
Последнее, что нужно сделать – создать класс, который сделает всю работу. Взгляните на код класса '''ListAdd''' на нашем DVD, в нем всего один метод:&lt;br /&gt;
&lt;br /&gt;
{{Врезка|Содержание=[[Изображение:LXF130_82_2.jpg|300px]] Вот что вы увидите при добавлении элемента в список.|Ширина=300px}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=java&amp;gt;&lt;br /&gt;
 @Override&lt;br /&gt;
 public void onCreate(Bundle savedInstanceState)&lt;br /&gt;
 {&lt;br /&gt;
 super.onCreate(savedInstanceState);&lt;br /&gt;
 setContentView(R.layout.newitem);&lt;br /&gt;
 label = (EditText) findViewById(R.id.newitemlabel);&lt;br /&gt;
 Button okButton = (Button) findViewById(R.id.okbutton);&lt;br /&gt;
 cancelButton = (Button) findViewById(R.id.cancelbutton);&lt;br /&gt;
 okButton.setOnClickListener(new View.OnClickListener()&lt;br /&gt;
 {&lt;br /&gt;
 public void onClick(View view) {&lt;br /&gt;
  Bundle bundle = new Bundle();&lt;br /&gt;
 bundle.putString(ListDbAdapter.DB_ITEM,&lt;br /&gt;
 label.getText().toString());&lt;br /&gt;
 Intent i = new Intent();&lt;br /&gt;
 i.putExtras(bundle);&lt;br /&gt;
 setResult(RESULT_OK, i);&lt;br /&gt;
 finish();&lt;br /&gt;
 }&lt;br /&gt;
 });&lt;br /&gt;
 cancelButton.setOnClickListener(new View.&lt;br /&gt;
 OnClickListener() {&lt;br /&gt;
 public void onClick(View view) {&lt;br /&gt;
 Intent i = new Intent();&lt;br /&gt;
 setResult(RESULT_CANCELED, i);&lt;br /&gt;
 finish();&lt;br /&gt;
 }&lt;br /&gt;
 });&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Этот метод вызывается при активации Занятия из '''List''' (а вообще-то, и из любого другого Занятия). Устанавливается раскладка Представлений (см. файл '''newitem.xml''' на DVD – в нем есть блок '''EditText''', куда можно ввести текст, и кнопка '''OK''').&lt;br /&gt;
&lt;br /&gt;
Мы получаем значение '''label''' (представляющее собой объект '''EditText''', объявленный в начале класса) из раскладки по его идентификатору '''ID newitemlabel''', а затем также получаем кнопку '''OK''' из раскладки как объект, снова идентифицируя его по ID. То же происходит и для кнопки '''Cancel'''.&lt;br /&gt;
&lt;br /&gt;
Самая важная часть кода – метод '''setOnClickListener()''' для кнопки '''OK''': он определяет, что произойдет по ее нажатию. Создается новая связка ['''Bundle'''], и к ней добавляется пара: ключ (строка '''DB_ITEM''', используемая в коде обработки возврата в классе '''List''') и значение из блока '''EditText''', преобразованное в строку. Наконец, создается Намерение, принимающее связку; результат устанавливается в '''OK''' ('''RESULT_OK''' – стандартное значение, заданное в классе '''Activity'''), и Занятие завершается. Затем результат вернется в вызывающее Занятие (в нашем случае – '''List'''), которое обработает его в соответствии с уже написанным нами кодом.&lt;br /&gt;
&lt;br /&gt;
{{Врезка|Заголовок=Скорая помощь|Содержание=Чтобы запустить эмулятор, наберите ''emulator -avd myavd''. Для переустановки в эмулятор существующего пакета, наберите ''adb in-stall -r List/bin/List-debug.apk''.|Ширина=200px}}&lt;br /&gt;
&lt;br /&gt;
Нам также понадобится метод '''setOnClickListener()''' для кнопки '''Cancel.''' Он проще: в нем лишь создается пустой объект '''Intent''' и используется глобальная константа '''RESULT_CANCELED''', означающая, что действие было отменено. Последняя задача – добавить свой класс в файл '''AndroidManifest.xml''', иначе он не будет найден во время компиляции. Добавьте строку&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;activity android:name=”.ListAdd”&amp;gt;&amp;lt;/activity&amp;gt;&lt;br /&gt;
&lt;br /&gt;
после тэга '''&amp;lt;/activity&amp;gt;''', завершающего листинг действия '''.List'''.&lt;br /&gt;
&lt;br /&gt;
Скомпилируйте свой код (ant debug), запустите эмулятор, загрузите его и попробуйте! Для отладки кода воспользуйтесь ''ddms'' и проверьте файлы журналов, детали работы с которыми описаны в предыдущей статье.&lt;br /&gt;
&lt;br /&gt;
===Публикация приложения===&lt;br /&gt;
&lt;br /&gt;
Пока у вас получилась отладочная (debug) версия программы. Следующий шаг – сделать из нее окончательную (release) версию, которой можно будет поделиться с другими. Все приложения Android должны быть заверены сертификатом разработчика, который может быть самоподписанным. Также нужно задать переменные '''android.versionCode''' и '''android.versionName''' в разделе '''&amp;lt;manifest&amp;gt;'''.&lt;br /&gt;
&lt;br /&gt;
Перед публикацией вам следует протестировать вашу программу на настоящем устройстве, если это вообще возможно. Не мешает также нарисовать иконку и указать ее в атрибуте '''android.icon''' секции '''&amp;lt;application&amp;gt;''' файла '''AndroidManifest.xml'''. Сам файл иконки сохраните в каталоге '''res/drawable'''.&lt;br /&gt;
&lt;br /&gt;
Редактируя '''AndroidManifest.xml''', нужно также указать в нем значение '''android.label''', название вашей программы в меню приложений. Удалите из манифеста атрибут '''android:debuggable=«true»''' и убедитесь, что в коде программы не осталось отладочных команд.&lt;br /&gt;
&lt;br /&gt;
Первый шаг – создание окончательной версии, пока не подписанной. Это сделает команда ''ant release'' (в отличие от ''ant debug''). Далее создайте свой сертификат с помощью ''Keytool'' (проверьте, что ссылка из '''/usr/bin/keytool''' указывает на версию в ''JDK'', а не ''gjc''). Рекомендуется задать срок действия в 25 лет, чтобы гарантировать возможность будущих обновлений без проблем для пользователя (сертификаты будут проверяться во время установки/обновления). Если вы хотите разместить приложение на Android Market, вам придется указывать именно этот срок. Он соответствует 9130 дням, которые мы округлим до 10 000.&lt;br /&gt;
&lt;br /&gt;
 keytool -genkey -v -keystore ~/android/release-keys.keystore -alias listapp -keyalg RSA -validity 10000&lt;br /&gt;
&lt;br /&gt;
У вас запросят пароль для '''keystore''', кое-какую персональную информацию о вас и пароль для ключа. Используйте сложные пароли или парольные фразы. Для '''keystore''' можно указать любой путь.&lt;br /&gt;
&lt;br /&gt;
 Затем подпишите приложение с помощью ''Jarsigner'', запустив эту команду в подкаталоге '''/bin/''' директории вашей программы:&lt;br /&gt;
&lt;br /&gt;
 jarsigner -verbose -keystore ~/android/release-keys.keystore List-unsigned.apk listapp&lt;br /&gt;
&lt;br /&gt;
Здесь '''listapp''' – псевдоним для ключа, '''List-unsigned.apk''' — само приложение, а '''-keystore''' задает ключевое хранилище – нужно указать полный путь к нему.&lt;br /&gt;
&lt;br /&gt;
Итак, приложение подписано; дайте ему какое-нибудь значимое имя, используя ''mv List-unsigned.apk List.apk''. Теперь можно проверить, что программа подписана, командой:&lt;br /&gt;
&lt;br /&gt;
 jarsigner -verify List.apk&lt;br /&gt;
&lt;br /&gt;
Еще раз проверьте финальную версию, и затем ее можно публиковать. Самый простой способ сделать это – просто выложить файл '''.apk''' на ваш сайт: пользователи смогут загрузить его и установить приложение с помощью ''AppManager'' или похожей программы.&lt;br /&gt;
&lt;br /&gt;
Альтернатива – воспользоваться Android Market (http://market.android.com/publish), который требует регистрации и взноса в 25 долларов, но упрощает загрузку приложения.&lt;br /&gt;
&lt;br /&gt;
Будем надеяться, наши уроки дали вам общее понятие о написании программ для Android. В сети есть масса полезных ресурсов: очень хороша документация разработчика для Android, есть и форумы, где можно задать вопрос разработчикам. Чтобы упростить создание интерфейса, попробуйте DroidDraw (http://www.droiddraw.org) – созданный нами интерфейс довольно примитивен! Также можно взглянуть на расширение Google API: оно позволит связать вашу программу с Google Maps. Как мы уже говорили, архитектура Android позволяет вызывать части кода других программ: приложение со списком Намерений (Intents List Appendix) в документации разработчика Android содержит все программы Google, которые можно вызвать (например, браузер или программу для звонков по телефону), и сообщает как это сделать. Вытакже можете рассмотреть API для определения движения.&lt;br /&gt;
&lt;br /&gt;
===Дальнейшие шаги===&lt;br /&gt;
&lt;br /&gt;
Наши уроки вас заинтриговали? Не останавливайтесь на достигнутом: есть масса способов улучшить написанное нами приложение. Вот несколько из них для начала. Обратите внимание, что некоторые из них могут потребовать изменения – или полной переработки – кода для работы с базой данных.&lt;br /&gt;
* Добавить возможность редактирования элемента: можно воспользоваться классом '''ListAdd''' и переданным объектом '''Intent''' для хранения информации о текущих значениях метки элемента и идентификатора строки в базе данных.&lt;br /&gt;
* Добавить обработку ввода, чтобы, например, нажатие '''Enter''' обладало тем же эффектом, что и нажатие кнопки '''OK''' в окне «'''Добавить элемент'''».&lt;br /&gt;
* Улучшить управление жизненным циклом, чтобы кнопка «'''Назад'''» работала правильно.&lt;br /&gt;
* Добавить флажки рядом с каждым элементом.&lt;br /&gt;
* Реализовать массовое удаление.&lt;br /&gt;
* Добавить к элементу категорию, поле примечания или другие информационные поля.&lt;br /&gt;
* Поищите сайты программ для составления списков и подумайте, не поучаствовать ли.&lt;/div&gt;</description>
			<pubDate>Fri, 15 Apr 2011 13:48:23 GMT</pubDate>			<dc:creator>Crazy Rebel</dc:creator>			<comments>http://wiki2.linuxformat.ru/index.php/%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:LXF130:Android</comments>		</item>
	</channel>
</rss>