Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторные работы. Мобильные устройства.doc
Скачиваний:
2
Добавлен:
01.05.2019
Размер:
1.8 Mб
Скачать

Содержание

Лабораторная работа № 1 10

Wireless Development Tutorial Часть 1 10

Wireless Development Tutorial Часть 2 14

Лабораторная работа №2 21

Работа с сетью в J2ME - Generic Connection Framework (GCF) API. Сокеты, дейтаграммы, HTTP 21

Лабораторная работа №3 27

Использование Bluetooth в J2ME приложениях. (JSR-82) - Часть 1. Знакомство с технологией Bluetooth и Java API for Bluetooth 27

Использование Bluetooth в J2ME приложениях. (JSR-82) - Часть 2. Обзор Connection и Device Management API 31

Лабораторная работа №4 38

JSR 75. Часть 1 - Personal Information Management (PIM) API. Работа с личными данными 38

Лабораторная работа №5 43

JSR75 - Часть 2. Работа с файловой системой телефона 43

Лабораторная работа №6 47

Вычисление математических функций в j2me (exp, ln, log, arcsin, arccos, arctn, power, root) 47

Лабораторная работа №7 52

Работа со звуком и видео в J2ME MIDP 2.0. Библиотека Mobile Media API (MMAPI) 52

Mobile Media API (MMAPI) - дополнительный пакет, который поддерживается мультимедийными устройствами. Стандартная Java спецификация, заданная в JSR 135, отличается своей гибкостью. Она рассчитана на работу с произвольными протоколами и форматами. 52

В данной лабораторной работе рассматривается техническая реализация архитектуры MMAPI и ее практическое использование. 52

Обзор MMAPI 52

В профиле MIDP 1.0 отсутствовала возможность работы со звуком, поэтому приходилось полагаться на нестандартные классы, предлагаемые производителями мобильных телефонов. С появлением MIDP 2.0 эта проблема исчезла, поскольку в его состав входит мультимедиа библиотека MMAPI. 52

MMAPI имеет следующие особенности: 52

Поддерживает генерацию тонов, воспроизведение и запись Time-Based медиа информации. Пакет поддерживает любой time-based аудио или видео контент. 52

Скромные системные требования. MMAPI рассчитан на рабату в жестких условиях мобильных устройств. 52

Безразличие к протоколам и форматам. MMAPI не заточен под конкретный протокол и формат. 52

Разработчики могут ориентироваться на ограниченную часть типов контента. 52

Расширяемость. Новые возможности могут быть добавлены без необходимости переделывать старые функции. Легко добавляются новые форматы и механизмы управления средой. 52

Механизм обработки мультимедмйной информации 52

Обработка мультимедмйной информации делится на две части: 52

Обработка протокола: чтение данных из различных источников, например из файлов или сервера потока данных в систему обработки мультимедийной информации. 52

Обработка формата: разбор или декодирование полученных данных; предоставление их в понятном формате устройствам вывода (спикеру или дисплею). 52

Для облегчения этих операций API предоставляет два типа объектов высокого уровня: 52

DataSource реализует обработку протокола, скрывая подробности чтения данных из источника. Сервисные методы этого объекта дают возможность объекту Player обрабатывать контент. 52

Player получает данные от DataSource, обрабатывает их, переводит в формат, понятный устройствам вывода. Этот объект содержит методы управления воспроизведением. 52

MMAPI определяет еще один объект Manager. С его помощью ваше приложение может создавать объект Player на основании DataSources, и DataSources на основании InputStreams. 52

Для создания объекта Player необходимо вызвать метод Manager.createPlayer(String url). Параметр URL определяет протокол и формат. Он имеет вид: протокол:источник. 52

Приложение может использовать методы объекта Player для управления воспроизведением time-based медиа информацией. 52

Player может находиться в пяти состояниях: UNREALIZED, REALIZED, PREFETCHED, STARTED и CLOSED. После создания, Player находится в состоянии UNREALIZED. Вызов метода realize() переводит его в состояние REALIZED и инициализирует информацию необходимую player-у для получения медиа ресурсов. Метод prefetch() переводит его в состояние PREFETCHED. На этом этапе формируется соединение с потоком данных и производится закачка всех необходимых файлов. Вызов start() переводит плеер в режим STARTED, с этого момента начинается воспроизведение. Когда обработка данных завершается (достигнут конец потока данных), Player переходит в режим PREFETCHED. Вызов метода close() переводит Player в состояние CLOSED. 52

