Пример Android приложения inventory

Чтобы проиллюстрировать процесс работы в Eclipse, создадим короткое приложение в 200 строк, хранящее инвентарные номера в базе данных в самом устройстве. Этот пример можно взять за основу для создания программ для хранения номеров для кодовых замков для коммунальных служб, например.
Сначала я хотел выбрать приложение, подсчитывающее количество людей наподобие простых счетчиков, используемые, например, авиации для подсчета пассажиров при посадке, но он состоял бы из одного значимого оператора count++. Поэтому я решил продемонстрировать, как Андроид предлагает работать с более сложными наборами данных и, главное, предоставлять их из одного приложения в другое. Думаю, это интересно- так как SDK Андроид предлагает практически только один такой способ, причем достаточно новый.
Опишу шаг за шагом.
Установив Android SDK и плагин к Eclipse, запускаем среду разработки.
Выбираем меню File-New-Android Project.
 
 
 
 
Menu
В появившемся диалоге задаем имя проекта: inventory, папку, где плагин создаст файлы проекта, имя Java пакета: ru.icsit.inventory, одинаковые имена активности и приложения: inventory. Активностью называется класс окна Android. Это подчеркивает отличия в поведении окон в Андроиде от, например, Windows. Плагин Eclipse создает новый проект с одной активностью, хотя их может быть несколько.New class
Начнем с добавления класса, обеспечивающего доступ к базе данных. Выбираем меню File-New-Java class и в диалоге вводим имя нового класса: ItemsProvider. Этот класс расширит класс провайдера данных ContentProvider, мы используем его, чтобы предоставить другим приложениям доступ к нашей базе.
Мы могли бы написать класс провайдера с использованием файла или удаленного сервера для хранения данных, но раз уж в Андроид штатно входит СУБД SQLite, разумно использовать ее. На мой взгляд, ее удобнее использовать вместо файлов, и это не отражается на занимаемом размере и скорости работы. Я рассматриваю ее, если сравнивать с Windows, одновременно, как реестр для хранения настроек программы, так и отдельное для данного приложения хранилище пользовательских данных. Разумеется, хранить полноценную СУБД предприятия на мобильном устройстве никто не рискнет, да и по моим экспериментам, размер одной таблицы не может быть больше 40М (скорее всего, здесь играют роль аппаратные ограничения (или эмулятора) и ограничения в настройках где то в глубинах Linux).
Сначала объявим в нем вложенный класс DatabaseHelper, который поможет создать саму базу данных при первом старте приложения. Два абстрактных метода нужно перекрыть. Перекрытый метод onCreate вызывается, если база еще не существует, и он создает таблицу оператором SQL:
CREATE  	TABLE items (_id INTEGER PRIMARY KEY, invno INTEGER, description  	TEXT, qty INTEGER, location TEXT)
Когда пользователь получит пакет приложения и запустит его, приложение само создаст нужные файлы. Одно из особенностей SQLite- поле первичного ключа _id является автоинкрементным. SQLite не проверяет типы, поэтому нет смысла указывать длины полей.
Второй перекрываемый метод onUpdate вызывается в случае, когда пользователь устанавливает обновление программы с измененной структурой таблиц, что отмечается увеличением номера версии базы данных. Так как это пример, в этом методе просто уничтожим существующую таблицу и вызовем метод onCreate для создания таблицы заново. В реальных же приложениях изменение структуры таблиц должно происходить без потери пользовательских данных.
Перейдем теперь от вложенного собственно к классу ContentProvider. Перекроем метод ItemsProvider.onCreate, где создадим экземпляр DatabaseHelper и вызовем, что очевидно, его метод openDatabase.
Другие приложения могут получить доступ к нашим данным, вызывая методы query, getType, insert, delete (как вы догадались, их нужно перекрыть), которые получают в параметре url:
content://ru.icsit.provider.Inventory/items
Этот URL мы присвоим публичному члену класса CONTENT_URI_ITEMS, так как он будет часто использоваться и внутри нашей программы для доступа к данным. Другие приложения узнают об этом URL из манифеста Andoid.
Получается, что приложения могут получать данные друг от друга, используя URL. Также, как в веб, полученный ответ снабжается MIME типом возвращаемых данных. Приложение Андроид можно представить как веб-сервер, для которых ОС Андроид копирует Интернет. По аналогии с Интернет, где вы должны зарегистрировать ваш домен, в Андроиде вы должны зарегистрировать свой «адрес» чтобы публиковать данные.
Любое приложение Android имеет манифест. Плагин Eclipse создает файл манифеста AndroidManifest.xml. К нему добавим указание, что класс ItemsProvider по этому URL предоставляет данные:
<provider  	class="ItemsProvider"  	authorities="ru.icsit.provider.Inventory" />
Из манифеста операционная система регистрирует не только то, какие данные приложение может предоставить другим приложениям, но и позволяет контролировать другие взаимодействия между приложениями. В SDK Андроида нет событий, как в Windows для оповещения других приложений, их заменяет описанная выше техника. Когда другое приложение захочет получить данные от нашего приложения, Андроид загрузит класс ItemsProvider, и из него внешнее приложение получит данные.
Теперь, используя этот URL, любое приложение может запросить данные. В веб возвращаемые объекты имеют, например, MIME тип text/html. В нашем примере мы хотим передать курсор набора данных, содержащий один или несколько строк, и в перекрываемом методе getType вернем один из двух MIME типов:
vnd.android.cursor.item/vnd.icsit.item
vnd.android.cursor.dir/vnd.icsit.item
в зависимости от переданного URL. Мы можем передать и картинки, тогда нужно указать, например, тип image/jpeg. Пусть, если приложение хочет получить отдельную запись, оно может добавить идентификатор записи прямо в URL. Если идентификатора нет, вернем ему курсор для всего набора данных. Чтобы сделать это, создадим объект URL_MATCHER класса ContentURIParser, задача которого определить по передаваемому URL, какие данные нужны. Добавим два варианта- .items и items/#
Если URL завершается items/#, то вернем одну запись по ее идентификатору (вариант 2), иначе вернем весь набор данных (вариант 1).
Перейдем теперь к методу query. В параметре selection запрашивающее приложение может передать выражение, стоящее в операторе SELECT за словом WHERE (мы используем SQLite, так что проблем нет. Если бы использовались файлы для хранения, то этот параметр можно просто игнорировать). Также оно может управлять сортировкой и группированием результатов. Но если мы не желаем предоставить такую возможность, в вызове конструктора запроса можно не передавать эти параметры.
Перекрытые методы insert, update, delete проверяют правильность передаваемого URL и вызывают одноименные методы класса SQLiteDatabase, которые возвращают количество задействованных строк. Эту приятность я решил использовать в методе update, если результат выполнения mDB.update() говорит, что записей, удовлетворяющих условию нет, то вызывается метод вставки. Это, конечно, не совсем корректно, зато упростит наш пример.

