M. Fraś + D. Konieczy

Laboratorium SW

Ćwiczenie 3

Konfiguracja środowiska deweloperskiego Java ME.

Interfejs wysoko-poziomowy i RMS

1 Cele ćwiczenia

Celem ćwiczenia jest:

1. Przygotowanie środowiska do pisania programów w Java ME.

2. Opanowanie technik tworzenia aplikacji J2ME.

3. Poznanie mechanizmów tworzenia interfejsu wysokopoziomowego aplikacji J2ME.

4. Poznanie mechanizmów obsługi pamięci nieulotnej.

2 Środowiska tworzenia i testowania programów J2ME

Możliwe środowiska do pisania programów w Java ME są następujące:

Niezbędnym pakietem jest:

a.

Java Platform Micro Edition Software Development Kit 3.2 (Java ME SDK 3.2).

Platformę można pobrać ze strony:

http://www.oracle.com/technetwork/java/javame/javamobile/download/sdk/index.html

Platforma zawiera to co potrzebne do pisania programów, w tym środowisko

uruchomieniowe oraz symulatory telefonów komórkowych.

Uwaga: pakiet Netbeans (zależnie od wersji) może już zawierać Java ME SDK.

Ponadto wygodnie jest wykorzystać jedną z platform deweloperskich Eclipse lub Netbeans.

Mariusz Fraś

b.

Eclipse wer. 3.7.2 Indygo (lub nowszy), wraz z Mobile Tools for Java (MTJ).

Środowisko IDE można ściągnąć z witryny http://www.eclipse.org.

Instalacja i konfiguracja (dla Eclipse 3.7.2):

i.

Pakiet rozpakować w wybranym katalogu. Uwaga: zaleca się nie stosować polskich

liter w nazwach katalogów.

Instytut Informatyki

ii.

Doinstalować dodatek MTJ. MTJ najlepiej doinstalować z poziomu programu.

opcja: Help→ Install New Software. W oknie Available Software obok pola Work with klikamy przycisk Add i wprowadzamy adres URL z lokalizacją repozytorium Eclipse

Indigo: http://download.eclipse.org/releases/indigo. Zaznaczmy pakiety Mobile

Tools for... w węźle Mobile and Device Developement i zatwierdzamy instalację.

Politechnika Wrocławska

iii.

Zainstalować Java ME SDK Plug-in do Eclipse:

Ściągnąć ze witryny www.oracle.com Java ME SDK Plug-in do Eclipse (plik .zip).

Następnie z poziomu programu Eclipse wybieramy:

opcja: Help→ Install New Software. W oknie Available Software obok pola Work with klikamy przycisk Add, wybieramy Archive i wskazujemy plik .zip z plug-in’em.

Zatwierdzamy instalację.

1

M. Fraś + D. Konieczy

Laboratorium SW

iv.

Zintegrowanie Eclipse z Java ME SDK (ustawienie emulatorów urządzeń):

- w menu Window wybieramy polecenie Preferences.

- drzewku rozwijamy Java ME i wybieramy Device Management,

- klikamy przycisk Manual Install,

- w oknie Import Devices, w polu Specify search directory wpisujemy ścieżkę katalogu

gdzie zainstalowano Java ME SDK (zostaną wyszukane emulatory urządzeń),

- wybieramy emulatory (najlepiej wszystkie) i zatwierdzamy.

Może być czasami pomocne (do przetestowania w danym środowisku) ustawienie:

- w oknie Window→ Preferences rozwijamy Java i w drzewku wybieramy Debug,

- usuwamy zaznaczenie opcji Suspend execution on uncaught exceptions i Suspend

execution on compilation errors oraz zmieniamy wartość pola

Debugger timeout (ms) na większą.

Konfiguracja środowiska Eclipse oraz tworzone projekty aplikacji zapamiętywane są

w katalogu .workspace. Usunięcie go spowoduje konieczność ponownej konfiguracji.

c.

Netbeans IDE wer. 7.2.1 (lub nowsza, lub nieco starsza).

Pakiet Netbeans zależnie od wersji może zawierać starszą wersję SDK. Szczegóły

instalacji dostępne są na stronach www.oracle.com i netbeans.org.

Uwaga 1: Wymieniony wyżej opis konfiguracji Eclipse dotyczy wersji 3.7.2. Inne wersje

Eclipse (w tym najnowsza) mogą wymagać innych zabiegów, które są opisywane na

stronach www.oracle.com lub różnych forach internetowych.

Uwaga 2: W przypadku instalacji Netbeans z Java ME SDK, a potem instalacji Eclipse, przy

