} else {
addComponent (new MylistItem (MainMenuConstatns.MOVEMENT_NOTIFICATION,
"Movement notification"));
}
if (pr.getErrNotificationNumber()!= "") {
addComponent (new MylistItem (MainMenuConstatns.ERROR_NOTIFICATION,
new String[] {"Error Notification", pr.getErrNotificationNumber()}));
} else {
addComponent (new MylistItem (MainMenuConstatns.ERROR_NOTIFICATION,
"Error Notification"));
}
addComponent (new MylistItem (MainMenuConstatns.CAMERA, "Camera"));
addComponent (new MylistItem (MainMenuConstatns.EXIT, "Exit"));
addComponent (new MylistItem (MainMenuConstatns.HELP, "Help"));
Обработка нажатия пользователем кнопок и определение, какая экранная форма должна быть показана далее, выполняется так, как показано в следующем листинге 3.6.
Листинг 3.6 – Обработка нажатий кнопок для главного меню
class MainMenuActionListener implements ActionListener {
public void actionPerformed (ActionEvent act) {
Component cmp = getFocused();
if (cmp instanceof MylistItem) {
int id = ((MylistItem) cmp).getId();
switch (id) {
case MainMenuConstatns.SCHEDULE:
midlet.getScheduleDisplay().show();
break;
case MainMenuConstatns.TRANSLATE_VIDEO:
midlet.getVideoTransmitionDisplay().show();
break;
case MainMenuConstatns.MOVEMENT_NOTIFICATION:
midlet.getMovementNotificationDisplay().show();
break;
case MainMenuConstatns.CAMERA:
midlet.getCamera().show();
midlet.getCamera().startCamera();
midlet.getCamera().revalidate();
break;
case MainMenuConstatns.EXIT:
midlet.exitMIDlet();
break;
case MainMenuConstatns.HELP:
midlet.getHelpScreen().show();
break;
case MainMenuConstatns.ERROR_NOTIFICATION:
midlet.getErrorNotification().show();
break;
}
}
}
На форме настройки расписания (рисунок 3.3) необходимо было реализовать динамическое скрытие / отображение некоторых элементов, а именно: когда выбирается радиокнопка enter time, то должны сразу под ней отобразиться поля для ввода часов, минут, дня, месяца, года. А при выборе радиокнопки unbounded эти поля должны быть скрыты.
Рисунок 3.3 – Заполнение расписания работы камеры
Такая функциональность реализуется путем указания у каждой радиокнопки ActionListener, который отслеживает выбор радиокнопок (листинг 3.7). dateFrom и dateTo являются контейнерами типа Container и содержат все необходимые поля для указания точной даты и времени.
Листинг 3.7 – Обработка выбора радиокнопок
publicvoidactionPerformed(ActionEventevt) {
Component cmp = (Component) evt.getSource();
if (cmp == rb1DateFromEnter) {
if (rb1DateFromEnter.isSelected()) {
if (! getContentPane().contains(dateFrom)) {
addComponent (3, dateFrom);
revalidate();
return;
}
}
}
if (cmp == rbDateFromUnbounded) {
if (getContentPane().contains(dateFrom)) {
removeComponent(dateFrom);
revalidate();
return;
}
}
if (cmp == rbDateToEnter) {
if (rbDateToEnter.isSelected()) {
if (! getContentPane().contains(dateTo)) {
addComponent (getContentPane().getComponentCount() – 2, dateTo);
dateTo.setFocus(true);
revalidate();
return;
}
}
}
if (cmp == rbDateToUnbounded) {
if (getContentPane().contains(dateTo)) {
removeComponent(dateTo);
revalidate();
return;
}
}
}
Рисунок 3.4 – Экранная форма со списком
Для всех списков в данном приложении разработан специальный способ их отображения – класс MyListCellRenderer. По умолчанию для отображения списков применяется DefaultListCellRenderer, который просто преобразовывает все элементы к объектам класса Label. Для создания своего способа отображения элементов списка необходимо реализовать интерфейс ListCellRenderer.
Метод getListCellRendererComponent этого интерфейса должен возвращать отображаемый элемент списка из объекта, передаваемого ему в качестве параметра. Переопределение методов getListFocusComponent обеспечивает возможность настройки стилей отображения выделенного и невыделенного элемента списка.
Пример списка, реализованного с помощью MyListCellRenderer, приведен на рисунке 3.4. В листинге 3.8 приведен программный код класса, который прорисовывает список.
Листинг 3.8 – Прорисовкасписка
public class MyListCellRenderer extends Container implements ListCellRenderer {
public MyListCellRenderer() {
setLayout (new BoxLayout (BoxLayout.Y_AXIS));
}
/**
* Returns displayable list element from received object
*/
public Component getListCellRendererComponent (List list, Object value,
int index, boolean isSelected) {
if (value instanceof String) {
setText((String) value);
} else {
setText (value.toString());
}
setFocus(isSelected);
applyStyle (this, isSelected);
return this;
}
/**
* Applies style for selected and unselected element
*/
private void applyStyle (Component component, boolean isSelected) {
Style style = null;
if (isSelected) {
style = UIManager.getInstance().getComponentStyle ("_selected");
} else {
style = UIManager.getInstance().getComponentStyle ("_unselected");
}
component.setStyle(style);
}
public Component getListFocusComponent (List list) {
returnnull;
}
}
3.3 Передача данных по Bluetooth
API для работы с Bluetooth содержится в пакете JSR-82 [9]. Эта библиотека состоит из двух пакетов: базовое BluetoothAPI и OBEX.
Для работы с Bluetooth у телефона должны быть минимум 512 килобайт памяти, а также поддерживаться CLDC.
Чтобы приложение могло использовать возможности Bluetooth, необходимо реализовать интерфейс DiscoveryListener и его методы deviceDiscovered(), inquiryCompleted(), servicesDiscovered(), serviceSearchCompleted(), используемые для обнаружения рядом находящихся Bluetooth-устройств.
Далее приводится программный код (листинг 3.9), который инициирует поиск. Вначале инициализируется переменная LocalDevice local, которая представляет собой данный телефон; потом инициализируется переменная DiscoveryAgent agent. Именно этот объект запускает поиск методом startInquiry() с параметрами DiscoveryAgent.GIAC и ссылкой на объект, который реализовал интерфейс DiscoveryListener и будет обрабатывать все события, связанные с обнаружением устройств и их сервисов. Этот метод возвращает true, если поиск устройств был успешно начат, или false в противном случае.
Переменная Vector devicesFound используется для сохранения всех обнаруженных устройств.
Листинг3.9 – Началопоискаустройств
* This method starts device discovering
*/
public void doDeviceDiscovery() {
try {
local = LocalDevice.getLocalDevice();
} catch (BluetoothStateException bse) {
Log.out.println ("EXCEPTION!"+ bse.toString());
}
agent = local.getDiscoveryAgent();
devicesFound = new Vector();
try {
if (! agent.startInquiry (DiscoveryAgent.GIAC, this)) {
Log.out.println (" DISCOVERING IS NOT STARTED");
}
} catch (BluetoothStateException bse) {
Log.out.println (" BluetoothStateException "+ bse.toString());
}
}
При обнаружении Bluetooth-устройства вызывается метод deviceDiscovered(), который получает в качестве параметров найденное устройство remoteDevice и его тип deviceClass.
Далее приводится программный код (листинг 3.10) этого метода. В методе выполняется добавление в список, отображаемый на экране, доступных рядом находящихся Bluetooth-устройств. Найденное устройство также добавляется в массив devicesFound.
Листинг 3.10 – Обработка события, связанного с обнаружением нового устройства
/**
* Called when a device is discovered during device discovery
* @param remoteDevice founded device
* @param deviceClass
public void deviceDiscovered (RemoteDevice remoteDevice,
DeviceClass deviceClass) {
try {
midlet.getSelectDeviceDisplay().getDevicesList().addItem (
remoteDevice.getFriendlyName(false));
devicesFound.addElement(remoteDevice);
} catch (IOException ex) {
Log.out.println ("ex when device has been discovered "+ex.toString());
}
}
После окончания поиска всех устройств вызывается метод inquiryCompleted(), в параметре которого содержится код результата поиска. Далее приводится этот метод (листинг 3.11).
Листинг 3.11 – Завершение поиска устройств
/**
* Calledwhendevicediscoveringiscomplete
* @param – param discovering status
public void inquiryCompleted (int param) {
midlet.getSelectDeviceDisplay().removeCommand (midlet.getSelectDeviceDisplay().
getStopSearchDevices());
midlet.getSelectDeviceDisplay().addCommand (midlet.getSelectDeviceDisplay().
getBackSelectDevice());
switch (param) {
case DiscoveryListener.INQUIRY_COMPLETED:
if (devicesFound.size() > 0) {
midlet.getSelectDeviceDisplay().removeCommand (
midlet.getSelectDeviceDisplay().getStopSearchDevices());
midlet.getSelectDeviceDisplay().addCommand (
midlet.getSelectDeviceDisplay().getBackSelectDevice());
doServiceSearch((RemoteDevice) devicesFound.elementAt(0));
} else
break;
case DiscoveryListener.INQUIRY_ERROR:
//Error during inquiry
break;
case DiscoveryListener.INQUIRY_TERMINATED:
// Inquiry terminated by agent.cancelInquiry()
break;
}
}
Рисунок 3.5 – Список найденных устройств
После поиска устройств (на рисунке 3.5 показан список обнаруженных устройств) начинается поиск сервисов на одном из них. Найденные сервисы запоминаются в массиве ServiceRecord[] servicesFound. В следующем листинге 3.12 приводится метод, который начинает поиск сервисов. Для начала поиска вызывается метод searchServices() ранее созданного объекта DiscoveryAgent agent, которому передаются следующие параметры: атрибуты искомого сервиса или его UUID, удаленное устройство, на котором производить поиск, а также ссылка на объект, который будет обрабатывать все события, связанные с обнаружением сервисов.
Листинг3.12 – Инициацияпоискасервисов
/**
* This method starts service search on the divice
* @param device to be scanned for services
public void doServiceSearch (RemoteDevice device) {
* Service search will always give the default attributes:
* ServiceRecordHandle (0x0000), ServiceClassIDList (0x0001),
* ServiceRecordState (0x0002), ServiceID (0x0003) and
* ProtocolDescriptorList (0x004).
* These hex-values must be supplied through an int array
*/
int[] attributes = null; // {0x100};
/*
* Supplying UUIDs in an UUID array enables searching for
* specific services.
UUID[] uuids = new UUID[1];
uuids[0] = new UUID(0x0003);
try {
agent.searchServices (attributes, uuids, device, this);
} catch (BluetoothStateException e) {
Log.out.println ("BluetoothStateException error"+ e.getMessage());
}
}
Когда поиск сервисов завершен, вызывается метод serviceSearchCompleted(), код которого приведен ниже (листинг 3.13). В параметре данного метода содержится код результата поиска сервисов.
Листинг 3.13 – Завершениепоискасервисов
/**
* Called when service search completes
* @param transID identifies a particular service search
* @param respCode indicates why the service search is ended
*/
public void serviceSearchCompleted (int transID, int respCode) {
switch (respCode) {
case DiscoveryListener.SERVICE_SEARCH_COMPLETED:
Log.out.println ("serviceSearchCompleted: SERVICE_SEARCH_COMPLETED");
if (servicesFound.length > 0) {
midlet.getSelectDeviceDisplay().addCommand (
midlet.getSelectDeviceDisplay().getSelectDeviceCommand());
}
/*
* The service to connect to has been found earlier
* (by service discovery) and the service record is
* referencedthrough the object named: service (of type
* ServiceRecord)
*/
break;
case DiscoveryListener.SERVICE_SEARCH_DEVICE_NOT_REACHABLE:
Log.out.println ("serviceSearchCompleted: SERVICE_SEARCH_DEVICE_NOT_REACHABLE");
break;
case DiscoveryListener.SERVICE_SEARCH_ERROR:
Log.out.println ("serviceSearchCompleted: SERVICE_SEARCH_ERROR");
break;
case DiscoveryListener.SERVICE_SEARCH_NO_RECORDS:
Log.out.println ("serviceSearchCompleted: SERVICE_SEARCH_NO_RECORDS");
break;
case DiscoveryListener.SERVICE_SEARCH_TERMINATED:
Log.out.println ("serviceSearchCompleted: SERVICE_SEARCH_TERMINATED");
break;
}
}
Когда среди обнаруженных устройств выбрано одно и выполнен на нем поиск сервисов, то можно осуществить передачу данных по Bluetooth. Передача осуществляется через StreamConnection, URL которого получается с помощью следующего метода (листинг 3.14).
Листинг 3.14 – Получение URLдля доступа к сервису
public String getServiceConnectionURL (int nom) {
if (nom < servicesFound.length) {
return servicesFound[nom].getConnectionURL (
ServiceRecord.NOAUTHENTICATE_NOENCRYPT,
false);
} else {
returnnull;