1. Motiváció és bevezetés
A mobiltelefonok már régóta vonzzák az
alkalmazásprogramozókat. A mobiltelefonnak számos
tulajdonsága van, ami rendkívül izgalmas, új
alkalmazásoknak nyithat utat. Például a
mobiltelefon általában a
felhasználónál van (triviális, de
eléggé ritka tulajdonság), a SIM
kártyán keresztül a tulajdonos nagy
biztonsággal azonosítható és ez a
tulajdonos számlázható is (ugyancsak nagyon ritka
tulajdonság), az eszköz közel állandó
kapcsolatban áll a hálózattal és azzal
sokféle módon tud kommunikálni (hang,
jelcsatornák, különböző minőségű
adatátviteli csatornák). Ehhez járulnak
különböző bővített képességek, pl.
az eszköz pozíciója bemérhető (az eszköz
vagy a hálózat által), az eszköz
rövidtávú kapcsolatot képes létrehozni
környezetében levő nem mobil eszközökkel
(infravörös vagy Bluetooth kapcsolat, esetleg WLAN) és
esetleg még beépített kamerával is
rendelkezik. A mobiltelefonok operációs rendszere
és hardvere nagyon gyártófüggő, mindeddig
domináns szabvány nem alakult ki. Csak a Nokia pl.
három nagyobb platformot használ a mobiltelefonjaiban
és ezek közül kettő nem készült fel
alkalmazói programok futtatására. A hardver
és operációs rendszer
különbözőségeinek
áthidalására a Jáva ideálisan
alkalmas, így kézenfekvő ötlet a mobiltelefonokon a
Jávát tenni a közös
alkalmazásplatformmá.
A mobiltelefonos Jáva nagyon régi ötlet, már
a nyelv megszületésekor felmerült. Az ötlet
megvalósítása azonban nem volt egyszerű.
Mindenekelőtt a mobiltelefonok nagyon sokféle platformot
használnak úgy szoftverben, mind hardverben.
Általában az a helyzet, hogy a
készülékgyártó fejleszt egy
valósidejű operációs rendszermagot, aminek
képességei komponensek szeparálására
és azok kommunikációjára, valamint
végrehajtási szálak kezelésére
szorítkoznak. Nagyon különözően
használják magát a processzort, amin a
Jávát futtathatnánk (a telefonokban tipikusan
legalább két processzor van, egy DSP felel a
hívással kapcsolatos jelfeldolgozási
feladatokért, egy "szokásos" (általában ARM
architektúrájú) processzor pedig a
felhasználói felületért felel). Némely
telefonokban a "fő" processzor aktívan részt vesz a
híváskezelési feladatokban, más telefonokon
csak a hívással kapcsolatos felhasználói
felületkezelés a dolga. A Jáva virtuális
gép integrálása a különböző
telefonos környezetekbe és a JVM viselkedése
telefonhívás alatt tehát nem egyszerű
problémák.
Másik kézenfekvő akadály a memória: egy
tipikus mobiltelefon kb. 8-16 Megabájt ROM
memóriát tartalmaz, ami önmagában sem sok egy
J2SE JVM kb. 10 megabájtos méretéhez
képest. Nagyobb probléma azonban a RAM,
különösen a nem felejtő (tipikusan flash)
változata, ami garantálja, hogy a telefon nem felejti el
pl. a telefonkönyvet, ha az elem kimerül. Ez drága
memória és nincs is belőle sok, tehát ezzel
különösen óvatosan kell bánni. A
"normális", kikapcsolás esetén felejtő
RAM-ból sincs sok, nem feltételezhetünk
megabájtokat csak azért, hogy a JVM elinduljon (mint
ahogy a J2SE-nek ez szokása). A JVM-et tehát
"méretre kellett vágni", hogy beférjen a
telefonokba.
Ha a JVM megvan, következő kérdés, hogy mit
futtatunk rajta. A Jáva alkalmazásmodelljei
közül a Jáva alkalmazás és a Jáva
applet jöhet számításba, de
valójában egyik se megfelelő. Jáva
alkalmazás feltételez egy operációs
rendszert, aminek tetején ő futhat, a mobiltelefonokban ilyen
nincs. A Jáva applet modellje állandóan élő
szerverkapcsolatot feltételez (hiszen a böngésző
kedve szerint tölti be és ki az appleteket) ami a
mobiltelefónia világában igen
problémás, hiszen a felhasználó a
drága és lassú kapcsolat miatt maga
szeretné ellenőrzése alatt tartani, mikor és
mennyit tölt le.
A fenti megfontolások vezettek a mobiltelefonos Jáva
két rétegének megalkotásához.
- A Connected, Limited Device Configuration (CLDC) megszabja, mit
kell tudnia a virtuális gépnek ebben a környezetben.
A CLDC specifikáció a virtuális gép
specifikációja, de tartalmazza az összes
alkalmazásmodell által használt osztályok
(java.lang, java.util) osztály
specifikációját is. A CLDC 1.0
változatot a JSR-30, a CLDC 1.1 változatot a JSR-139
specifikáció írja le.
- Mobile Information Device Profile (MIDP) megszabja a
mobiltelefonos alkalmazások (midletek)
életciklusát és definiálja az
alkalmazások készítéséhez
szükséges Jáva osztályokat (pl.
felhasználói felület, kommunikáció,
stb.) A MIDP 1.0 változatot a JSR-37, a MIDP 2.0
változatot a JSR-118 specifikáció írja le.
2. A Connected, Limited Device Configuration (CLDC)
A CLDC specifikáció egy szűkített Jáva
környezetet ír le. A specifikáció az
alkalmazásmodellel nem foglalkozik, csak a
virtuális gép képességeit és a
támogatott alap Jáva osztályokat írja le.
A CLDC-t futtató környezet hardverigényeit a
következőképpen
definiálták.
- 160-512 Kbájt teljes memóriaigény. Ezen
belül 128 Kbájt "nem felejtő" (ROM, flash, stb) és
32 kbájt "felejtő" (RAM) memória a minimum. Ez a
memóriaméret nem tartalmazza az installált
alkalmazásokhoz tartozó memóriát.
- 16 vagy 32 bites processzor
- Alacsony fogyasztás, elemes üzem
- Valamilyen hálózati kapcsolat akár
korlátozott sávszélességgel is (9600
bit/sec)
A szoftverkörnyezetre a rendkívül változatos
mobiltelefonos operációs rendszerek miatt nagyon
kevés korlátozást adtak. A CLDC
implementációnak nincs szüksége arra, hogy az
operációs környezet támogasson
elválasztott címterületeket vagy legyen valami
fájlnak megfelelő fogalma. A CLDC implementáció
egyetlen végrehajtási szálban fut (tehát
nincs szüksége arra, hogy Jáva
végrehajtási szálakat natív
végrehajtási szálaknak feleltesse meg).
Érezhető, hogy a szigorú követelmények miatt
a JVM képességei jelentősen leszűkültek. A főbb
megszorítások a következők:
- Nincs lebegőpontos támogatás. A float és a
double típus nem támogatott és hiányzik
minden metódus, ami ezeket használja.
- A finalizációs mechanizmust kivették, az
Object.finalize() metódus hiányzik. Ez a
szolgáltatás amúgy is problémás volt
a J2SE-ben is, így ez nem nagy veszteség.
- A hibakezelés (java.lang.Error leszármazottak)
korlátozott. Ez azt jelenti, hogy bizonyos hibafajtákat a
JVM nem kezel le korrekten, hanem egyszerűen kilép.
- Natív kód nem használható.
- Az osztályok betöltése (Classloader)
Jáva programból nem befolyásolható, az
alapértelmezett osztálybetöltő nem cserélhető
ki, saját osztálybetöltő nem hozható
létre.
- Semmilyen mód nincsen az
osztálybetöltés
befolyásolására, a rendszerosztályokat nem
lehet felülírni. A rendszerosztályok esetleg
már eleve előre betöltött formában
(preloading/prelinking) vannak tárolva, így őket
betölteni a hagyományos értelemben véve nem
kell.
- A Reflection API (Jáva programok önelemző
képessége, amivel meg lehet tudni hogy pl. egy
osztálynak milyen metódusai vannak) hiányzik. Ez
lehetetlenné teszi önelemzésre alapuló
szolgáltatások (pl. objektumszerializáció)
használatát.
- Habár végrehajtási szálak
(java.lang.Thread) támogatottak, szálcsoportok
(java.lang.ThreadGroup) és démon szálak (daemon
thread) nincsenek.
- A gyenge hivatkozások (weak reference) hiányoznak
és nem lehet olyan szolgáltatást használni,
ami gyenge huvatkozást igényelne. A gyenge
hivatkozások olyan objektumokra hivatkoznak, amiket akkor lehet
szemétgyűjteni, ha a rendszer kifut a
memóriából. Főként akkor
használják őket, ha az alkalmazásnak
nagyméretű adatszerkezetei vannak, amik a futást
gyorsítják, de újra lehet generálni őket.
Ilyenekre lehet gyenge referenciákkal hivatkozni és ha az
objektum szemétgyűjtés áldozata lett, újra
lehet az adatszerkezetet generálni (habár a
felhasználónak ekkor várnia kell).
- Osztályok ellenőrzése. A Jáva egyik
legfontosabb újdonsága az osztályellenőrzés
(class verifier), amely a Jáva környezet
biztonságát jelentősen megnöveli. Az
osztályellenőrzés a J2SE-ben az osztály
betöltődésekor történik. Az
osztályellenőrzés egy bonyolult, többlépcsős
művelet, aminek során pl. ellenőrzik, hogy a
változókhoz a megfelelő típusú
értékek rendelődnek vagy hogy a program nem fut ki a
veremből. A Sun szerint az osztályellenőrzés kb. 50
kBájt programkódot és 30-100 kBájt RAM
memóriát igényel. A CLDC környezetben az
osztályellenőrzést kettéválasztották
és egy részét még az osztály
letöltése előtt, a fejlesztés során
végzik el. Ennek a folyamatnak a neve osztály
előellenőrzés (class preverification). Az osztály
előellenőrzés során az osztályellenőrzés
egy részét elvégzik és az
eredményét beszúrják a Jáva
osztályba. Ezt olymódon teszik, hogy hagyományos
virtuális gépek ezt a beszúrást figyelmen
kívül hagyják, az osztály nem CLDC
virtuális gépen is használható marad. Az
osztálybetöltődés során a CLDC
virtuális gépnek ezt az információt
már nem kell legenerálnia, ezzel
végrehajtási időt és memóriát
spórolunk. Az osztály mérete kb. 5%-kal nő, de a
CLDC programok szokásos mérete mellett
(néhányszor 10 kBájt) ez nem okoz jelentős
növekedést a letöltési időben, a
virtuális gépnek pedig nem kell tárolnia a plusz
információt, elég, ha az osztály első
használatakor felhasználnia az ellenőrzés
során, utána eldobhatja. CLDC virtuális gép
nem fogad el nem előellenőrzött kódot.
A CLDC igyekszik független maradni az
alkalmazásmodellektől, ezért csak a legalapvetőbb
osztályokat definiálja. Ezek nagy része a J2SE
osztályok szűkített változata, de van
néhány CLDC-specifikus osztály is. A
következő osztályok támogatotak,
- Rendszerosztályok a java.lang csomagból
(java.lang.Object, java.lang.Class, java.lang.Runtime,
java.lang.System, java.lang.Thread, java.lang.Runnable
(interface), java.lang.String, java.lang.StringBuffer,
java.lang.Throwable)
- Adattípusok a java.lang csomagból
(java.lang.Boolean, java.lang.Byte, java.lang.Short, java.lang.Integer,
java.lang.Long, java.lang.Character)
- Collection osztályok a java.util csomagból
(java.util.Vector, java.util.Stack, java.util.Hashtable,
java.util.Enumeration (interface))
- Kiviteli/beviteli osztályok a java.io csomagból
(java.io.InputStream, java.io.OutputStream,
java.io.ByteArrayInputStream, java.io.ByteArrayOutputStream,
java.io.DataInput (interface), java.io.DataOutput (interface),
java.io.DataInputStream, java.io.DataOutputStream, java.io.Reader,
java.io.Writer, java.io.InputStreamReader, java.io.OutputStreamWriter,
java.io.PrintStream)
- Idővel és dátummal kapcsolatos osztályok a
java.util csomagból (java.util.Calendar, java.util.Date,
java.util.TimeZone)
- Matematikai bővítések (java.util.Random,
java.lang.Math)
- Kivételek és hibák (itt nem soroljuk fel
őket)
- Generic Connection Framework (GCF). Ez egy CLDC-specifikus
csomag, ami a J2SE túl bonyolult kommunikációs
osztályait hivatott kiváltani. A GCF egységes
keretbe foglalja az összes kommunikációs
módszert és egyetlen metódus által teszi
elérhetővé az összes támogatott
sémát. Ez az osztály a
javax.microedition.io.Connector. A Connector kap egy URL-t és
visszaad egy megfelelő típusú Connection egyedet. Az URL
fogalmát kibővítették, így pl. socket
alapú kommunikáció megnyitására is
használható. Példák:
HTTP kapcsolat megnyitása:
String url = "http://www.j2medeveloper:80/com/myServlet";
HttpConnection c = (HttpConnection)Connector.open(url);
Socket kapcsolat megnyitása:
String url = "socket://www.j2medeveloper.com:80";
SocketConnection c = (SocketConnection)Connector.open(url);
A Connection-t implementáló osztályok
biztosíthatják a megfelelő metódusokat a
kommunikáció lebonyolításához. Pl. a
StreamConnection interface-t implementáló
osztályoknak van openInputStream és openOutputStream
metódusok, amelyekkel egy TCP-szerű szolgáltatást
nyújtó protokol adatfolyamaihoz
hozzáférhetnek. A CLDC-ben hiányzanak a java.net
osztályok, helyette a javax.microedition.io csomagban levő
osztályokkal végezhető a kommunikáció.
A fejlettebb, több memóriát tartalmazó
mobiltelefonok számára a CLDC 1.0
specifikációt kibővítették, ez a CLDC 1.1.
A legjelentősebb különbség, hogy a lebegőpontos
típusok most támogatottak és gyenge
referenciák használhatók. Ezen felül tucatnyi
kisebb bővítés történt a CLDC
osztályokon, amelyek közelebb hozták a CLDC API-t a
J2SE-hez.
3. A Mobile Information Device Profile (MIDP)
Amint az előzőekben említettem, egy dolog, hogy van egy
korlátozott képességű Jáva virtuális
gépünk, arról is gondoskodnunk kell, hogy valami
fusson is rajta. Az alkalmazásmodellt és a hozzá
kapcsolódó csomagokat a Mobile Information Device Profile
(MIDP) specifikáció tartalmazza. A
specifikáció a következő nagyobb részekből
áll:
- MIDlet alkalmazásmodel
- Felhasználói felület
- Hálózatkezelés
- Perzisztens adattárolás
- Időzítők (a java.util.Timer és a
java.util.TimerTask osztályok a J2SE-ből)
3.1. A MIDlet alkalmazásmodel
A MIDlet egy menedzselt alkalmazásmodel. Ez azt jelenti, hogy
van egy alkalmazásmenedzser rendszer (AMS), amelyik a MIDleteket
letölti, aktiválja és deaktiválja. Ez a
rendszer
kívül van a specifikáció keretén,
tipikusan a telefonszoftver része. Az AMS
implementációjáról a
specifikáció keveset szól, de a szokásos
implementációban az AMS letölti a MIDletet, a
készüléken tárolja (tehát nem
szükséges használat előtt letölteni),
kérésre aktiválja, végül a
felhasználónak módja van törölni a
MIDletet, ha már nincs rá szüksége.
A MIDleteket
szabványos JAR fájlokba csomagolják. Több
MIDlet is lehet egy JAR fájlban, ha többen vannak, akkor
őket MIDlet sorozatnak (MIDlet suite) nevezzük. Egy JAR-ba
csomagolt MIDletek
egymástól nincsenek elválasztva, egy MIDlet a JAR
bármelyik osztályát elérheti. Az
alkalmazásmenedzser a JAR fájlhoz tartozó
leíró (manifest) alapján találja meg a
JAR-ba csomagolt MIDleteket és tudja meg a
kezelésükhöz szükséges
információkat. Egy leírófájl
így néz ki:
MIDlet-Name:
CardGames
MIDlet-Version:
1.1.9
MIDlet-Vendor:
CardsRUS
MIDlet-1:
Solitaire, /Solitare.png, com.cardsrus.org.Solitare
MIDlet-2:
JacksWild, /JacksWild.png, com.cardsrus.org.JacksWild
MicroEdition-Profile:
MIDP-1.0
MicroEdition-Configuration:
CLDC-1.0
A leírófájl a JAR manifest fájlok
szokásos helyén van, tehát a JAR
archívumban a neve META-INF/manifest.mf. A legtöbb
fejlesztőeszköz a manifest fájlt képes
létrehozni a megfelelő helyen, ha erre kérik (pl. a JDK
jar programja a -m kapcsolóval utasítható erre).
A MIDlet JAR archívuma mellett kell legyen egy fájl, amit
alkalmazásleírónak neveznek. Ennek a
fájlnak a szokásos kiterjesztése JAD, ha
webszerveren van, a szerver text/vnd.sun.j2me.app-descriptor MIME
típussal kell kiszolgálja. Az
alkalmazásleíró nagyon hasonlít a JAR-on
belüli leírófájlra, több mező (pl.
MIDlet-Name, MIDlet-Version, MIDlet-Vendor) azonos KELL legyen
és szerepelnük kell mindkét fájlban. A
MIDlet-x mezőket viszont mindig a JAR-ban levő fájlból
veszi a az AMS, így ezek az
alkalmazásleíróban nem lehetnek.
Az alkalmazásleíró tartalmazza a JAR adatait,
melyek alapján a telefon már a JAD alapján
eldöntheti, képes-e a JAR letöltésére
(van-e hozzá elég memóriája) és
megtalálhatja a JAR-t magát. A telefonnak tehát a
JAD elérési útját (webes
letöltés esetén URL-jét) adjuk meg, a JAD
alapján a telefon eldönti, tudja-e a MIDletet fogadni, majd
a JAR-t ő tölti le a JAD információi alapján.
JAD példa:
MIDlet-Name:
CardGames
MIDlet-Version:
1.1.9
MIDlet-Vendor:
CardsRUS
MIDlet-Jar-URL:
http://www.cardsrus.com/games/cardgames.jar
MIDlet-Jar-Size:
7378
MIDlet-Data-Size:
256
A MIDlet-JAR-URL mutat a JAR fájlra, a MIDlet-JAR-Size megmondja
a JAR méretét bájtban, a MIDlet-Data-Size pedig a
MIDlet által igényelt minimális perzisztens
tárolóterületet. A MIDlet-Data-Size előfordulhat a
JAR-ban levő leírófájlban is, a MIDlet-JAR-URL
és a MIDlet-JAR-Size azonban nem. A MIDlet
letöltésekor az AMS ellenőrzi, hogy a JAR mérete
megfelel-e az alkalmazásleíróban szereplő
értéknek és megszakítja a
letöltést, ha különbséget észlel.
Minden MIDlethez egy osztály tartozik, amelyik a
javax.microedition.midlet.MIDlet osztály leszármazottja.
A MIDlet osztályt a JAR leírófájl
azonosítja, a MIDlet-x sorokban ez a harmadik elem.
MIDlet-1:
Solitaire, /Solitare.png, com.cardsrus.org.Solitare
A MIDlet életciklusának három állapota van.
Az AMS a MIDlet osztály metódusainak
hívásaival értesíti a MIDletet az
életciklus-változásokról.
- A MIDlet normálisan Destroyed
állapotban van. Ez azt jelenti, hogy a MIDlet
installálódott, de a JVM-be nem töltődött be.
- A MIDlet aktiválásakor Paused állapotba
kerül. Ez azt jelenti, hogy a MIDlet osztály és a
belőle hivatkozott osztályok betöltődtek a JVM-be a
JAR-ból. A MIDlet még nem foglal erőforrásokat.
- A MIDletet ezek után aktiválja az AMS. Ezt a MIDlet
startApp() metódusának meghívásával
teszi. A startApp() metódusban a MIDlet létrehozza a
felhasználói felületét és egyéb
módokon is kapcsolódik a környezetéhez (pl.
értesítéseket kér a
kommunikációs könyvtártól). A
startApp() sikeres lefutása után a MIDlet Active állapotba kerül.
- Bizonyos körülmények teljesülése
esetén a MIDlet futását szüneteltetni lehet,
ez a Paused állapot.
Ilyenkor az AMS meghívja a MIDlet pauseApp()
metódusát. Jól viselkedő MIDlet ilyenkor minimumra
csökkenti erőforráshasználatát és
várja az újabb startApp() hívást. Ennek az
állapotnak pontos definíciója vitatott. A Nokia
MIDlet implementációja pl. magától soha nem
szünetelteti a MIDlet futását, csak akkor, ha a
MIDlet azt maga kéri. A Motorola ezzel szemben úgy
implementálta ezt az állapotot, hogy valahányszor
a MIDlet eltűnik a képernyőről (pl. hívás
érkezett és a dialógusablak eltakarja) a MIDlet Paused állapotba
kerül. Robusztus MIDlet tehát lekezeli a pauseApp()
hívást, de nem okoz neki gondot az se, ha a pauseApp()-ot
sose hívják meg.
- Végül a MIDlet befejezi
pályafutását és az AMS törli. Mielőtt
ez megtörténik, az AMS meghívja a MIDlet destroyApp(
boolean unconditional ) metódusát. Ha a destroyApp()
paramétere false, a MIDlet megakadályozhatja az
állapotátmenetet, ha a destroyApp metódusban
MIDletStateChangeException-t dob. A paraméter true
értéke esetén a MIDletet mindenképpen
elpusztítja az AMS.
3.2. Felhasználói felület
A Jáva létező felhasználói felület
csomagjai (pl. AWT) nem alkalmasak mobiltelefonos használatra.
Egyrészt túl nagyok, másrészt
általában átlapolódó ablakokkal
modellezik a rendszert, ami a mobiltelefonos felhasználói
felületekre nem igaz. A MIDP-t kis méretű, tömegesen
használt mobiltelefonokra tervezték, amelyeknek tipikus
felhasználói felület-eleme a lista. Ilyen
felületekre a MIDP megalkotásának idején nem
volt alkalmas Jáva könyvtár, ezért
hozták létre a MIDP LCDUI
könyvtárát.
Az LCDUI tervezésekor a fő követelmények a
következők voltak:
- Támogatni kell olyan alkalmazásokat, amelyek teljes
ellenőrzést szeretnének a kijelző felett, pontosan meg
akarják mondani, mi hova kerüljön. Tipikusan ilyen
alkalmazás egy játék, ami a MIDP egyik
legfontosabb
alkalmazástípusa.
- Támogatni kell, hogy a lehető legegyszerűbb módon
lehessen írni egyszerű, űrlap-alapú
alkalmazásokat, amelyek üzleti rendszerek kliensoldali
részeként működhetnek.
- A telefon felhasználói felületére a
lehető legkevesebb megkötés vonatkozzon, minthogy a
telefongyártók ezen a területen versenyeznek.
Az LCDUI központi fogalma a
képernyő
(screen). A képernyő egy objektum, ami a
valóságos kijelzőn megjelenítendő tartalmat
jelképez. Az alkalmazás élete során a
felhasználó képernyőről képernyőre halad. A
képernyők három fő fajtája a következő:
- A telefon által meghatározott szerkezetű
képernyők összetett funkciókkal, pl. List vagy
TextBox. Ezeknek a képernyőknek a szerkezetét a program
nem változtathatja meg és nem adhat hozzá
újabb elemeket.
- A telefon által meghatározott kinézetű
képernyők, melyeket a program tölt fel tartalommal (pl.
Form). Ezekre a képernyőkre szövegmezők,
szövegbeviteli mezők, képek, stb. helyezhetők, a telefon
azonban maga dönti el, hogyan nézzen ki a tényleges
kijelzőkép.
- Képernyők, melyeknek tartalmát teljesen a program
határozza meg (Canvas és leszármazottjai). A
képernyő pontosan úgy jelenik meg, ahogy a program
megrajzolta.
A képernyők megjelenítését a Display
osztályon keresztül vezérelhetjük. Ennek
setCurrent metódusa beállítja az aktuális
képernyőt, ami ezután meg is jelenik a mobiltelefon
képernyőjén.
Display.getDisplay(
this ).setCurrent( f ); // f mutat a megjelenítendő
képernyőre
A képernyőket alapvetően két stílus
szerint kell létrehozni, ezek: Canvas és Screen (ezek
egyben az ősosztályai a stílust
megvalósító objektumoknak).
A Canvas stílus a következőképpen néz ki:
import
javax.microedition.lcdui.*;
public class MyCanvas extends Canvas {
public void keyPressed( int keycode ) {
// Billentyűnyomás eseménykezelő. A Canvas minden
eseménykezelőhöz
// implementál üres metódusokat, úgyhogy
mindegyik opcionális
...
}
public void paint( Graphics g ) {
// Meghívják, ha a Canvas-t újra kell festeni.
Minthogy ez
// abstract metódus a Canvas-ban, implementálni
kötelező.
}
}
A Canvas-nak
nagyjából egy tucat eseménykezelő metódusa
van, a keyPressed csak egy közülük. A
legérdekesebb a showNotify-hideNotify páros. A MIDlet nem
egyedül fut a telefonban és általában
még csak nem is a legfontosabb folyamat. Beérkezhet egy
hívás, amit azonnal jelezni kell a
felhasználóknak. Ilyenkor a felhasználói
felület olyan lehet, hogy a MIDlet képernyőjét
eltakarja egy üzenet, hogy hívás érkezett.
Ekkor a MIDlet hideNotify üzenetet kap, majd ha a képernyő
újra szabad, showNotify-t.
A MIDletek hívás közbeni viselkedése a
MIDlet specifikáció legzűrösebb pontja, amelyet a
Nokia és Motorola másként
implementált. Nokia telefonokon a MIDletet semmi nem
akadályozza a futásban, még akkor sem, ha a
telefon hívást fogad. A MIDlet háttérbe
kerülhet a hívás során (pl. üzenetablak
miatt), de ettől még fut. A
háttérbe-előtérbe kerülési
események hideNotify-showNotify események
formájában jutnak el hozzá. Motorola telefonokon a
hívás ideje alatt a MIDlet nem fut, hanem Paused
állapotba kerül.
A másik fontos stílus a Screen. A Screen alapelve, hogy a
MIDlet komplex felhasználói felület-elemek
megjelenítését kéri a telefontól,
melyet az kedve szerinti stílusban jelenít meg. A
Screen-típusú képernyők tehát
különbözőképpen jelennek meg
különböző telefonokon, cserébe viszont a
képernyő részletes rajzolásával nem kell
bajmolódjunk.
A Screen ősosztálya két specializált
leszármazotti ágnak.
- A List és TextBox egész képernyőt foglalnak
el, megjelenésük semmilyen módon nem
módosítható.
- A Form képernyőkre egy sor egyszerű
képernyőelem (statikus kép, szöveg,
szövegbeviteli mező, kiválasztólista, vonalkijelző
(gauge)) helyezhető el. A telefon így is szabadon
megválaszthatja, hogyan jeleníti meg a Form-ot.
Az egyszerűség kedvéért Screen-t a
Canvas-tól teljesen különböző programozói
stílusban kell létrehozni. Vegyünk példa
kedvéért egy Form-ot! A Form konstruktorában a
Form-hoz kell adni a képernyő elemeit, majd
eseménykezelőket kell installálni a Listener pattern
szerint. Példa:
import
javax.microedition.lcdui.*;
class MyListener implements ItemStateListener {
public void itemStateChanged( Item i ) {
// Lekezeli az i Item változásait
}
}
class MyForm extends Form {
TextField f1;
public MyForm() {
super( "Adder" ); // A Form
címkéje, pl. a képernyő tetején jelenhet meg
// Egy TextField Item-et ad a Form-hoz
f1 = new TextField( "Num1","", 10, TextField.NUMERIC
);
append( f1 );
// A Form változásairól a MyListener kapjon
értesítést
MyListener m = new MyListener();
setItemStateListener( m );
}
...
}
vagy
egyszerűbben:
import
javax.microedition.lcdui.*;
class MyForm extends Form implements ItemStateListener {
TextField f1;
public MyForm() {
super( "Adder" ); // A Form
címkéje, pl. a képernyő tetején jelenhet meg
// Egy TextField Item-et ad a Form-hoz
f1 = new TextField( "Num1","", 10, TextField.NUMERIC
);
append( f1 );
// A Form változásairól ez a MyForm egyed kapjon
értesítést
setItemStateListener( this );
}
public void
itemStateChanged( Item i ) {
// Lekezeli az i Item változásait
}
...
}
Másik
fontos Listener típus a CommandListener, ami Command egyedekhez
kapcsolódó eseményekről küld
értesítést (itt nem részletezzük, a
Command osztály egyedeivel saját opciómenü
vagy funkcióbillentyű-kezelést
valósíthatunk meg).
3.3. Perzisztens tárolás
Minthogy a MIDleteket installálják a telefonra és
hálózati kapcsolat nélkül is
működőképeseknek kell maradniuk, igen jól jön
egy perzisztens (=a MIDlet lelövése, sőt a telefon
kikapcsolása) után is megőrződő tárolóhely.
A MIDlet API egy rendkívül egyszerű rendszert
kínál, ez a Record Management System (RMS) API. Az RMS
funkciói a következők:
- Névvel azonosított, a MIDlet sorozathoz
tartozó tároló (RecordStore)
létrehozása. Ha egy MIDlet sorozat létrehozott egy
RecordStore-t, az végigköveti a MIDlet sorozatot az
életén át (a MIDlet sorozat törlése
során törlődik a RecordStore is), más MIDlet sorozat
nem tud hozzáférni. A RecordStore neve a MIDlet sorozat
számára kell egyedi legyen, egy MIDlet sorozat több
RecordStore-t is létrehozhat, de azok neve
különböző kell legyen.
- Rekordok hozzáadása a RecordStore-hoz ill. rekordok
kiolvasása a RecordStore-ból. Egy rekord egy egyszerű
bájtsorozat. A rekordokat a számuk azonosítja, az
rekordazonosító 1-ről indul és minden rekord
hozzáadásánál eggyel növekszik.
Ezen felül az RMS még néhány egyszerű
szolgáltatást nyújt, pl.
változásfigyelő eseménykezelőt lehet a
RecordStore-hoz kötni, a rekordok utolsó
változtatási idejét le lehet kérdezni, stb.
A RecordStore mérete nem túl nagy, pl. a Nokia 6310-ben
csupán 20Kbájt az összes MIDlet sorozat
számára. A méret azonban jelentősen nőtt az
utóbbi időben, a Nokia legújabb nem Symbian telefonjaiban
a teljes méret eléri az 1 MBájtot, Symbian-os
telefonokban ennél nagyobb is lehet.
3.4. Hálózatkezelés
A MIDP hálózatkezelési osztályai a
CLDC GCF-re épülnek. A MIDP kötelező
hálózati protokollja a HTTP, ennek megfelelően MIDP
implementációknak képeseknek kell lenniük
HTTP URL-t fogadni a javax.microedition.io.Connector osztály
open metódusában. Maga a kommunikáció nem
feltétlenül HTTP protokollon folyik, de a protokoll
funkcionalitása HTTP-vel egyenértékűnek kell
legyen (pl. WAP).
3.5. MIDP 2.0
Nagyon röviden teszek említést a MIDP új,
2.0-ás változatáról (JSR-118)
.Ez felfelé
kompatibilis a MIDP 1.0-val. A legjelentősebb változások
a következők:
- Biztonsági mechanizmus, ami lehetővé teszi
megbízható, digitális
aláírással ellátott MIDleteknek, hogy
érzékeny funkciókhoz (pl.
üzenetküldés,
hívásindítás) férjenek hozzá.
- Bővített kommunikációs könyvtár,
ami lehetővé teszi, hogy MIDletek üzenetekre
várjanak és a beérkező üzenetek
aktiválják őket.
- Javított játéktámogatás, pl.
kettős képernyőbuffer támogatása, sprite-ok,
layer-ek, jobb nyomógombfigyelés (le lehet kérdzni
azt is, hogy egy gombot éppen nyomva tartanak-e).
- Multimédia támogatás, különös
tekintettel a hangokra.