Теперь перейдем к наполнению формы. Плагин Eclipse создал два файла нашей единственной формы- inventory.java и main.xml и уже в классе активности добавил загрузку элементов управления по описанию в main.xml. Можно вызывать конструкторы элементов управления в коде, но мне кажется, это слишком трудоемко. Поэтому будем редактировать ресурс main.xml. На форму положим элементы ввода текста для четырех полей в таблице и снабдим их метками: Номер, Описание, Кол-во, Размещение. Также добавим кнопки: со знаком «?» для поиска, «Схр» для сохранения изменений и одновременно, для создания новой записи (для этого я и совместил insert с update в классе провайдера) и «-» - для удаления записи. Введя инвентарный номер и нажав кнопку поиска, остальные элементы управления заполнятся найденными значениями. Отредактировав их, можно сохранить изменения кнопкой «Схр».
Я использовал ранее утилиту DroidDraw для визуального редактирования main.xml, так как я не получаю удовольствия от ручной правки XML. DroidDraw не понимает кодировку UTF-8, а я использовал символы кириллицы, поэтому после нее пришлось немного подправить файл руками, заодно изменить автоматически создаваемые DroidDraw идентификаторы элементов на более осмысленные:
<Button  	id="@+id/bsearch"  	a:text="\?"  	/>
Сейчас плагин Eclipse предоставляет более удобный встроенный визуальный редактор экранов. Eclipse вызывает упаковщик ресурсов SDK aapt для генерации класса R, добавляемого в проект для указания идентификаторов ресурсов. Символы @+id/ указывают aapt поместить идентификатор bsearch в класс R. Я удалил идентификаторы меток, так как мне не нужно ссылаться на них из программы. Кнопки должны иметь идентификаторы, так как я должен буду назначить им обработчики нажатий, а из полей ввода я должен брать вводимые значения, так что им тоже нужны идентификаторы.
Для отрисовки формы Андроид использует механизмы, подобные браузерному рендеру, поэтому для веб программистов, наверное, не составит труда вручную редактировать main.xml. Я полагаю, что Андроид благодаря такому своему устройству окажется естественным для большого числа веб-программистов.
Теперь все готово, чтобы собрать все вместе в коде класса активности inventory. Перекроем метод onCreate, вызываемый при запуске активности. Первым делом проверим, что мы загружаем нашу форму main.xml из ресурсов:
setContentView(R.layout.main);
В ресурсы можно добавлять не только XML файлы, но файлы изображений и звуков, которым aapt назначает идентификаторы в класс R по названию файла. Проинициализируем переменные, которые будут указывать на элементы ввода текста:
mEditNum  	= (TextView) findViewById(R.id.enumber);
Затем создадим (пока пустые) обработчики нажатий
mButtonSearchClick,  	mButtonApplyClick, mButtonDeleteClick
для всех трех кнопок. Найдем загруженную кнопку по ее идентификатору, помещенному в классе R
findViewById(R.id.bsearch).setOnClickListener(mButtonSearchClick);
и назначим обработчики событий в методе onCreate.
Теперь остается написать код для этих трех событий.
В обработчике кнопки сохранения введенные данные берутся из формы и помещаются в объект ContentValues, который затем передается по URL нужному провайдеру данных в метод update:
values.put("invno",  	mEditNum.getText().toString());
getContentResolver().update(ItemsProvider.CONTENT_URI_ITEMS.addId(invno),  	values, null, null); 
Как видно, URL укажет на класс ItemsProvider и добавит идентификатор записи, так что будет вызван написанный ранее метод ItemsProvider.update. Конечно, можно было бы написать код доступа без класса ItemsProvider, но зато мы разделили код на часть, связанную с манипуляцией данными и часть, связанную с GUI, вдобавок, предоставили данные другим приложениям.
Теперь вернемся к манифесту. Добавим в него элемент intent-filter в раздел активности inventory:
<activity  	class=".inventory" a:label="@string/app_name">
...
<intent-filter  	a:label="Номер">
<action  	a:value="android.intent.action.VIEW" />
<action  	a:value="android.intent.action.EDIT" />
<action  	a:value="android.intent.action.DELETE" />
<type  	a:value="vnd.android.cursor.item/vnd.icsit.item" />
</intent-filter>
Действия VIEW, EDIT, DELETE соответствуют нашим трем кнопкам формы. Так мы объявляем (это называется Intent), что класс активности inventory позволяет показывать, редактировать и удалять данные указанного типа, и другие приложения могут вызывать наш класс формы для выполнения этих действий. Так обеспечивается интеграция приложений Андроида. Например, из своего приложения мы можем вызвать такие Intent'ы:
android.intent.action.CALL для URL вида tel:<номер телефона> чтобы позвонить,
android.intent.action.VIEW для URL вида geo:latitude,longitude или http://<адрес вебсайта> чтобы показать карту местности или веб страницу. Вызываемые Intent'ы могут возвращать результаты, которые мы можем использовать в своей программе. Службы Андроид также уведомляют приложения о внешних событиях (поступившем сообщении или звонке), о снижении заряда батареи и мощности сигнала, если приложение в манифесте указало, что оно желает получать такие уведомления.

