|
Miniguida su J2ME | |||||||||||
| di Dersew | |||||||||||
|
Definito dalla Sun Microsystems, fu' introdotto nel 1995 come linguaggio orientato agli oggetti e definito per essere trasportabile su architetture differenti e per essere eseguito da browser, il compilatore Java traduce il programma sorgente in una rappresentazione speciale detta bytecode. Il bytecode Java non è un linguaggio macchina di una CPU particolare, ma di una macchina virtuale Java. L'interprete traduce il bytecode nel linguaggio macchina e lo esegue. Un compilatore Java compiler non è legato ad una particolare macchina. Java è indipendente dall'architettura della macchina. J2ME (Java 2 Micro Edition) deriva da Java 2 Standard Edition J2SE, ottimizzato e "leggero" per girare su cellulari e Pda di ultima generazione. Più sinteticamente, si tratta della versione per dispositivi portatili di Java. È possibile dar vita a piccoli programmi (Generalmente di dimensione inferiore ai 100 KB), chiamati MIDLet ed eseguibili su dispositivi dotati di una Virtual Machine adatta. J2ME è una architettura che si rivolge ad una moltitudine di apparecchi anche profondamente diverse tra di loro (Telefonini, PDA, elettrodomestici, ...). per questo motivo SUN ha definito una architettura ed una serie di librerie di classi per affrontare in modo univoco la programmazione di questi dispositivi, introducendo i concetti di configurazione e di profili. J2ME comprende due livelli di configurazione (CDC e CLDC) ed inoltre il livello "Profile" MIDP. Un profilo è una estensione della configurazione; fornisce le librerie per permettere ai programmatori di scrivere applicazioni per un particolare tipo di dispositivo. Il MIDP è il profilo più famoso e sara' quello trattato in questa miniguida. Prevede un sistema di GUI (Graphical User Interface), API (Application Programming Interface) di base per giochi in 2D, possibilita' di effettuare connessioni di rete, ecc. Attualmente esistono due versioni di MIDP, rispettivamente MIDP 1.0 e MIDP 2.0. MIDP 2.0 estende le funzionalita' di MIDP 1.0. Cosa serve per iniziare? Java 2 sdk 1.4.2 (JDK) J2ME Wireless Toolkit (WTK) for CLDC Un editor di testo (Scite, UltraEdit, etc.) Documentazione J2ME (In inglese, assolutamente indispensabile) Un po' di buona volonta' (Anch'essa indispensabile) Per poter cominciare a creare una prima applicazione J2ME occorre quindi il J2ME Wireless Toolkit (WTK), messo a disposizione dalla Sun, che consente di compilare e testare con degli emulatori il codice che scriviamo. L'installazione del J2ME WTK richiede soltanto la presenza del Java sdk installato (JDK). Una volta sviluppato il nostro software possiamo infine creare l'eseguibile da inviare al telefono L'applicazione da noi creata presentera' un'estenzione ".jar" e sara' accompagnata inoltre da un altro file, detto descrittore e con estensione ".jad". Il descrittore JAD viene utilizzato per eseguire dei controlli base da parte del software di gestione applicazioni del dispositivo portatile: controllo versioni, dimensioni del jar file, nome autore ecc... La scrittura di una MIDlet è abbastanza semplice ed intuitiva. Si deve: 1) Estendere la classe javax.microedition.midlet.MIDlet 2) Implementare i metodi startApp, pauseApp, destroyApp
void startApp () segnala che la MIDlet è stata posta nello stato di attivita' (Active State) void pauseApp () segnala che la MIDlet sta entrando nello stato di pausa (Paused State) void destroyApp (boolean unconditional) segnala che la MIDlet sta per terminare la sua esecuzione (Passando quindi al Destroyed State) Il package javax.microedition.lcdui (User Interface Package) contiene tutte le classi per creare le interfacce utente sul display Con tali classi è possibile gestire le finestre per l'inserimento dei dati con campi di testo, selezioni a scelta multipla, date o ore in formato grafico, immagini, ecc. Caricare un'immagine è semplice e immediato. Bisogna però gestire le eccezioni
La Classe display Rappresenta il manager del display e dei dispositivi di input Contiene i metodi per recuperare le proprieta' del dispositivo e per richiedere che un oggetto sia visualizzato sul dispositivo C'è esattamente una solo istanza di Display per MIDlet e l'applicazione può ottenere in qualsiasi momento tale istanza tramite il metodo: 1)static Display getDisplay (MIDlet m) 2)boolean isColor () restituisce true se il dispositivo supporta i colori 3)int numColors () restituisce il numero di colori o di livelli di grigio (se isColor() è false) supportati 4)boolean vibrate (int duration) attiva la vibrazione per "duration" ms. 5)void setCurrent (Displayable nextDisplayable): imposta l'oggetto che deve essere visualizzato sul display (può essere presente solo un oggetto per volta) La Classe displayable La classe Displayable è la superclasse di tutti gli oggetti direttamente visualizzabili sul display Tutti gli oggetti Displayable hanno le seguenti proprieta': zero o più oggetti Command per le operazioni utente un CommandListener che riceve le notifiche di selezione dei comandi (si noti che si può impostare un solo CommandListener) la possibilita' di aggiungere un titolo ed un eventuale testo scorrevole (tramite la classe Ticker) void addCommand (Command cmd) aggiunge un comando int getHeight (), int getWidth () restituiscono altezza e larghezza del Displayable boolean isShown () verifica se l'oggetto è attualmente visibile sul display void setTicker (Ticker ticker) imposta il Ticker void setTitle (String s) imposta il titolo del Displayable void setCommandListener (CommandListener l) imposta il listener dei comandi La Classe form Un Form è uno Screen che può contenere oggetti di vario tipo (Immagini, campi di testo, campi per l'inserimento di una data, barre di progresso, etc.) In generale qualsiasi sottoclasse della classe Item può essere contenuta all'interno di un Form Costruttori: Form(String title) Form(String title, Item[] items)
La Classe Command La classe Command definisce le operazioni che l'utente può svolgere. L'utilizzo più comune di Command è fornire un modo per navigare tra i diversi Displayable dell'applicazione. Il posizionamento, l'aspetto ed il modo di interazione dell'utente con i Command è delegato al dispositivo, Il tutto semplifica di molto il lavoro del programmatore. Ogni Command ha un tipo ed una priorita'. Tipi e priorita' permettono al dispositivo di posizionare i Command in punti standard del display per esempio l'operazione "Indietro" potrebbe essere mappata in basso a destra. Costruttori Command(String label, int type, int priority) Command(String shortLabel, String longLabel, int type, int priority) BACK: comando per tornare allo schermo precedente CANCEL: comando per indicare una risposta negativa OK: comando per indicare risposta positiva HELP: comando per l'help on line EXIT: comando usato per uscire dall'applicazione ITEM: comando (di item) specifico dell'applicazione SCREEN: comando (di schermo) specifico dell'applicazione STOP: comando per interrompere qualcosa int getCommandType(): restituisce il tipo di comando String getLabel(): restituisce l'etichetta breve String getLongLabel(): restituisce l'etichetta estesa int getPriority(): restituisce la priorita' del comando
Per intercettare gli eventi di comando bisogna implementare l'interfaccia CommandListener e definire il metodo void commandAction(Command c, Displayable d): il metodo lanciato quando viene attivato il comando c sul Displayable d
La Classe Screen Screen è la superclasse comune a tutti gli elementi di alto livello di una GUI in J2ME Non aggiunge alcun metodo a Displayable e serve solo come base comune per le classi: Alert Form List TextBox La Classe Alert Uno Screen per la notifica di messaggi all'utente, Possono essere definiti diversi tipi di Alert a seconda dell'utilizzo che se ne deve fare, Costruttori Alert(String title) Alert(String title, String alertText, Image alertImage, AlertType alertType) alertType può assumere i valori ALARM, CONFIRMATION, ERROR, INFO, WARNING ALARM: notifica di una particolare condizione (es. il sopraggiungere di una data) CONFIRMATION: conferma dell'esecuzione di un'operazione (es. password inserita valida) ERROR: notifica di una condizione di errore (es. password inserita non valida) INFO: visualizzazione informazioni generiche WARNING: segnalazione della potenziale pericolosita' di un'operazione richiesta (es. richiesta di cancellazione dati) void setIndicator(Gauge indicator): imposta un eventuale indicatore di attivita' void setTimeout(int time): imposta il tempo di durata di visualizzazione (FOREVER indica durata infinita) Quando un Alert viene chiuso l'ultimo Displayable usato viene ri-visualizzato a meno di avere usato il metodo di Display void setCurrent(Alert alert, Displayable next): imposta alert come Displayable corrente e next come prossimo Displayable. Alert alert = new Alert ("Il nostro Splash Screen", "Benvenuti!!", splash_img, AlertType.INFO); display.setCurrent(alert, form); La Classe List Uno Screen per la visualizzazione di una lista Ogni elemento ha una stringa ed una icona Possono essere definite tre tipi di liste: implicita, a scelta esclusiva ed a scelta multipla Costruttori List(String title, int listType) List(String title, int listType, String[] stringElements, Image[] imageElements) ListType può essere IMPLICIT, EXCLUSIVE e MULTIPLE gli elementi della lista sono veri e propri Command e quindi lanciano eventi di comando, quando l'utente seleziona un elemento l'eventuale CommandListener associato alla lista sara' attivato, per verificare se un evento è stato lanciato da un elemento della lista bisogna controllare se il Command passato come parametro è List.SELECT_COMMAND Liste a scelta esclusiva: la selezione di un elemento esclude la selezione degli altri equivalenti ai gruppi di radiobutton Liste a scelta multipla: la selezione di un elemento non esclude la selezione degli altri equivalenti ai gruppi di checkbox int append(String stringPart, Image imagePart): aggiunge un elemento nella lista int getSelectedIndex(): restituisce l'indice dell'elemento selezionato boolean isSelected(int n): verifica se l'elemento di posizione n è selezionato int size(): restituisce il numero di elementi della lista
ESEMPIO
La Classe texbox Uno Screen per l'inserimento di testo. Possono essere definiti diversi tipi di TextBox a seconda dell'utilizzo che se ne deve fare Costruttore TextBox(String title, String text, int maxSize, int constraints) constraints può essere ANY, DECIMAL, EMAILADDR, NUMERIC, PASSWORD, PHONENUMBER, URL ANY: l'utente può inserire qualsiasi valore DECIMAL: l'utente può inserire solo valori numerici decimali EMAILADDR: i dati rappresentano una email NUMERIC: l'utente può inserire solo valori interi PASSWORD: i dati rappresentano una password PHONENUMBER: i dati rappresentano un numero telefonico URL: i dati devono rappresentare un URL String getString(): restituisce il testo della TextBox void setString(String text): imposta il testo della TextBox void delete(int offset, int length): cancella una parte del testo void insert(String src, int position): inserisce un testo int setMaxSize(int maxSize): imposta il massimo numero di caratteri accettati int size(): restituisce il numero di caratteri attualmente contenuti nella TextBox L'utilizzo delle API di alto livello per la creazione delle GUI (Graphic User Interface) fornisce la massima portabilita' e facilita' di sviluppo Tuttavia alcune applicazioni richiedono un controllo più fine sulla GUI L'API di basso livello per la creazione delle GUI è progettata per quelle applicazioni che necessitano invece di posizionamento e controllo preciso degli elementi grafici e di un accesso a basso livello agli eventi di input Tipici esempi di componenti che dovrebbero necessitare di tale approccio sono un game board, un diagramma, un grafico, ecc. Usando tale API un'applicazione può: Controllare con precisione cosa è disegnato sul display Gestire gli eventi di basso livello (keypressed, keyreleased, ecc.) Accedere direttamente alle key (tasti, softkey, ecc.) ed ad altri dispositivi di input Per utilizzare direttamente l'API di basso livello bisogna conoscere le classi Graphics e Canvas Graphics ci fornisce metodi per disegnare rettangoli, archi, scrivere testo, impostare il colore degli elementi, conoscere le dimensioni del display e i colori disponibili ecc. Canvas invece fornisce: La "superficie" e le dimensioni del display Le callback usate per gestire gli eventi ed i metodi per disegnare sul display La combinazione della capacita' di gestire gli eventi del Canvas e delle capacita' di disegno del Graphics permette di avere il completo controllo sullo schermo Queste classi possono essere usate per esempio per: Creare nuovi schermi personalizzati Implementare videogame Manipolare immagini Un Canvas non deve necessariamente avere accesso all'interno schermo di un dispositivo J2ME, Certe aree dello schermo possono essere riservate per altri scopi (ad esempio visualizzare lo stato della rete o della batteria), Inoltre l'uso di un titolo, di un Ticker e/o di oggetti Command possono ulteriormente ridurre lo spazio disponibile al Canvas. Le dimensioni di un Canvas possono essere ottenute tramite i metodi di Displayable: int getWidth(), int getHeight() Inoltre si può essere informati quando le dimensioni variano per qualche motivo tramite il metodo: void sizeChanged(int w, int h): lanciato quando variano le dimensioni del Canvas Ciò permette di (eventualmente) riadattare in tempo reale il layout dell'applicazione Se un'applicazione vuole una visualizzazione a tutto schermo allora bisogna lanciare il metodo void setFullScreenMode(boolean mode): attiva/disattiva la visualizzazione a tutto schermo Alcuni dispositivi potrebbero anche nascondere gli indicatori di stato del sistema Per dire al dispositivo cosa deve disegnare in un Canvas bisogna implementare il metodo void paint(Graphics graphics): descrive cosa deve essere disegnato nel Canvas Quando si vuole che un Canvas si ridisegni non si deve chiamare direttamente tale metodo, ma il metodo: void repaint(): forza il ridisegno del Canvas In J2ME i colori possono essere definiti solo: come terne di interi RGB come un unico intero opportunamente formattato (0x00RRGGBB) Esiste il solo modello di colore RGB Non esiste il concetto di trasparenza Per impostare il colore della classe Graphics bisogna usare i metodi: void setColor(int RGB), void setColor(int red, int green, int blue): impostano il colore della classe Graphics Dopo questo comando tutto ciò che verra' disegnato usera' il colore specificato Il colore di default è il nero! Le stringhe in J2ME vengono "disegnate" mediante la classe Font contenente tutte le caratteristiche tipografiche necessarie. Tale classe può richiamare solo un numero limitato di font standard. È possibile impostare gli stili corsivo, grassetto e sottolineato ed ovviamente la dimensione del font Per definire un Font si possono utilizzare i seguenti metodi statici: Font getDefaultFont(): restituisce il font di default del dispositivo Font getFont(int fontSpecifier): restituisce un font standard del dispositivo (fontSpecifier può essere FONT_INPUT_TEXT, FONT_STATIC_TEXT) Font getFont(int face, int style, int size): restituisce un font ad hoc Face può essere FACE_SYSTEM, FACE_MONOSPACE, FACE_PROPORTIONAL Style può essere STYLE_PLAIN, o una combinazione di STYLE_BOLD, STYLE_ITALIC e STYLE_UNDERLINED Size può essere SIZE_SMALL, SIZE_MEDIUM, SIZE_LARGE Per impostare il Font bisogna usare il metodo void setFont(Font f): imposta il Font del contesto grafico In J2ME esistono tre diversi tipi di eventi di basso livello Key Event: eventi generati dalla pressione dei tasti della tastiera del dispositivo Action Event: particolari key event collegati con dei tasti appositi per i giochi Pointer Event: eventi generati da dispositivi di puntamento Key Event Gestire i Key Event di un Canvas significa implementare i metodi void keyPressed(int keyCode): lanciato quando un tasto viene premuto void keyReleased(int keyCode): lanciato quando un tasto viene rilasciato void keyRepeated(int keyCode): lanciato quando un tasto viene tenuto premuto Ovviamente in J2ME esistono delle costanti per identificare i vari tasti Tali costanti sono definite nella classe Canvas KEY_NUM0, ..., KEY_NUM9: identificano i numeri da 0 a 9 KEY_POUND: identifica il tasto "#" KEY_STAR: identifica il tasto "*" La classe Canvas dispone inoltre di alcuni metodi per gestire in maniera portabile gli Action Event (anche chiamati Game Action) L'API definisce un insieme di costanti che possono essere mappate dall'implementazione MIDP su particolari tasti del dispositivo Tali costanti sono: UP, DOWN, LEFT, RIGHT, FIRE, GAME_A, GAME_B, GAME_C e GAME_D Una applicazione può individuare il corretto codice di Action Event generato tramite il metodo int getGameAction(int keyCode): restituisce il codice dell'Action Event Se invece dato un codice di Action Event si vuole conoscere un codice di Key Event associato si deve usare il metodo: int getKeyCode(int gameAction): restituisce un codice di Key Event associato al codice di Action Event Pointer Event I palmari e gli smart phone solitamente sono dotati di particolari dispositivi di puntamento (ad esempio i pennini) La classe Canvas ha dei metodi che permettono di gestire gli eventi generati da tali dispositivi void pointerPressed(int x, int y): lanciato quando il puntatore viene premuto sul display void pointerReleased(int x, int y): lanciato quando il puntatore viene sollevato dal display void pointerDragged(int x, int y): lanciato quando il puntatore viene trascinato sul display Ovviamente non tutti i dispositivi supportano queste caratteristiche e quindi non supporteranno nemmeno i Pointer Event È possibile comunque sapere se un dispositivo supporta o meno tali eventi tramite i metodi boolean hasPointerEvents(): verifica se il dispositivo supporta i Pointer Event di pressione e rilascio boolean hasPointerMotionEvents(): verifica se il dispositivo supporta i Pointer Event di trascinamento L'api per i giochi I video game si sono dimostrati essere i tipi di applicazioni J2ME più usati, Per tale ragione nella versione MIDP 2.0 è stata inserita un'intera libreria specificatamente progettata per lo sviluppo di video giochi. Tale libreria si trova nel package javax.microedition.lcdui.game Questa API fornisce molte facilitazioni per lo sviluppatore: 1)Semplifica lo sviluppo e fornisce un ambiente più familiare agli sviluppatori di video game 2)Ciduce la dimensione e la complessita' dell'applicazione fornendo funzionalita' e metodi altrimenti da sviluppare a mano 3)Poiché l'API può essere implementata usando codice nativo essa potrebbe incrementare le performance finali Il package.javax.microedition.lcdui.game GameCanvas: fornisce le funzionalita' per la gestione di base dello schermo (estende Canvas),in generale semplifica lo sviluppo ed aumenta le performance Layer: una delle novita' più consistenti introdotte con queste API,permette di isolare un elemento grafico dal contesto grafico e gestirne in questo modo la posizione, la dimensione e la visibilita' LayerManager: classe di servizio che facilita la gestione dei Layer, indispensabile quando si utilizza un considerevole numero di oggetti Layer Sprite: la classe più utilizzata quando si sviluppa un gioco, permette di gestire più immagini in un'unica immagine, in modo da semplificarne l'utilizzo e ridurne la dimensione (una PNG 100x10 è più leggera di 10 PNG 10x10) TiledLayer: permette di gestire un'area sullo schermo composta da tante "mattonelle" che possono essere tante immagini diverse in questa maniera si possono realizzare delle interessanti animazioni di sfondo per i giochi che si vogliono sviluppare La Classe layer La classe astratta Layer rappresenta l'entita' base che può essere visualizzata sullo schermo, Un Layer ha un suo bound rettangolare e può essere visibile o invisibile, può essere renderizzato usando un qualsiasi oggetto Graphics e chiamando il suo metodo void paint(Graphics g): disegna il Layer La classe Layer ha due sottoclassi: Sprite TiledLayer Sfortunatamente la classe Layer non può essere sottoclassata dal programmatore,Questo poiché potrebbe compromettere l'abilita' di incrementare le performance tramite l'uso di codice nativo nelle API Le sottoclassi di Layer possono essere disegnate in qualsiasi momento,Tale disegno utilizzera' le informazioni del Layer stesso (posizione, visibilita', ecc.), La posizione del Layer è sempre relativa all'attuale origine delle coordinate dell'oggetto Graphics int getWidth(), int getHeight(): restituiscono larghezza ed altezza del Layer int getX(), int getY(): restituiscono la posizione del Layer void setPosition(int x, int y): imposta la posizione del Layer void move(int dx, int dy): muove il Layer boolean isVisible(): restituisce la visibilita' del Layer void setVisible(boolean b): imposta la visibilita' del Layer La Classe sprite In qualsiasi gioco di successo un contributo fondamentale viene dato dalla qualita' grafica, Molti degli oggetti in un gioco vengono "categorizzati" come uno speciale tipo di grafica detto sprite. Un sprite può essere qualsiasi cosa: un proiettile, un mostro, il personaggio del gioco, item di energia o danneggiamento, chiavi, porte, ecc. Solitamente gli sprite sono animati, Tale animazione è ottenuta tramite una sequenza di immagini dello stesso sprite ognuna leggermente diversa dalle altre per simulare l'animazione, Ogni immagine di questo insieme è solitamente chiamata frame,Questi frame possono essere visualizzati in sequenza o meno. Esistono tre costruttori Sprite(Image image): crea un sprite non animato a partire da un'immagine Sprite(Image image, int frameWidth, int frameHeight): crea uno sprite animato a partire da un'immagine; ogni singolo frame è individuato da un intero univoco ed ha dimensione frameWidthxframeHeight Sprite(Sprite s): crea uno sprite da un altro sprite Per disegnare uno sprite è sufficiente chiamare il suo metodo paint, ovviamente lo sprite deve essere visibile; Per ottenere un'animazione bisogna invece impostare una sequenza di frame. La classe Sprite mette a disposizione una serie di metodi per questo scopo: void setFrameSequence(int[] sequence): imposta la sequenza di frame int getFrameSequenceLength(): restituisce la lunghezza della sequenza int getFrame(): restituisce l'indice del frame attuale void nextFrame(): passa al frame successivo void prevFrame(): torna al frame precedente void setFrame(int sequenceIndex): imposta il frame corrente
Note: Miniguida Realizzata Da Ðersew, per suggerimenti o correzioni: Mail (spero sia stata di vostro gradimento e abbiate imparato qualcosa di utile..bye) |
| Ecco cosa pensano le persone... |
| Loggati e scrivi il tuo commento, e' molto importante per noi conoscere il tuo parere sui nostri articoli, grazie. |