Пишем софт для телефона


1. Технология J2ME

Ситуация, сложившаяся сегодня в мире мобильного программирования во многом напоминает обстановку конца 80-х, когда на рынке ПК существовало несколько практически несовместимых между собой устройств. Стараясь выжать из железа максимум и как можно быстрее запустить в продажу новые модели, производители не особо заботятся даже о совместимости собственных устройств, что уж говорить о совместимости между устройствами разных производителей. Когда мобильные телефоны являлись просто средством коммуникации, несовместимость не вызывала особых проблем. С течением времени телефоны стали превращаться в сложные функционально насыщенные устройства. Возникла потребность в разнообразном и качественном софте. Осознавая, что сторонние разработчики не будут тратить время на написание программы для единственной модели телефона, производители стали создавать платформы, позволяющие запускать одну и ту же программу на различных устройствах. В настоящее время существует несколько решений, но в России по настоящему большое распространение получила только Java 2 Platform Micro Edition (J2ME).

Основная идея J2ME проста: программист компилирует программу в промежуточный код, который затем выполняется специальным эмулятором – виртуальной Java машиной (VJM). VJM выступает посредником между программой и прошивкой телефона. Таким образом, основную часть работы по адаптации приложений к конкретной модели берет на себя производитель. Кроме того, VJM решает проблему безопасности, поскольку приложения не имеют прямого доступа к памяти и ресурсам телефона.

На практике VJM разных производителей не всегда выдают одинаковый результат. Из других недостатков J2ME можно отметить неспособность ее работать с вещественными числами (не актуально для CDLC 1.1), а также проблему с исходными кодами. Поскольку в результате компиляции получаются промежуточный, а не машинный код, он легко может быть переведен обратно в java исходник.

2. Рабочая среда

Для того чтобы начать разрабатывать мидлеты (так принято называть J2ME приложения для мобильных телефонов) Вам необходимы три вещи:

  • Java 2 Standard Edition (J2SE) SDK version 1.4.2 или выше - компилятор и утилиты для создания Java архивов;
  • J2ME Wireless Toolkit (WTK) 2.2 - набор утилит и эмуляторов для создания и отладки мидлетов;
  • текстовый редактор или IDE.

Все эти компоненты абсолютно бесплатны и доступны по адресам: http://www.oracle.com/technetwork/java/javame/javamobile/download/sdk/index.html, www.netbeans.org. (При использовании SDK версии 3 и выше в установке WTK нет необходимости)

2.1 Создание нового проекта

Запустите WTK KToolbar. Для создания нового проекта выберите пункт меню File>New Project. В появившемся окне заполните поля "Project Name" и "MIDlet Class Name". Введите, например, SampleSuite и SampleMIDlet. После заполнение этих полей Вам будет предложено настроить параметры проекта. Ничего не меняйте, просто нажмите кнопку OK. В папке [WTK]\apps\ будет создан новый каталог SampleSuite. Каждый проект содержит стандартный набор каталогов:

  • bin - сюда попадают .jar и .jad файлы после упаковки проекта;
  • lib - сюда следует поместить файлы подключаемых библиотек;
  • res - файлы ресурсов (например, .png, .txt);
  • src - файлы .java с исходным текстом программы;

Название .java файла должно соответствовать имени расположенного внутри него класса. Не забудьте, что язык Java чувствителен к регистру букв.

2.2 Открытие и запуск примера

После написания кода программы, как правило, наступает этап тестирования. Сначала приложение отлаживается на эмуляторе, а затем непосредственно на телефоне. Давайте откроем один из стандартных примеров (например, UIDemo). Чтобы запустить проект в окне эмулятора, нужно его откомпилировать (кнопка Build), а затем нажать Run на панели инструментов.

Для переноса приложения на телефон, необходимо его упаковать. Для этого после компиляции надо выбрать пункт меню Project>Package. В папке bin проекта появятся файлы .jar и .jad. Файл jar является Java архивом, содержащим файлы проекта, а jad - так называемым дескриптором приложения. Дескриптор содержит вспомогательную информацию о классах архива. Эта информация используется телефоном для эффективного управления ресурсами. Именно эти два файла нужно копировать в телефон.

3. Простейшее приложение