Преимущества Андроида для разработчиков ПО

Сторонние разработчики обмениваются информацией о том, какие приложения они разрабатывают и их URL и Intent в рамках проекта OpenIntents. Здесь напрашивается сравнение с шеллами unix систем, как, например, ksh, в котором можно передавать выходные текстовые данные от одной программы другой по цепочке для получения желаемого результата. Андроид не ограничивается только текстовыми данными, можно получать от разных программ разные данные, включая аудио,- видеопотоки, пропускать через другие программы (фильтровать) и вызывать окна (активности) для того, чтобы пользователь мог поучаствовать в процессе.

Интересной особенностью Андроида является то, что, в качестве графических систем предлагается две- на базе веб браузера, и с использованием OpenGL. Так что разработчикам нет необходимости переучиваться на использование новой графической (оконной) системы, и процесс разработки приложений похож на создание динамических веб страниц. Хотелось бы, правда, чтобы интеграция ресурсов форм и кода была такой, как в интегрированной среде Delphi.

Для сетевой работы Андроид предлагает, в добавок к описанному выше механизму Intent'ов, привычные сетевые Java библиотеки и парсер XML. В собственном проекте я использовал пакет kSOAP, так как SDK не содержит в себе стандартные RPC функции. Так как ОС Андроида не позволяет процессам «зависать», удаленные вызовы лучше выполнять асинхронно в отдельных потоках.