Помимо указанных выше методов, Player имеет еще несколько: 53

getState() - возвращает текущее состояние проигрывателя. 53

setLoopCount( int ) - устанавливает число повторов при воспроизведении звука. 53

getDuration() - возвращает длительность звука в миллисекундах. 53

getMediaTime() - возвращает текущее время воспроизведения в миллисекундах. 53

setMediaTime( int) - устанавливает текущее время воспроизведения в миллисекундах. 53

getCountType() - возвращает тип воспроизводимых звуковых данных. 53

dellocate() - освобождает ресурс, занятый проигрывателем. 53

Player позволяет осуществлять управление обрабатываемыми данными. Для этого используются методы getControl() (для определения типа управления) и getControls() (для получения управления). Например, при обработке MIDI информации вызов getControl() вернет MIDIControl. 53

MMAPI пакеты 53

В состав MMAPI входят три пакета: 53

javax.microedition.media - здесь определено несколько интерфейсов и исключение, а также класс Manager. 53

javax.microedition.media.control - определяет типы управления, которые может использовать Player, например VolumeControl или VideoControl. 53

javax.microedition.media.protocol - определяет протоколы и класс DataSource. 53

В приведенных ниже таблицах описаны классы, интерфейсы и исключительные ситуации, входящие в состав MMAPI. Будем использовать следующие сокращения: 53

(M) - javax.microedition.media 53

(C) - javax.microedition.media.control 53

(P) - javax.microedition.media.protocol 53

Таблица 1 – Классы 53

Таблица 2 – Интерфейсы 53

Таблица 3 - Исключительные ситуации 54

Поддержка того или иного протокола и формата зависит от конкретного телефона. Чтобы получить список всех доступных протоколов и форматов необходимо воспользоваться методами Manager.getSupportedContentTypes() и Manager.getSupportedProtocols(). 54

Использование MMAPI 54

Ниже будет приведен код, показывающий использование MMAPI. Мы будем рассматривать стандартный пример, входящий в WTK: /wtk20/apps/mmademo. 54

Последовательности нот 54

Метод Manager.playTone() используется для генерации тонального звука. Вы должны передать ему требуемую ноту, ее длительность и громкость: 54

.. 54

try { 54

// Играть ноту C4 ("До") 4000 миллисекунд с громкостью 100 единиц (диапазон громкости от 0 до 100). 54

Manager.playTone()(ToneControl.C4, 4000, 100); 54

} 54

catch(MediaException me) { 55

} 55

... 55

Кроме того, Вы можете создать плеер для синхронизации с последовательностью нот. 55

... 55

Player player = 55

Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR); 55

player.realize(); 55

ToneControl tc1=(ToneControl)player.getContril("ToneControl"); 55

//Подключаем последовательность нот, указанных в массиве Nots 55

tc1.setSequence(Nots); 55

player.start(); 55

... 55

Последовательность нот должна быть задана в следующем виде: 55

byte[] Nots={ 55

ToneControl.VERSION, 1, //версия используемого атрибута 55

ToneControl.TEMPO, speed, //темп мелодии. Переменная speed = 5-127 55

ToneControl.BLOCK_START, 0, //начало блока 0 55

ToneControl.С4, 4 //Нота До продолжительностью 4 (можно от 2 до 16) 55

ToneControl.SILENCE, 4 //Пауза продолжительностью 4 55

ToneControl.С4+1, 4 //Нота До# продолжительностью 4 55

ToneControl.SILENCE, 4 //Пауза продолжительностью 4 55

ToneControl.С4+2, 4 //Нота Ре продолжительностью 4 55

ToneControl.SILENCE, 4 //Пауза продолжительностью 4 55

... 55

... 55

ToneControl.С4+12, 4 //Нота До следующей октавы 55

ToneControl.BLOCK_END, 0, //конец блока 0 55

ToneControl.PLAY_BLOCK, 0} //воспроизведение блока 0 55

Этот тип плеера создает ToneControl, который можно использовать для программирования последовательности нот. Эта возможность доступна только на мощных устройствах. 55

Проигрывание мультимедийных файлов 55