Особенностью программной модели мидлета является возможность вмешательства операционной системы в ход выполнения программы. Работа приложения может быть в любой момент прервана каким-нибудь внешним событием, например входящим телефонным звонком. Это обстоятельство требует постоянного контроля системы над ходом выполнения программы. Реализуется этот контроль с помощью специального управляющего софта, называемого AMS (Application-Management Software).

Каждый Java программист знает, что работа программы начинается с запуска метода main(). В J2ME этот метод недоступен. Вместо него предлагается использовать startApp().

Запущенное приложение может находиться в трех возможных состояниях: paused: мидлет запущен, но не активен; active: мидлет активен и destroyed: мидлет остановлен и готов к завершению.

Рассмотрим жизненный цикл мидлета. Сразу после запуска он находится в состоянии paused. Прежде чем перейти в активный режим, он должен выполнить инициализацию. Мидлет не имеет специального инициализационного метода и все необходимые действия выполняются внутри startApp(). Через некоторое время после запуска программы, AMS вызывает метод startApp(), в результате приложение переходит в состояние active. Если при запуске возникли какие-нибудь ошибки, управление передается методу javax.microedition.midlet.MIDletStateChangeException, который переводит мидлет в состояние destroyed.

В любое время AMS может прервать выполнение мидлета и перевести его в состояние paused. При этом AMS вызывает метод pauseApp(). Для того чтобы перевести приложение в состояние destroyed и закрыть его, AMS вызывает метод destroyApp().

Мидлет не способен перевести сам себя из одного состояния в другое. Он может только послать соответствующий запрос AMS, воспользовавшись одним из методов: notifyDestroyed() - запрос на завершение работы; notifyPaused() - запрос на дезактивацию и переход в состояние паузы; resumeRequest() - запрос на реактивацию и переход в активное состояние. AMS решает, нужно ли удовлетворить запрос, и если нужно, то когда это сделать. После запроса resumeRequest() ASM вызывает метод startApp(). В ответ на notifyPaused() и notifyDestroyed() AMS напрямую переводит мидлет в требуемое состояние.

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

//файл SampleMIDlet.java
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
 
publicclass SampleMIDletextends MIDlet{
private Display display;
public SampleMIDlet(){}
 
protected void destroyApp( boolean unconditional) throws MIDletStateChangeException
{
exitApp();// вызывает уборщик мусора
}
 
protected void pauseApp()
{
// Сюда следует добавить код, который надо выполнять непосредственно
// перед переводом приложения в режим паузы.
}
 
protected void startApp() throws MIDletStateChangeException
{
if( display==null)
{
// Этот код выполняется при запуске мидлета
initApp();
}
// Сюда следует добавить код, который надо выполнять непосредственно
// перед переводом приложения в активный режим.
}
 
private void initApp()
{
display= Display.getDisplay( this);
// Сюда добавляется код инициализации приложения
}
 
public void exitApp()
{
// Сюда следует добавить код, который будет выполняться
// при закрытии приложения.
notifyDestroyed();// уничтожение MIDlet-а
}
}

4. Пользовательский интерфейс высокого уровня

В состав J2ME входит пакет javax.microedition.lcdui, в котором реализованы классы пользовательского интерфейса. Принято различать низкоуровневые и высокоуровневые классы. В рамках данной статьи мы рассмотрим только последние. Программы, написанные с использованием только высокоуровневого интерфейса, практически не требуют адаптации при переносе на различные модели телефонов.

Разработка программ на основе высокоуровневого интерфейса сводятся к двум этапам: созданию окон и настройке команд.

4.1 Создание окон

Высокоуровневый интерфейс определяет четыре типа окон: Alert, TextBox, List и Form.

Alert - окно служебных сообщений. При создании требует четыре параметра: заголовок окна, текстовое сообщение, рисунок и тип сообщения (ALARM, CONFIRMANTION, ERROR, INFO, WARNING). С помощью метода setTimeout можно установить время (в миллисекундах), через которое окно будет закрыто.

Alert myAlert=new Alert("Заголовок сообщения","сообщение",image,AlerType.ALARM);
myAlert.setTimeout(1000);
 
 

TextBox - окно-редактор текста. При создании требует, чтобы ему передали заголовок, начальный текст, максимальный размер текста и ограничения. В качестве ограничений можно использовать константы: ANY - ограничений на текст нет, EMAILADDR - ввод e-mail адресов, NUMERIC - ввод чисел, PASSWORD - ввод пароля, PHONENUMBER - ввод телефонных номеров, URL –ввод URL адресов.