Особо нужно отметить сервис Google Talk. В Андроиде этот XMPP сервис позволяет разработчику передавать в сообщениях от одного абонента другому не только текст, но и организовывать пиринговую сеть с помощью вашего приложения. В последнем релизе, правда, разработчикам был ограничен доступ к этрому сервису. В манифесте приложения нужно заявить свой класс IntentReceiver для получения сообщений, поступающих из P2P сети. Для меня не совсем, правда, понятно, какой процент устройств Андроид будут иметь свой аккаунт в GoogleTalk. Очевидно, что насильно заставлять пользователей открывать аккаунт нельзя, особенно с учетом того обстоятельства, что телефон в большой пиринговой сети может просто не справиться с нагрузкой, например, в P2P сети для обмена снятым на камеру видео. Я полагаю, что Google будет каким то образом пытаться контролировать пиринговые сети через свой сервис, потому что, с одной стороны, пиринг может дискредитировать компанию, а с другой стороны, упустить его возможности, тоже нельзя.

Большинство пользовательских приложений визуальные, но иногда нужно иметь фоновые задачи. В SDK Андроид демоны пишутся также на Java, с их помощью можно периодически отсылать, например, координаты ребенка на телефон родителя и по сигналу от родителя задействовать камеру.

Новое осмысление процессов

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

Функция определения географических координат тоже внесет лепту в развитие веб сервисов. Зная положение абонента, сервис становится ближе к нему и, в первую очередь, это касается рекламы. Для примера, если абонент находится в океанариуме, то электронная книга от Amazon предложит ему книги про рыб, пока он находится под впечатлением от уведенного. Кажется, что опасения насчет назойливости рекламы несколько преувеличены, просто она станет более целевой. Зайдя в торговый центр, реклама может проложить долгий маршрут к нужной полке, где размещен искомый товар.

Так как Андроид открыт, относительно нетребователен к вычислительным ресурсам, его можно встроить в другие устройства, не обязательно телефоны- киоски, кард ридеры, кассовые терминалы, пропускные системы, копировальные аппараты и аппараты печати фотографий, бытовую технику и другие встроенные системы. В консорциум OHA входит один из крупнейших производителей микросхем для сотовой телефонии и бытовой техники Texas Instruments, а также Quallcomm и Samsung Electonics, так что рано или поздно появятся другие встраиваемые системы на базе Андроида. Если Андроид получит определенное распространение среди разработчиков, греющимся под солнцем Sun, то появится смысл замещать существующие средства разработки для некоторых встраиваемых систем Андроидом.

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

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

Я полагаю, что процесс специализации продолжается, и будут востребованы не универсальные инструменты, а узкоспециализированные нуль-администрируемые устройства, как это произошло ранее с вытеснением мейнфреймов ПК, а сейчас происходит с сетевыми устройствами- маршрутизаторы, сетевые устройства хранения и сетевые принтеры вытесняют универсальные машины с unix, выступающие в качестве шлюзов, файл-серверов и серверов печати. Поэтому можно скептически отнестись к тому, что Андроид переломит отношение к мобильному устройству только как к телефону, для некорпоративных пользователей.