Приведенный ниже пример показывает, как воспроизвести простой mp3 файл без использования контроля. 55

... 55

try { 55

Player p = Manager.createPlayer 55

("http://server/somemusic.mp3"); 55

p.setLoopCount(5); 55

p.start(); 55

} 55

catch(IOException ioe) { 55

} 55

catch(MediaException e) { 55

} 55

... 55

Аналогичным способом можно воспроизводить wav и midi файлы. 55

В приведенном ниже коде добавлена возможность управления: 55

... 55

Player p; 55

VolumeControl vc; 56

try { 56

p = Manager.createPlayer("http://server/somemusic.mp3"); 56

p.realize(); 56

// получаем доступ к управлению громкостью и устанавливаем ее на полную мощность. 56

vc = (VolumeControl) p.getControl("VolumeControl"); 56

if(vc != null) { 56

vc.setVolume(100); 56

} 56

// плеер запускается с минимальным временем ожидания 56

p.prefetch(); 56

// неблокируемый запуск 56

p.start(); 56

} 56

catch(IOException ioe) { 56

} 56

catch(MediaException e) { 56

} 56

... 56

Поскольку Manager.createPlayer() можно передавать любой InputStream, ваше приложение может проигрывать информацию, сохраненную в MIDP Record Management System (RMS), или находящуюся внутри JAR архива. В приведенном ниже примере показано, как получить InputStream из RMS и воспроизвести эту информацию. 56

... 56

RecordStore store; 56

int id; 56

// воспроизведение из RMS 56

try { 56

InputStream is = new ByteArrayInputStream(store.getRecord(id)); 56

Player player = Manager.createPlayer(is, "audio/X-wav"); 56

p.start(); 56

} 56

catch (IOException ioe) { 56

} 56

catch (MediaException me) { 56

} 56

... 56

Обратите внимание на строчку Player player = Manager.createPlayer(is, "audio/X-wav"). Если Вы хотите проигрывать midi файл, необходимо указать другой MIME тип: "audio/midi". 56

Ниже приведен пример, проигрывающий wav файл, входящий в состав JAR архива. 56

... 56

try { 56

InputStream is = getClass().getResourceAsStream("audio.wav"); 56

Player player = Manager.createPlayer(is, "audio/X-wav"); 56

p.start(); 56

} 56

catch(IOException ioe) { 56

} 56

catch(MediaException me) { 56

} 56

... 57

Воспроизведение видео 57

Приведенный ниже код показывает, как организовать воспроизведение MPEG видео. 57

... 57

Player p; 57

VideoControl vc; 57

try { 57

p = Manager.createPlayer("http://server/somemovie.mpg"); 57

p.realize(); 57

// Получаем управление для видео 57

vc = (VideoControl) p.getControl("VideoControl"); 57

.... 57

p.start(); 57

} 57

catch(IOException ioe) { 57

} 57

catch(MediaException me) { 57

} 57

... 57

Использование камеры 57

MMAPI обеспечивает поддержку встроенной камеры. Для ее использования при создании плеера нужно задать параметр capture://video . Для управления используется VideoControl, например, для получения картинки с камеры нужно вызвать метод VideoControl.getSnapshot(String imageType). По умолчанию картинка возвращается в формате PNG. Вы можете использовать параметр imageType, чтобы выбрать другой доступный формат. Доступные форматы можно узнать, получив значение системного параметра video.snapshot.encodings. 57

J2ME Wireless Toolkit и MMAPI 57

J2ME Wireless Toolkit 2.0 поддерживает MMAPI. Среди входящих в его состав примеров есть программы, использующие MMAPI. Вы прямо сейчас можете открыть пример mmademo и запустить его. Обратите внимание, в mmademo воспроизведение некоторых файлов требует подключения к интернету. 57

Поддерживаемые форматы 57

2ME Wireless Toolkit поддерживает следующие форматы 57

Audio: PCM и WAV 57

MIDI: Type 0 (single track), Type 1 (multiple tracks) и SP-MIDI 57

Video: MPEG-1 57

Ограничения использования MMAPI в WTK 57

Имейте в виду, что J2ME Wireless Toolkit имеет следующие ограничения (Помните о том, что каждое конкретное устройство имеет свои собственные ограничения): 57