Для получения введенного текста можно воспользоваться либо методом getChars(char[] chAr), который записывает текст в переданный массив символов chAr; либо getString(), который возвращает строку. С помощью метода size() можно узнать размер введенного текста.

TextBox myTb=new TextBox("Введите текст","",255,TextBox.ANY);
...
String strRes=myTb.getString();

List - окно-список элементов. При создании список требует четыре параметра: заголовок списка, тип списка, массив строк и массив картинок для элементов списка. Два последних параметра можно опустить, но тогда для формирования списка нужно использовать метод append(String str, Image img).

В J2ME реализованы четыре типа списков. Тип EXCLUSIVE предназначен для пометки одного элемента из списка (соответствует TRadioButton в Delphi); MULTIPLE предназначен для пометки нескольких элементов (соответствует TCheckBox); IMPLICIT позволяет выбрать один элемент из списка (cоответствует TListBox).

Чтобы узнать, какие элементы выбрал или пометил пользователь, нужно воспользоваться одним из следующих методов. getSelectedIndex() - возвращает номер выбранного элемента. getSelectedFlags(boolean[] selArr) - записывает в переданный массив selArr состояние всех элементов списка.

String st={"Элемент 1","Элемент 2","Элемент 3"};
List myList=newList("Элементы",Choice.IMPLICIT,st,null);
...
int index=myList.getSelectedIndex();

Form. Форма - это контейнер, куда можно помещать различные визуальные элементы управления. Если элементы формы не умещаются на экране телефона, создается вертикальная полоса прокрутки. Для добавления элемента на форму используется метод append(). В качестве единственного параметра ему нужно передать либо строку, либо картинку, либо один из визуальных компонентов класса Item.

ChoiceGroup - группа элементов для выбора. Этот элемент аналогичен List. Как и List он позволяет создавать EXCLISIVE и MULTIPLE списки. Вместо типа IMPLICIT нужно использовать POPUP, который создает список в виде выпадающего меню.

DateField - элемент предназначен для установки даты и времени. При создании требуется передать три параметра: заголовок, режим даты (DATE, TIME или DATE_TIME) и часовой пояс. Последний параметр можно опустить.

TextField - поле для ввода текста. Этот элемент очень похож на TextBox, но, в отличие от последнего, не занимает весь экран.

StringItem - элемент предназначен для добавления на форму статических строк текста, кнопок и гиперссылок. При создании требуется передать три параметра: строку-метку, строку текста и форматирование текста. В качестве последнего параметра используются константы: BUTTON - для создания кнопки, HYPERLINK - для гиперссылки, LAYOUT_BOTTOM, LAYOUT_CENTER, LAYOUT_TOP, LAYOUT_LEFT, LAYOUT_RIGHT - для определения положения текста на экране.

Spacer - элемент предназначен для создания свободного пространства указанного размера. Используется для позиционирования других элементов на форме. В качестве параметров при создании задаются ширина и высота области.

ImageItem - элемент предназначен для размещения изображения на форме. При создании требуется передать пять параметров: текст над рисунком, объект класса Image с загруженным рисунком, расположение рисунка (LAYOUT_LEFT, LAYOUT_RIGHT, LAYOUT_CENTER), текст под рисунком и форматирование. Последний параметр аналогичен рассмотренному в StringItem и также может быть опущен.

J2ME гарантированно умеет работать с рисунками в формате PNG. Все рисунки проекта должны быть расположены в папке res. Код загрузки и использования рисунка нужно обязательно помещать в try{…}catch{…} скобки, в противном случае при сборке проекта возникнут ошибки. Для загрузки изображения из файла используется метод Image.createImage("/файл.png").

Guage - элемент для отображения полос состояния. При создании требуется передать три параметра: метку, флаг типа boolean, указывающий на то должна ли полоса быть интерактивной; значение, соответствующее заполненной полосе, и начальное значение. Для установки текущего положения используется метод setValue(int value).

Помимо указанных элементов, под заголовком окон TextBox, List и Form можно поместить бегущую строку с текстом. Для этого нужно создать объект класса Tricker и вызвать метод setTricker окна, указав в качестве параметра созданный объект.