konfiguracji Eclipse, należy szukać katalogu z Java ME SDK w podkatalogach Netbeans.

3 Architektura MIDleta

Mariusz Fraś

3.1

Cykl życia MIDleta

Cykl życia midleta (MIDleta) przedstawia poniższy schemat, na którym można wyróżnić 3

stany, w których może się on znajdować.

new()

Instytut Informatyki

destroyApp()

Zawieszony

(Paused)

Zakończonu

Politechnika Wrocławska

pauseApp()

startApp()

(Destroyed)

Aktywny

(Active)

destroyApp()

2

M. Fraś + D. Konieczy

Laboratorium SW

Midlet musi zawierać 3 niezbędne metody do zarządzania jego stanem. Z cyklu życia

wynika, że metoda startApp() może być wykonywana wielokrotnie, natomiast

konstruowanie midletu poprzez new() wykonuje się tylko raz, przed tą metodą. To oznacza,

że działania, które należy zrobić tylko raz powinny być wykonane w konstruktorze. Jeśli z

pewnych powodów muszą być wykonane dopiero w metodzie startApp(), to należy

wprowadzić mechanizm, żeby nie były wykonywane wielokrotnie. Przejście w stan

zawieszenia oznacza często potrzebę zwolnienia zasobów (np. ekranu), zatrzymania

timerów itd. Przejście w ten stan może się odbyć w dwojaki sposób. Jedną sytuacją jest gdy

maszyna Javy zawiesi midlet z powodu np. przychodzącej rozmowy telefonicznej. Drugą jest

możliwość samodzielnego przejścia w stan zawieszenia. W tym przypadku należy wykonać

zwolnienie zasobów (np. poprzez wywołanie metody pauseApp()) a następnie wywołać

metodę notifyPaused(). Informuje ona maszynę Javy, że aplikacja jest przygotowana do

zawieszenia. Maszyna KVM w najbliższym czasie zawiesi midlet, ale już nie wywoła jego

metody pauseApp()!

Aby powrócić do stanu aktywnego sam midlet (lub inny midlet) może wywołać metodę

resumeRequest(). Oznacza to, że midlet jest gotowy do działania i tylko czeka na

przydział zasobów.

Przejście ze stanu zawieszonego do aktywnego dokonuje się zawsze poprzez wywołanie

przez KVM metody startApp(). Jak wcześniej wspomniano, oznacza to, że należy

uważać, aby w tej metodzie nie rezerwować ponownie zasobów, jeśli wcześniej nie zostały

one zwolnione w metodzie pauseApp().

Podobnie sprawa się ma z metodą destroyApp(). Jest ona wywoływana przez KVM, gdy

system chce zamknąć midlet. Gdy wartość parametru logicznego tej metody jest równa

true, midlet będzie bezwzględnie zamknięty. Jeśli jednak wartość ta wynosi false, to

midlet może stwierdzić, że nie jest gotowy do zamknięcia i poinformować o tym fakcie

Mariusz Fraś

poprzez rzucenie wyjątku MIDletStatChangeException. Midlet można samodzielnie

zamknąć poprzez wywołanie metody notifyDestroyed(). Jej działanie jest analogiczne

to metody notifyPaused(), stąd wszelkie zwolnienie zasobów należy wykonać wcześniej.

Wyjątek może rzucać również metoda startApp(). Jeśli będzie to wyjątek

MIDletStateChangeException, to aplikacja przejdzie w stan zawieszenia, jeśli jakiś inny

wyjątek, to aplikacja zostanie zawieszona poprzez wywołanie destroyApp().

Instytut Informatyki

3.2

Interfejs wysokiego poziomu midletu

Midlet korzysta z ekranu w celu wyprowadzania informacji oraz z klawiatury do

wprowadzania informacji. Dostęp do ekranu realizuje się poprzez klasę Display. Jej

statyczna metoda getDisplay(MIDlet m) zwraca obiekt klasy Display dla midletu m. W

Politechnika Wrocławska

czasie działania midletu jest to zawsze jeden i ten sam obiekt tej klasy (wzorzec Singleton).

Odpowiada on za zarządzanie urządzeniami ekranu i klawiatury.

Interfejs wysokiego poziomu w Javie ME jest podobny do interfejsu w wersjach Javy SE i EE,

ale jest mocno ograniczony. Midlet może zawierać wiele pojemników-okien, jednak tylko

jedno okno w danym momencie może być wyświetlane. Pojemniki-okna to obiekty