Хотя вы можете создать в приложении несколько различных плееров, в данный момент времени может использоваться только один MIDI плеер. В противном случае возникнет ошибка MediaException. 57

WTK позволяет одновременно вызвать любое количество playTone(), однако, гарантированно будут воспроизведены только четыре ноты. Метод playTone() можно вызывать во время воспроизведения MIDI последовательности. 57

Число видео плееров ограничено размером динамической памяти и задается в параметре Xheapsize команды emulator (если Вы вызываете эмулятор из командной строки) или в пункте меню KToolBar Edit -> Preferences -> Storage 57

Число WAV аудио плееров также ограничено размером динамической памяти. 57

В данный момент времени может воспроизводиться только один аудио файл. 58

Кроме того, WTK ограничивает число одновременно открытых HTTP соединений (не более четырех). 58

Пример простого медиаплеера 58

Чтобы не быть голословным я написал небольшой пример медиаплеера, использующего Mobile Media API. PlayerMIDlet позволяет проигрывать файлы, загруженные из сети. Для этого необходимо указать их URL. 58

import javax.microedition.lcdui.*; 58

import javax.microedition.media.*; 58

import javax.microedition.media.control.*; 58

import javax.microedition.midlet.*; 58

public class PlayerMIDlet extends MIDlet implements 58

CommandListener, PlayerListener, Runnable { 58

private Display display; 58

private Form form; 58

private TextField url; 58

private Command start = new Command("Play", 58

Command.SCREEN, 1); 58

private Command stop = new Command("Stop", 58

Command.SCREEN, 2); 58

private Player player; 58

58

public PlayerMIDlet() { 58

display = Display.getDisplay(this); 58

form = new Form("Demo Player"); 58

url = new TextField("Enter URL:", "", 100, TextField.URL); 58

form.append(url); 58

form.addCommand(start); 58

form.addCommand(stop); 58

form.setCommandListener(this); 58

display.setCurrent(form); 58

} 58

protected void startApp() { 58

try { 58

if(player != null && player.getState() == Player.PREFETCHED) { 58

player.start(); 58

} else { 58

defplayer(); 58

display.setCurrent(form); 58

} 58

} 58

catch(MediaException me) { 58

reset(); 58

} 58

} 58

protected void pauseApp() { 58

try { 58

if(player != null && player.getState() == 58

Player.STARTED) { 58

player.stop(); 59

} else { 59

defplayer(); 59

} 59

} 59

catch(MediaException me) { 59

reset(); 59

} 59

} 59

protected void destroyApp( 59

boolean unconditional) { 59

form = null; 59

try { 59

defplayer(); 59

} 59

catch(MediaException me) { 59

} 59

} 59

public void playerUpdate(Player player, 59

String event, Object data) { 59

if(event == PlayerListener.END_OF_MEDIA) { 59

try { 59

defplayer(); 59

} 59

catch(MediaException me) { 59

} 59

reset(); 59

} 59

} 59

public void commandAction(Command c, Displayable d) { 59

if(c == start) { 59

start(); 59

} else if(c == stop) { 59

stopPlayer(); 59

} 59

} 59

public void start() { 59

Thread t = new Thread(this); 59

t.start(); 59

} 59

// Для предотвращение блокировки, все действия 59

// по работе с сетью должны выполняться 59

// в отдельном потоке, а не в commandAction. 59

public void run() { 59

play(getURL()); 59

} 59

String getURL() { 59

return url.getString(); 60

} 60

void play(String url) { 60

try { 60

VideoControl vc; 60

defplayer(); 60

// создаем плеер 60

player = Manager.createPlayer(url); 60

player.addPlayerListener(this); 60

player.realize(); 60

vc = (VideoControl)player.getControl("VideoControl"); 60

if(vc != null) { 60

Item video = (Item)vc.initDisplayMode( 60

vc.USE_GUI_PRIMITIVE, null); 60

Form v = new Form("Playing Video..."); 60

StringItem si = new StringItem("Status: ", "Playing..."); 60

v.append(si); 60

v.append(video); 60

display.setCurrent(v); 60

} 60

player.prefetch(); 60

player.start(); 60

} 60

catch(Throwable t) { 60

reset(); 60

} 60

} 60

void defplayer() throws MediaException { 60

if (player != null) { 60

if(player.getState() == Player.STARTED) { 60

player.stop(); 60

} 60

if(player.getState() == Player.PREFETCHED) { 60

player.deallocate(); 60

} 60

if(player.getState() == Player.REALIZED || 60

player.getState() == Player.UNREALIZED) { 60

player.close(); 60

} 60

} 60

player = null; 60

} 60

void reset() { 60

player = null; 60

} 60

void stopPlayer() { 60

try { 60

defplayer(); 60

} 61

catch(MediaException me) { 61

} 61

reset(); 61

} 61

} 61

