Fejlett Webes Technológiák II. Bilicki Vilmos 2002.10.07
A mai előadás tartalma: MIDP (Mobile Information Device Profile) Célok, Követelmények Architektúra MIDP könyvtárak: Rendszer Időzítők Hálózatkezelés Tartós Tárolás Alkalmazások Felhasználói interfész
Célok, Követelmények Követelmények: Képernyő 96x54 1 bit színmélység 128 kbyte nem illékony a MIDP komponensek számára 8 kbyte nem illékony az alkalmazás adatok számára 32 kbyte a Java runtime számára Kétirányú hálózatkezelés
Hatókör: Alkalmazások (a MIDP alkalmazás szemantikája, hogyan futtatjuk) Felhasználói felület UI (kijelző, bevitel) Állandó tár Hálózatkezelés Időzítők
Architektúra
MIDP könyvtárak Rendszer (System Functions) Időzítők (Timers) Hálózatkezelés (Networking) Tartós Tárolás (Persistent Storage) Alkalmazások (Applications) Felhasználói interfész (User Interface)
Rendszer (System Funtions) CLDC-n alapul System properties: microedition.locale a jelenlegi beállítás nyelvkód-ORSZÁGKÓD (en-US, fr-FR, hu-HU) microedition.profiles (a MIDP verzió) Erőforrások: java.lang.Class getResourceAsStream(String name) System.exit (MIDlet.notifyDestroyed) Runtime.exit (MIDlet.notifyDestroyed)
Időzítők (Timers) I. Osztályai: java.util.Timer java.util.TimerTask segítségével egy párhuzamos szálat indíthatunk mely adott időközönként lefuttatja a run metódust az alosztályt a TimerTask osztályból kell származtatnunk meg kell valósítanunk a run metódust amikor példányosítjuk akkor létrehozunk egy új szálat is, melyet a schedule metódus segítségével elindítjuk A Timer objektumokat egy háttér szál menedzseli (az egyes feladatoknak rövideknek kell lenniük)
Időzítők (Timers) II. Metódusok: public void schedule (TimerTask task, Date firstTime, long period) – nem veszi figyelembe a csúszást (animáció) public void scheduleAtFixedRate (TimerTask task, Date firstTime, long period) – megpróbálja kiküszöbölni a csúszást (hálózati időzítések) public boolean cancel ()
Időzítők (Timers) III. az időzítésre megadhatunk konkrét időpontot is: Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, 23); calendar.set(Calendar.MINUTE, 1); calendar.set(Calendar.SECOND, 0); Date time = calendar.getTime(); timer = new Timer(); timer.schedule(new RemindTask(), time);
Időzítők (Timers) IV. System.out.println("Time's up!"); class RemindTask extends TimerTask { public void run() System.out.println("Time's up!"); } public static void main(String args[]) System.out.println("About to schedule task."); new Reminder(5); System.out.println("Task scheduled."); import java.util.Timer; import java.util.TimerTask; public class Reminder { Timer timer; public Reminder(int seconds) timer = new Timer(); timer.schedule(new RemindTask() , seconds*1000); }
Időzítők (Timers) V. class RemindTask extends TimerTask { int numWarningBeeps = 3; public void run() { if (numWarningBeeps > 0) System.out.println("Beep!"); numWarningBeeps--; } else { System.out.println("Time's up!"); System.exit(0); } } } public static void main(String args[]) { System.out.println("About to schedule task."); new AnnoyingBeep(); System.out.println("Task scheduled."); } } import java.util.Timer; import java.util.TimerTask; public class AnnoyingBeep { Timer timer; public AnnoyingBeep() { timer = new Timer(); timer.schedule(new RemindTask(), 0, 1*1000); }
Hálózatkezelés I. GenericConnection framework HTTP protokoll egy része használható Transzparens szolgáltatást kell nyújtania (nem kell tudnunk arról, hogy esetleg nem IP hálózatot is használunk)
Hálózatkezelés II.
HTTP kapcsolat I. HTTP 1.1 Osztályok: Intefészek: HEAD GET POST javax.microedition.io Intefészek: public interface HttpConnection extends javax.microedition.io.ContentConnection setRequestMethod setRequestProperty
HTTP kapcsolat II. HttpConnection openConnection() throws IOException { HttpConnection result; result = (HttpConnection) Connector.open(servletUrl); result.setRequestProperty("User-Agent", System.getProperty("microedition.profiles")); result.setRequestProperty("Content-Type", "application/binary"); result.setRequestMethod(HttpConnection.POST); return result; }
HTTP kapcsolat III. DataOutputStream openDataOutputStream(HttpConnection conn) throws ApplicationException { try { return conn.openDataOutputStream(); } catch (IOException ioe) { throw new ApplicationException(ErrorConstants.CANNOT_CONNECT);
HTTP kapcsolat IV. try { conn = openConnection(); out = openDataOutputStream(conn); out.writeInt(MessageConstants.CREATE_USER); out.writeUTF(c.getUsername()); out.writeUTF(c.getPassword()); out.writeUTF(zipCode); out.writeUTF(creditCardNumber); out.close(); in = openDataInputStream(conn); } catch (IOException ioe) { throw new ApplicationException(ErrorConstants.CANNOT_CONNECT);} finally { closeAll(conn, out, in); }
Tartós Tárolás javax.microedition.rms Record Management Store (RMS) Max 8kbyte A MIDletek futtatása között is megőrzik az értéküket Minden MIDlet-nek saját RMS A neve max. 32 unicode karakter (egyedinek kell lennie) Egymás RMS-ét elérhetik (nincs zárolás, a programozónak kell gondoskodnia erről) Módosítási idő Verzió
Rekordok Bájt tömb Egyedi id: Módosítás: recordId (elsődleges kulcs, az első 1, …) Módosítás: DataInputStream DataOutputStream ByteArrayOutputStream ByteArrayInputStream
Fontosabb metódusok public static RecordStore openRecordStore (String recordStoreName, boolean createIfNecessary) public void closeRecordStore () public int addRecord (byte[] data, int offset, int numBytes) public void setRecord (int recordId, byte[] newData, int offset, int numBytes) public void deleteRecord (int recordId) public int getNumRecords () public int getSizeAvailable ()
Record store példa try { bout = new ByteArrayOutputStream(); dout = new DataOutputStream(bout); dout.writeUTF(c.getUsername()); dout.writeUTF(c.getPassword()); byte[] record = bout.toByteArray(); recordStore.addRecord(record, 0, record.length); }
Rekord szűrés I. try { RecordFilter rf = new RecordFilter() { public boolean matches(byte[] candidate) { return candidate[0] == MOVIES_TYPE; } }; RecordEnumeration re = listingsRecordStore.enumerateRecords(rf, null, false); int recordId = 0;
Rekord szűrés II. int recordId = 0; if (re.numRecords() > 0) { recordId = re.nextRecordId(); byte[] record = listingsRecordStore.getRecord(recordId); in = new ByteArrayInputStream(record, 5, record.length-5); din = new DataInputStream(in); result = MovieListModel.fromStream(din); if (!result.isExpired()) { return result; }
Rekord szűrés III. public static MovieListModel fromStream(DataInputStream in) throws IOException { long expiryDate = in.readLong(); Movie[] movies = new Movie[in.readInt()]; for (int i = 0; i != movies.length; i++) { movies[i] = Movie.fromStream(in); } return new MovieListModel(expiryDate, movies);
Alkalmazások MIDlet csomag: Futtató környezet (MIDlet osztályból származik) Csomagolás (egy JAR fájlban egy vagy több midlet) Alkalmazás leíró (.jad ) MIDlet-Name MIDlet-Version MIDlet-Vendor MIDlet-Jar-URL MIDlet-Jar-Size Alkalmazás életciklus (MIDlet osztályból származik) Paused Active Destroyed
Minta JAD fájl 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
import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class HelloVilag1 extends MIDlet implements CommandListener { public HelloVilag1() { } protected void pauseApp() { protected void startApp() throws MIDletStateChangeException { protected void destroyApp(boolean p0) throws MIDletStateChangeException { public void commandAction(Command p0, Displayable p1) {
Felhasználói interfész javax.microedition.lcdui Felső szintű (high level) Készülék független Nincs sok beleszólás a kinézetbe Alsó szintű (low level) Jobban kihasználja a készülékek képességeit Teljes hozzáférés a képernyőhöz Egyszerű események is használhatóak Elérhetjük a az egyes beviteli elemeket
Osztály hierarchia Képernyő (screen) Eseménykezelés Képernyőkezelés egyszerre csak egy lehet belőle látható Három típus: Képernyő (komplex elemek: List, Text Box) Általános képernyő (Form, itt lehet 2 szövegmező …) Alacsony szintű elemekkel foglalkozó képernyők Display.setCurrent()
Elemek I. Alert - Figyelmeztető képernyő mely egy adott ideig várakozik mielőtt egy másik képernyőre váltana AlertType - A figyelmeztetés típusa Canvas – Az alacsony szintű grafika alposztálya ChoiceGroup – A Form elembe helyezhető válaszható elmeket magában foglaló elem Command – Egy esemény szemanitkus leírására szolgál DateField – A Form elemen elhelyezhető dátum beviteli mező Display – A képernyőkezelőt képviseli Displayable – Olyan objektum mely kihelyezhető a képernyőre
Elemek II. Font – A betűk paraméterei Form – Több elemet magába foglaló elem Gauge - Grafikon Graphics - segítségével rajzolhatunk 2D-ben Image – Kép adatai tartalmazza ImageItem – A kép megjelenítését definiálja Form vagy Alert elmen
Elemek III. Item – A Form vagy Alert elemekhez adható elemek ősosztálya List - Lista Screen – A magas szintű grafikai elemek ősosztálya StringItem – Karakterlácot tartalmazó elem TextBox – Szöveg bevitele kiírása TextField – A Form elemre elhelyezhető szőveg kiírására szolgáló elem Ticker – Gördülő szöveget tartalmazó elem
Eseménykezelés Absztrakt parancsok Alacsony szintű események Command – Displayable objektum addCommand Néhány alapértelmezett parancs már fenn lehet Label, CommandType, Priority void commandAction(Command c, Displayable d); void itemStateChanged(Item item); Alacsony szintű események public void keyPressed(int keyCode); public void keyReleased(int keyCode); public void keyRepeated(int keyCode); paint() hívások run() metódus hívások
Eseménykezelés class TetrisCanvas extends Canvas { int leftKey, rightKey, downKey, rotateKey; void init () { leftKey = getKeyCode(LEFT); rightKey = getKeyCode(RIGHT); downKey = getKeyCode(DOWN); rotateKey = getKeyCode(FIRE); } public void keyPressed(int keyCode) { if (keyCode == leftKey) { moveBlockLeft(); } else if (keyCode = rightKey) { ...}}}
Eseménykezelés package minta; import javax.microedition.midlet.*; import javax.microedition.lcdui.*; public class HeloVilag extends MIDlet implements CommandListener { public HeloVilag() { } protected void pauseApp() { protected void startApp() throws MIDletStateChangeException { Displayable current = Display.getDisplay(this).getCurrent(); if(current == null) { Kepernyo kepernyo = new Kepernyo("Minta", "Tartalom",this); Display.getDisplay(this).setCurrent(kepernyo); Eseménykezelés
public void commandAction(Command p0, Displayable p1) { } protected void destroyApp(boolean p0) throws MIDletStateChangeException { void exitRequested() { try{ destroyApp(false); notifyDestroyed(); catch(MIDletStateChangeException e)
Alacsony szintű grafika package minta; import javax.microedition.lcdui.*; public class Kepernyo extends TextBox implements CommandListener { private final HeloVilag midlet; private final Command exitCommand; public Kepernyo(String cim, String tartalom, HeloVilag midlet) { super( cim, tartalom, 256, 0); this.midlet = midlet; exitCommand = new Command("Kilep", Command.EXIT, 1); addCommand(exitCommand); setCommandListener(this); } public void commandAction(Command c, Displayable p1) { if (c == exitCommand) { midlet.exitRequested(); } } Alacsony szintű grafika
Eredmény
Forrás Mobile Information Device Profile (JSR-37) JCP Specification Java 2 Platform, Micro Edition, 1.0a (http://jcp.org/aboutJava/communityprocess/final/jsr037/index.html )