dziedziczące po klasie Displayable. Tylko jeden midlet ma w danym momencie dostęp do

3

M. Fraś + D. Konieczy

Laboratorium SW

ekranu. Pojemniki pozwalają na umieszczenie w nich innych komponentów. Składniki zwykłe

(kontrolki) dziedziczą po klasie Item i mogą być wstawiane do pojemników. Pojemnik-okno

jest ustawiany jako aktywny/widoczny dla ekranu za pomocą metody setCurrent(….klasy

Display . W klasie tej możemy sprawdzić czy wyświetlacz jest kolorowy (metodą

isColor()) i ile ma kolorów (numColors()), włączyć wibrację (vibrate(…)) lub też

poświetlenie (flashBacklight(…)). Dostępne w Javie ME pojemniki dla interfejsu

wysokiego poziomu to Form (formatka), TextBox (okno tekstowe), Alert (okno z

komunikatem alarmowym), List (okno z listą opcji). Każda z wymienionych klas umożliwia

pobranie danych nt. rozmiarów pojemnika (getWidth(), getHeight()), ustawić/pobrać

tytuł (setTitle/getTitle), sprawdzić, czy jest wyświetlony (isShown()).

TextBox

Ten pojemnik pozwala na wpisywanie tekstu. W konstruktorze podaje się tytuł, początkowy

tekst, maksymalną długość tekstu oraz flagę informująca jakie znaki są dozwolone i jak

prezentować wpisywany tekst (np. dla hasła są to gwiazdki). Posiada metody do

pobranie/ustawienia wpisanego tekstu oraz do sterowania kursorem.

Alert

Okienko alarmowe z komunikatem. W konstruktorze podaje się tytuł, tekst komunikatu, obraz

oraz typ komunikatu. Poprzez metodę setTimer(…) podaje się na ile milisekund ma być

okienko pokazywane. Przy wstawianiu obiektu tej klasy do obiektu Display należy w

metodzie setCurrent(…) podać jako drugi parametr inny pojemnik, do którego nastąpi

przełączeniu po upływie podanego czasu.

List

Okno z listą opcji. W konstruktorze podajemy tytuł oraz czy jest to wybór pojedynczy czy

wielu. Ponieważ klasa ta implementuje interfejs Choice, posiada metody do wstawiania

Mariusz Fraś

kolejnych opcji metodą append(…) oraz sprawdzania i ustawiania aktualnego wyboru.

Form

Najbardziej rozbudowany pojemnik. Pozwala dodawać/usuwać kontrolki, obrazki poprzez

metody append(…), insert(…), set (…) i delete(…). Zapamiętuje listę kontrolek w

postaci listy, którą organizuje na ekranie z góry do dołu, a w linii od lewej do prawej.

Instytut Informatyki

Do formatki można dodawać różne elementy (obiekty klasy Item). Dodatkowo można

dodawać element typu String. Poniżej krótki przegląd podklas klasy Item:

• StringItem - napis

• TextField – pole edycji tekstowej

• DateField – pole edycji daty

Politechnika Wrocławska

• ImageItem – obraz (niezmienny)

• Image – obraz (zmienny)

• ChoiceGroup – grupa pól wyboru

• Gauge - suwak

• Spacer – odstęp między komponentami

• Ticker – przesuwający się tekst (nie zaleca się jego używania)

4

M. Fraś + D. Konieczy

Laboratorium SW

3.3

System zarządzania rekordami (RMS)

Record Management System (RMS) jest uniwersalnym sposobem przechowywania danych

zapisywanych przez midlety. Podstawowym elementem zapisu/odczytu jest rekord, czyli

tablica bajtów. Rekordy tworzą zbiór rekordów, przechowywany w obiekcie klasy

RecordStore. Każdy rekord ma unikalny identyfikator (numer). Każdy zbiór ma przypisaną

nazwę oraz właściciela (midlet), jednak można określić uprawnienia dla innych midletów.

Jeden midlet może mieć dowolną liczbę zbiorów rekordów. Zbiór można otworzyć/utworzyć

za pomocą metod:

static RecordStore openRecordStore(String nazwa, boolean flaga)

static RecordStore openRecordStore(String nazwa, boolean flaga,

int dostep, boolean zapis)

Gdzie nazwa, to nazwa zbioru rekordów, natomiast flaga określa czy zbiór ma być

utworzony jeśli jeszcze nie istnieje

Operacje możliwe do wykonania na zbiorze to:

• int getNumRecords() – podaje liczbę rekordów w zbiorze

• int getSize() – podaje rozmiar w bajtach zbioru rekordów

• int getSizeAvailable()– podaje rozmiar w bajtach wolnego obszaru pamięci

dostępnego dla zbioru rekordów

• byte[] getRecord(int id) – zwraca rekord (tablicę bajtów) o podanym

identyfikatorze id

• void addRecord(byte[] bufor, int początek, int n) – dodanie nowego

rekordu na końcu zbioru

Mariusz Fraś

(rekord ma postać tablicy bajtów o indeksach od początek do początek+n-1)

• void setRecord(int id, byte[] bufor, int poczatek,int n) – zmiana

zawartości istniejącego rekordu o identyfikatorze id

• void deleteRecord(int id) – usunięcie ze zbioru rekordu o identyfikatorze id

• void deleteRecordStore(String nazwa) – usunięcie całego zbioru rekordów o

Instytut Informatyki

podanej nazwie (usuwany zbiór musi być zamknięty)

• closeRecodStore() – zamknięcie zbioru.

Istnieje również mechanizm obsługi zbioru za pomocą iteratora RecordEnumeration oraz

słuchaczy.

Używając obiektów klas ByteArrayOutputStream oraz DataOutputStream można

Politechnika Wrocławska

łatwo wstawiać do strumienia dane różnych typów a następnie pobrać ze strumienia dane

postaci bajtów i zapisać do zbioru. Analogiczne można wczytywać dane różnych typów z

rekordu.

5

M. Fraś + D. Konieczy

Laboratorium SW

4 Zadanie

Napisać aplikację, która będzie pozwalała wprowadzać, zapamiętywać i przeglądać

indywidualnie wymyślony zestaw danych. Aplikacja powinna się charakteryzować poniżej

podanymi szczegółowymi cechami.

1. Jako pierwszy ekran zrealizować główne menu aplikacji z opcjami wyboru:

a. wprowadzania danych,

b. przeglądania wprowadzonych danych,

c. zakończenia działania aplikacji.

itp. (to co będzie potrzebne)

2. Zrealizować wprowadzanie danych poprzez pojemnik Form i umieszczone w nim

kontrolki. Po wprowadzeniu danych wyświetlić informację o fakcie w oknie klasy Alert (a

w nim np. jakiś element identyfikujący dane (np. nazwisko jeśli są to dane osobowe, albo

model samochodu/samolotu/itp. w innym przypadku)).

Zestaw danych do wprowadzenia należy wymyślić samemu. Powinien on być na tyle

urozmaicony, żeby można było wykorzystać różne kontrolki.

3. Uzupełnić funkcję wprowadzania danych o zapis do pamięci trwałej wykorzystując

mechanizm RMS. Dostęp do danych powinien być tak zorganizowany, żeby w razie

potrzeby utworzyć odpowiedni zbiór i móc z niego korzystać po powtórnym uruchomieniu

aplikacji.

Uwaga: dla emulatora jest odpowiednia opcja dla restartu aplikacji. Wyłączenie

emulatora wymazuje wszystko.

4. Zaimplementować przeglądanie listy danych i po wyborze konkretnej pozycji

wyświetlenie pełnej informacji w oknie tekstowym.

5. Dodać opcję przeglądania ze względu na różne kryteria sortowania rekordów i/lub

Mariusz Fraś

filtrowania danych (rekordów).

6. Dodać funkcję kasowania danych (pojedynczych rekordów). Dodać przy tym możliwość

określenia, które dane kasujemy.

Uwaga: w przypadku kasowania danych przeglądanie danych musi to uwzględniać.

7. Dodać funkcję modyfikacji rekordu danych (jako oddzielną pozycję menu lub komendę

Instytut Informatyki

przy przeglądaniu danych). Przy modyfikacji danych dodać komendy zatwierdzania i

zaniechania edycji.

8. W ćwiczeniu należy wykorzystać jak najwięcej różnych elementów interfejsu wysokiego

poziomu. (przyciski, listy, różne pola wyboru, linie i pola tekstowe, pola daty i czasu,

suwaki, obrazki, itd. itp. ), a także możliwość formatowania kontrolek.

Politechnika Wrocławska

Ważne: różnorodność użytych środków będzie w ćwiczeniu oceniana.

9. Elementy aplikacji powinny być proporcjonalnie rozłożone, gdy uruchomimy aplikację na

różnych komórkach. W miarę możliwości uwzględnić orientację ekranu (pion/poziom).

10. Oddzielne logicznie elementy aplikacji należy umieszczać w osobnych klasach. Aplikacja

powinna mieć czytelną strukturę.

6