ChoiceGroup myCG=new ChoiceGroup("Элементы",Choice.POPUP);
DateField myDF=new DateField("Дата и время",DateField.DATE_TIME);
TextField myTF=new TextField("Введите текст","",20,TextField.ANY);
StringItem mySI1=new StringItem("Ф.И.О.","Иванов Иван Иванович");
StringItem mySI2=new StringItem("URL",
"www.MobiLab.ru",Item.HYPERLINK);
StringItem mySI3=new StringItem("OK","", Item.BUTTON);
Spacer mySp=new Spacer(50,0);
Gauge myG=new Gauge("Идет процесс",true,100,45);
try{
Image img=Image.createImage("/mobilab.png");
ImageItem myII=new
ImageItem("Логотип",img,ImageItem.LAYOUT_CENTER,"www.mobilab.ru");
myForm.append(myII);
}catch(java.io.IOException ex){}
myForm.append(myCG);
myForm.append(myDF);
myForm.append(mySp);
myForm.append(myTF);
myForm.append(mySp);
myForm.append(mySI1);
myForm.append(mySI2);
myForm.append(mySI3);
myForm.append(myG);
Tricker myTR=new Tricker("Это бегущая строка...");
myForm.setTricker(myTR);

4.2 Создание и настройка команд

Для перехода между окнами используется метод Display.setCurrent(Displayable d). Обычно переход выполняется после какого-то действия пользователя. Для настройки реакции на действие, необходимо: 1. создать команду;
2. связать ее с экраном или элементом управления;
3. связать с экраном или элементом класс, реализующий обработчик событий;
4. внутри метода commandAction запрограммировать реакцию на данную команду;

Для создания команды необходимо создать объект класса Command

private Command MyCommand=new Command("Моя команда",Command.SCREEN,2);

Первый параметр определяет строковое представление команды, второй - тип команды, третий - ее приоритет. В качестве типа используется одна из: BACK, CANCEL, EXIT, HELP, ITEM, OK, SCREEN, STOP. Тип команды лишь указывает ее предполагаемое назначение и не влияет на функциональность.

Для связи команды с экраном используется метод Displayable.addCommand(Command cmd), а для связи с элементом управления - Item.setDefaultCommand(Command cmd).

Если с экраном связаны две команды, то для них создаются соответствующие подэкранные кнопки. Если команд больше, то для одной из них создается кнопка, а остальные помещаются в меню, вызываемое при нажатии второй кнопки. Система решает, какую из команд поместить на экран, ориентируясь на их тип. Например, если среди команд есть команда типа EXIT, то именно с ней будет связана подэкранная кнопка.

Класс может обрабатывать команды, только если он реализует интерфейсы CommandListener и ItemCommandListener:

publicclass Navigatorextends MIDlet implements CommandListener, ItemCommandListener{}

Для связи обработчика с экраном используется метод Displayable.setCommandListener(CommandListener cl); для связи с элементом формы - Item.setItemCommandListener(ItemCommandListener cl). В качестве параметра нужно указать объект, реализующий обработчик событий. Если обработка команд выполняется внутри класса, откуда вызывается метод, то в качестве параметра можно использовать слово this.

При выполнении команды система вызывает метод commandAction(Command c, Displayable d) для окна и commandAction(Command c, Item i) для элементов формы. Вызвавшая метод команда передается в параметр c. Внутри этого метода необходимо идентифицировать команду и написать код ее обработки:

//Обработка команд от окна.
public void commandAction(Command c, Displayable d){
if(c==command1){
//Сюда помещаем код, выполняющийся при
//возникновении команды command1
}
if(c==command2){...}
...}
 
//Обработка команд от формы
public void commandAction(Command c, Item i){
if(c==comForm1){
//Сюда помещаем код, выполняющийся при
//возникновении команды comForm1
}
...}

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

Исходники (250Kb)

Александр Ледков
Мпр ПК 2006 №2




Наши соцсети

Подписаться Facebook Подписаться Вконтакте Подписаться Twitter Подписаться Google Подписаться Telegram

Популярное

Ссылки

Новости [1] [2] [3]... Android/ iOS/ J2ME[1] [2] [3]) Android / Архив

Рейтинг@Mail.ru Яндекс.Метрика
MobiLab.ru © 2005-2018
При использовании материалов сайта ссылка на www.mobilab.ru обязательна