Открытость платформы Андроида призвано, в первую очередь, привлечь корпоративных пользователей, ведь на его базе можно создать целей спектр новых специализированных устройств с беспроводным доступом. Очевидно, что именно для корпоративного рынка сейчас следует ожидать роста числа приложений.
Для корпоративных разработчиков здесь, возможно, откроется новое поле для деятельности. Ранее мобильные устройства как то выпадали из сферы интересов ИТ отделов, теперь, с возможностью включения их в вычислительную сеть предприятия, можно ожидать постепенного увеличения к ним интереса, начиная с инструментария для специалистов ИТ в виде, например, консолей управления сетевыми устройствами. Для успешности новой платформы всегда важно, видят ли ИТ специалисты ее преимущества. Я полагаю, что, ИТ специалисты стремятся к замене оборудования с высокой стоимостью владения (CTO) на оборудование с низкой CTO, а говоря проще, готовы дать пользователям нуль-администрируемые устройства, на жаргоне называемые железками, тем самым уменьшая количество походов к пользователям для настройки ПО.
В идеале, специализированное устройство с Андроидом- это пресловутая большая красная кнопка, нажав на которую, пользователь получает ожидаемый результат. И теперь, наконец то, можно, поэкспериментировав с телефоном, начать изготавливать такие кнопки на базе какого нибудь набора с Андроидом.

Устройства Андроид могут с успехом применяться в устройствах, автоматизирующих рутинные процессы, например, в складском учете или приеме заказов и в бытовой технике. Наличие беспроводного доступа позволит быстро подключать устройства к Интернет через WiFi хотспоты, установленные в торговых центрах. Эта простая возможность может оказать сильное влияние на ускорение процесса централизации ИТ ресурсов в сбытовой цепочке.

Если устройство с Андроидом будет снабжено камерой, то, например, можно сделать из него сканер штрих-кода для склада или супермаркета. Тогда, зайдя в книжный магазин, можно будет просканировать штрих код ISBN и посмотреть отзывы других читателей на заинтересовавшую книгу или узнать, что в Amazon такую же книгу можно купить дешевле.

Вообще, существует ряд направлений, которые не слишком успешно автоматизируются с помощью ПК. Например, небольшие зубоврачебные кабинеты- дантисту, стоя у кресла, просто неудобно пользоваться ПК. Тут будет к месту ЖК панель с Андроидом, вмонтированная в кресло, которая позволит не только просматривать снимки, но и связываться с поставщиком расходных материалов для пополнения. Более общо, стоит посмотреть вокруг и найти предприятия, в котором сотрудники не сидят за ПК весь день, или где обслуживаемые ими объекты находятся в разных точках города- наружная реклама, доставка, транспорт.

Что касается независимых разработчиков (ISV), им Google предлагает приложить усилия на ниве социальных сетей, то есть, преимущественно, предлагать новые виды коммуникации в группах пользователей, собирающихся вокруг какого нибудь сервиса.
Очевидно, что пользователи социальных сетей вряд ли будут готовы оплачивать услуги самой сети, скорее будут приобретать смежные (рекламируемые) услуги, и, получается, социальная сеть будет участвовать в контекстной рекламе Google. Интерес представляет и сам сервис, вокруг которого может быть построена группа пользователей. Многие предприятия сейчас стараются привлечь потребителей, используя различные социальные техники. Например, российская компания ICS разрабатывает прототип open-source приложения (http://meetup.sf.net/) для поиска услуг и назначения времени приема в клиниках и присутственных местах поблизости от абонента, находить предложения по продаже автомобилей и недвижимости, временной работы, гаражных распродажах. Полезной функцией для абонента является то, что приложение согласует свободное время, когда абоненты договариваются о встрече.

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

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

Логотип Андроида напоминает ремонтного дроида R2 из Звездных войн, в фильме герои использовали его не по назначению, а в качестве коммуникатора. Его же напарник, дроид-коммуникатор, в общем-то оказывался бесполезным. В этом видится намек на то, что Андроиду надо быть больше, чем просто коммуникатором, чтобы быть коммуникатором.

Снимки экранов приложения inventory

Screenshot 1. Appliaction after first startТак выглядит приложение сразу после первого запуска.

Screenshot 1. Enter data then press "Save" buttonВведем одну запись в базу данных.

Screenshot 3. Open application again and enter number then press "Search" buttonТеперь проверим, добавлена ли запись.

Screenshot 4. Delete record - enter number and press "Delete" buttonТеперь запись можно удалить.

 

Ссылки:

Скачать архив примера

Страница Meetup

Страница Meetup на SourceForge