В методе play() реализованы следующие функции: 61

Cоздание экземпляра Player. 61

Регистрация мидлета как PlayerListener, поскольку наш мидлет переопределяет метод playerUpdate() интерфейса PlayerListener. Когда происходит какое либо событие, связанное с воспроизведением звука, все PlayerListener-ы получают соответствующее уведомление. Например, при завершении воспроизведения вызывается событие, обозначенное константой PlayerListener.END_OF_MEDIA. 61

Проверяет, был ли создан VideoControl. Если да, выполняет инициализацию компоненты экрана Item и добавляет ее на форму. 61

Выбирает плеер и запускает его. 61

Вы можете проверить работоспособность данного примера, используя J2ME Wireless Toolkit 2.0. Создайте новый проект и скопируйте исходный код в файл /apps/SimplePlayer/src/PlayerMIDlet.java. Выполните компиляцию и запустите мидлет. Для проверки можете использовать следующие URL адреса: 61

http://java.sun.com/products/java-media/mma/media/test-wav.wav 61

http://java.sun.com/products/java-media/mma/media/test-mpeg.mpg 61

1) Описати Механізм обробки мультимедійної інформації. 61

2) Які MMAPI пакеты ви знаєте? 61

Лабораторна робота №8 62

Використання Game Builder для Java ME development 62

Більше інформації про технології, використані в цій роботі, доступні на наступних сторінках: 68

MIDP Profile API JavaDoc (especially package javax.microedition.lcdui.game) http://java.sun.com/javame/reference/apis/jsr118/index.html 68

More Mobility Tutorial Drafts http://wiki.netbeans.org/wiki/view/DraftTutorials 68

Відповісти на наступні питання: 69

1) Що представляє собою Game Builder: описати елементи вікна програми. 69

2) За що відповідає графа Z-order у навігаторі? 69

Дополнения 70

Додаток № 1 70

NetBeans 6.5 - бесплатная IDE для разработки J2ME приложений 70

Додаток № 2 74

Как загрузить текст из файла в J2ME 74

Додаток № 3 78

Как настроить Tomcat 78

Лабораторная работа 1

Wireless Development Tutorial Часть 1

В этой лабораторной работе содержится все, что вам надо знать для начала программирования на Java в рамках технологии Micro Edition (J2ME).

Сначала рассмотрим как написать простейшее J2ME приложение, как выполнить его компоновку и тестирование. Поскольку MIDlet-ы выполняются на мобильных устройствах, оснащенных коммуникационным оборудованием, то в распоряжении програмиста оказываются мощнейшие инструменты для создания мобильных клиент-серверных приложений. Поэтому на следующем этапе мы рассмотрим процесс создания и отладки серверной части приложения (servlet-а) и как заставить MIDlet с ней взаимодействовать.

Что Вам необходимо?

Минимальная среда разработки должна состоять из трех компонентов; Java 2 Standard Edition (J2SE) SDK version 1.6.0 или выше; J2ME Wireless Toolkit — пакет утилит для компоновки и тестирования MIDlet-ов; текстовый редактор — блокнот или что-нибудь более подходящее. Ключевым элементом среды разработки является J2ME Wireless Toolkit. Она может быть интегрирована в IDE, но может использоваться и отдельно. Большинство IDE содержат свой собственный редактор — к примеру NetBeans 6.5, который упрощает процессы разработки визуального интерфейса приложения и его отладки.

J2ME Wireless Toolkit

J2ME Wireless Toolkit — набор утилит, позволяющих выполнить компоновку и тестирование MIDP приложений (toolkit автоматизирует процесс компоновки приложения MIDP и позволяет создавать пакеты для переноса на мобильный телефон). Для запуска toolkit-а выберите ярлык KToolbar. Вы должны увидеть следующую картинку:

J2ME Wireless Toolkit работает с проектами, конечным результатом которых являются MIDlet-ы. Toolkit не может работать с несколькими проектами одновременно. Вы можете выполнять компановку проектов, запускать их на эмуляторе, создавать пакеты для переноса на телефон и много всего другого. В состав J2ME Wireless Toolkit входят несколько примеров; изучите их. Давайте приступим к созданию проекта. Нажмите кнопку New Project. Toolkit спросит у Вас его имя, а также имя MIDlet класса. Введите HelloSuite и HelloMIDlet, как показано ниже:

После того, как вы заполните эти два поля, вам предложат установить другие настройки проекта. Примем все по умолчанию и нажмем OK. Проект будет создан. На текстовой панели J2ME Wireless Toolkit отображаются сообщения, котороые подскажут Вам, где находятся исходники вашего проекта. Toolkit сохраняет каждый проект в подкаталоге apps. Имя родительского каталога совпадает с названием проекта. В нашем случае Toolkit создал новый каталог c:\WTK22\apps\HelloSuite. Каждый проект содержит стандартный набор каталогов:

В bin содержатся откомпилированные MIDlet-ы: suit (файлы .jar) и дескриптор (.jad- файл); в папке lib — все дополнительные JAR файлы, которые подключаются к проекту; в res — файлы ресурсов, например рисунки или текстовые файлы; в scr — исходные тексты проекта. Существует общепринятое правило именования файлов и каталогов. Пусть у нас есть исходный код класса users.Root, тогда для него мы должны создать файл scr/users/Root.java. Когда Вы производите компоновку проекта в KToolbar, создается несколько новых каталогов:

Как видите, J2ME Wireless Toolkit создал папки classes, tmpclasses и tmplib. В большинстве случаев Вы можете смело их игнорировать.

Создание miDlet-а

Давайте напишем простой MIDlet. Откройте текстовый редактор и поместите туда следующий код:

---------

import javax.microedition.lcdui.*;

import javax.microedition.midlet.*;

public class HelloMIDlet extends MIDlet implements CommandListener {

private Form mMainForm;

public HelloMIDlet() {

mMainForm = new Form( "HelloMIDlet" );

mMainForm.append( new StringItem( null, "Hello, MIDP!" ) );

mMainForm.addCommand( new Command( "Exit", Command.EXIT, 0 ) );

mMainForm.setCommandListener( this );

}

public void startApp() {

Display.getDisplay( this ).setCurrent( mMainForm );

}

public void pauseApp() {}

public void destroyApp( boolean unconditional ) {}

public void commandAction( Command c, Displayable s ) {

notifyDestroyed();

}

}

---------

Сохраните его как HelloMIDlet.java в папке scr нашего проекта. Затем нажмите кнопку Build в KToolbar. Toolkit приступит к компиляции вашего проекта. Если возникнут какие-нибудь ошибки, вы увидете их в текстовом поле KToolbar-а. Исправьте все возникшие ошибки и добейтесь успешного окончания компоновки. Теперь Вы готовы к тестированию нашего MIDlet-а. Нажмите кнопку Run. Вы должны увидеть окно эмулятора с изображением телефона.

Эмулятор показывает список доступных MIDlet-ов. В нашем случае будет показан один MIDlet. Итак, Вы видите HelloSuite, при его выборе будет запущен класс HelloMIDlet. Чтобы увидеть, где он встречается, перейдите в KToolbar и выберите Settings... Затем выберите MIDlets, чтобы увидеть список MIDlet-ов в проекте. Вернитесь в эмулятор, нажмите на изображение клавиши "Select" на телефоне. Это приведет к запуску нашего MIDlet-а. Будет показан простой экран (см. рис.)

Нажмите на Exit, чтобы выйти из MIDlet-а. Закройте эмулятор или нажмите Escape для завершения сессии эмулятора.

Мы только что использовали эмулятор "стандартного" телефона (DefaultColorPhone). J2ME Wireless Toolkit позволяет эмулировать и другие телефоны. Попробуйте запустить HelloMIDlet на нескольких других устройствах и посмотрите, как адаптируется к ним интерфейс. Выберите понравившийся вам эмулятор в выпадающем меню KToolBar-а и нажмите Run снова. Откройте проекты, которые поставляются вместе с J2ME Wireless Toolkit и изучите их код.