You are on page 1of 97

------

Gio trnh
Java v cng ngh
J2ME

CHNG I: GII THIU TNG QUAN


1. Gii thiu v Java v cng ngh J2ME
Gii thiu v Java
Java la mt cng nghc hng Sun Microsystems xy dng t cui nm 1990 vi tn
gi Oak v hin nay ang pht trin vt bc vi s ng gp ca hng vn lp trnh vin
trn th gii. Ban u, Oak c k s James Gosling v cc cng s xy dng vi mc
ch lp trnh cho cc mt hang in dn dng vi mc tiu nh gn v tng thch c
vi nhiu loi thit b phn cng khc nhau. Sau Oak c s dng trong nhiu d n
nh d n Xanh (Blue Project), d n Phim theo yu cu (Video on demand Project). Sau
mt chuyn du lch ti o Java ca Indonesia, nhm pht trin Oak i tn Oak thnh
Java.
Java m tin thn l Oak c xy dng ch yu da trn b cng c pht trin
(Java Development Kit - JDK) nh l b th vin chun trong cha trnh bin dch,
trnh thng dch, trnh ng gi, v ti liu.y chnh l nn tng cho vic pht trin cc
ng dng Java. Hin nay, cng ng Java trn th gii m i u l hang Sun
Microsystem xy dng nhiu nhnh mi cho Java nh: Javamail (th din t), Java
TAPI (vin thng), Java3D ( ha 3 chiu_, J2ME (ng dng cho thit b di ng). Hin
nay Java c cc phin bn sau:
J2SErM(Java 2 Platform, Standart Edition): Phin bn chun gm b cng c thng dng
dng chy trn cc my PC hoc cc mng my tnh nh.
J2EE (Java 2 Platform, Enterprise Edition): Phin bn dnh cho cc my ch vi b
nh ln. Bao gm cc kin trc nng cao nh Web, EJB, Transactiondng xy dng
cc ng dng c quy m ln.

J2ME (Java 2 Platform, Micro Edition): Bao gm mi trng v th vin Java dng
pht trin cc ng dng trn cc thit b c b nh nh nh in thoi di ng, PDA, cc
gia dng.
Gii thiu v J2ME v lp trnh cho thit b di ng
J2ME c pht trin t kin trc JavaCard, EmbededJava v PersonalJava ca
phin bn Java 1.1. Sau s ra i ca phin bn Java 2 th Sun quyt nh thay th
PersonalJava bng mt phin bn mi c tn Java 2 Micro Edition, vit tt l J2ME. J2ME
c s dng cho cc thit b nh gn vi dung lng b nh nh b v kh nng x l
thp.
Mc tiu ca Java l cho php ngi lp trnh vit cc ng dng c lp vi thit b
di ng., khng cn quan tm n phn cng thc s. lm c nh vy, J2ME c
xy dng bng cc tng khc nhau che giu i vic tng tc trc tip vi phn cng
ca thit b. Cc tng ca J2ME c xy dng trn CLDC (Connected Limited Device
Configuration):

Tng di cng l tng Phn cng thit b - y l tng vt l bao gm phn cng ca
thit b di ng. Cc tng bn trn tng Phn cng thit b l cc tng tru tng, chng
cung cp cho lp trnh vin nhiu giao din lp trnh thn thin v d dng hn m khng
cn quan tm n phn cng. Ni cc khc chng ng vai tr trung gian gip cho lp
trnh vin tng tc c vi phncng m khng cn quan tm n cc chi tit thc s
ca phn cng ca thit b.

Tng Phn cng thit b (Device Hardware Layer): y l thit b di ng tht s vi b


nh v tc x l c th. Cc thit b di ng khc nhau c th c b vi x l v cc tp
lnh rt khc nhau. Mc tiu ca J2ME l cung cp cho lp trnh vin kh nng giao tip
ging nhau vi tt c cc loi thit b di ng khc nhau..
Tng my o Java (Java Virtual Machine Layer): y l tng ng vai tr thng ngn gia
chng trnh v thit b. N s thng dch cc m bytecode (m c c sau khi bin dch m
ngun chng trnh) thnh m my ca cc thit b di ng. Tng ny bao gm KVM (K
Virtual Machine) l b bin dch m bytecode thnh m my. N cung cp mt s chun ha
cho cc thit b di ng ng dng J2ME sau khi bin dch c th chy c trn bt k
thit b di ng no h tr KVM.
Tng cu hnh (Configuration Layer): Tng ny cung cp cc hm API c bn l nhn ca
J2ME. Lp trnh vin c th s dng cc lp v cc phng thc ca cc API ny tuy nhin
n khng thc s phong ph bng tp API ca tng hin trng.
Tng hin trng (Profile Layer): Tng ny cung cp cc hm API hu dng hn cho vic lp
trnh. Mc ch ca tng ny xy dng nn lp cu hnh v cung cp nhiu th vin ng dng
hn.
6.1 L do chon J2ME:
Java ban u c thit k dnh cho cc my vi ti nguyn b nh hn ch. Th trng ca
J2ME c m rng ra cho nhiu chng loi thit b nh:
Cc lai th c nhn nh Java Card
My in thoi di ng My PDA (Personal Digital Assistant - thit b tr gip c
nhn)
Cc hp iu khin dnh cho tivi, thit b gii tr gia dng.

6.2 Kin trc ca J2ME


Phn ny s trnh by kin trc tng qut ca nn tng Java

a) Gii thiu cc thnh phn trong nn tng J2ME: nh ngha v Configuration (Cu
hnh): l c t nh ngha mt mi trng phn mm cho mt dng cc thit b c
phn loi bi tp hp cc c tnh, v d nh:
Kiu v s lng b nh
Kiu v tc b vi x l
Kiu mng kt ni
Do y l c t nn cc nh sn xut thit b nh Samsung, Nokia ...bt buc phi thc
thi y cc c t do Sun qui nh cc lp trnh vin c th da vo mi trng lp
trnh nht qun v thng qua s nht qun ny, cc ng dng c to ra c th mang
tnh c lp thit b cao nht c th. V d nh mt lp trnh vin vit chng trnh game
cho in thoi Samsung th c th sa i chng trnh ca mnh mt cch ti thiu nht
c th chy trn in thai Nokia.. Hin nay Sun a ra 2 dng Configuration:
CLDC (Connected Limited Device Configuration-Cu hnh thit b kt ni gii hn):
c thit k nhm vo th trng cc thit b cp thp (low-end), cc thit b ny
thng thng l my in thai di ng v PDA vi khong 512 KB b nh. V ti
nguyn b nh hn ch nn CLDC c gn vi Java khng dy (JavaWireless ), dng
nh cho php ngi s dng mua v ti v cc ng dng Java, v d nh l Midlet.
CDC- Connected Device Configuration (Cu hnh thit b kt ni): CDC c a ra
4

nhm n cc thit b c tnh nng mnh hn dng thit b thuc CLDC nhng vn yu
hn cc h thng my bn s dng J2SE. Nhng thit b ny c nhiu b nh hn
(thng thng l trn 2Mb) v c b x l mnh hn. Cc sn phm ny c th k n
nh cc my PDA cp cao, in thoi web, cc thit b gia dng trong gia nh ...
C 2 dng Cu hnh k trn u cha my o Java (Java Virtual Machine) v tp hp cc
lp (class) Java c bn cung cp mt mi trng cho cc ng dng J2ME. Tuy nhin,
bn ch rng i vi cc thit b cp thp, do hn ch v ti nguyn nh b nh v b
x l nn khng th yu cu my o h tr tt c cc tnh nng nh vi my o ca J2SE,
v d, cc thit b thuc CLDC khng c phn cng yu cu cc php tnh ton du phy
ng, nn my o thuc CLDC khng c yu cu h tr kiu float v double.

Ram
Rom

CLDC
>=32K, <=512K
>=128k, <=512k

CDC
>=256K
>=512k

Nguon Nang Luong

Co GioI Han (nguon pin)

Khong gioi han

Network

Cham

Nhanh

b) nh ngha v Profile:
Profile m rng Configuration bng cch thm vo cc class b tr cc tnh nng
cho tng thit b chuyn bit. C 2 Configuration u c nhng profile lin quan v t nhng
profile ny c th dng cc class ln nhau. n y ta c th nhn thy do mi profile nh
ngha mt tp hp cc class khc nhau, nn thng ta khng th chuyn mt ng dng Java
vit cho mt profile ny v chy trn mt my h tr mt profile khc. Cng vi l do ,
bn khng th ly mt ng dng vit trn J2SE hay J2EE v chy trn cc my htr J2ME.
Sau y l cc profile tiu biu:
Mobile Information Device Profile (MIDP): profile ny s b sung cc tnh nng
nh htr kt ni, cc thnh phn h tr giao din ngi dng ... vo CLDC. Profile ny
c thit k ch yu nhm vo in thai di ng vi c tnh l mn hnh hin th hn
ch, dung lng cha c hn. Do MIDP s cung cp mt giao din ngi dng n gin
v cc tnh nng mng n gin da trn HTTP. C th ni MIDP l profile ni ting nht
bi v n l kin thc c bn cho lp trnh Java trn cc my di ng (Wireless Java)
PDA Profile: tng t MIDP, nhng vi th trng l cc my PDA vi mn hnh v
b nh ln hn
Foundation Profile: cho php m rng cc tnh nng ca CDC vi phn ln cc th vin
ca b Core Java2 1.3 Ngoi ra cn c Personal Basis Profile, Personal Profile, RMI Profile,
Game Profile.

6.3 Pht trin ng dng


Bin dch

M ngun chng trnh c th c bin dch bng cc trnh bin dch chun ca Java,
chng to ra cc file .class. Ta c th bin dch t cc trnh son tho hoc bin dch
trc tip t dng lnh..
6.4 Kim tra li v chy th

Chng ta s dng cc cng c nh WTK kim tra li v chy th chng trnh v


vic ny nu tin hnh trn thit b tht rt mt thi gian. Vic s dng cc gi lp gip
nhanh chng pht hin cc li. Ngoi ra n cn gip lp trnh vin c nhng ci nhn
cm quan v chng trnh ca mnh.

6.5 ng gi

Sau khi kim li v chy th chng trnh, chng ta tin hnh ng gi ng dng
c th ci t trn cc thit b tht. Vic ng gi ng dng thc cht l nn cc file
.class vo trong mt file .jar, iu ny gip gim kch thc ng dng v n gin ha
khi ci t trn thit b tht. Chng ta c th ng gi ng dng bng trnh ng gi ca
JDK hoc trnh ng gi nm trong cc IDE. Hoc mt cch rt th cng, chng ta c
th ng gi ng dng mt cch trc tip. Vic ng gi trc tip thc cht cng tin
hnh li cc cng vic nh cc trnh ng gi nhng chng ta c th kim sot li tt
hn. Tuy vy vic ny kh phc tp v d gy ra li nu lp trnh vin cha thun thc.
6.6 ng gi v trin khai ng dng thnh tp tin JAR
Cc lp c bin dch ca ng dng J2ME c ng gi trong tp tin JAR
cng vi cc ti nguyn khc nh: hnh nh, m thanh,... Tp tin JAR ny chnh l tp tin
c ci vo thit b di ng. Ngi s dng c th ti tp tin JAR vo my di ng bng
cc cch sau:
Kt ni in thoi di ng vi my tnh bng cp truyn d liu: Vic ny yu cu
ngi dng phi c tp tin JAR tht s v phn mm truyn thng ti ng dng vo in
thoi thng qua cp d liu
Cng hng ngoi: Yu cu thit b di ng v ngun cha file JAR phi h tr hng ngoi
v ngi dng c file JAR tht s
S dng mng khng dy: ti ng dng thng qua mng GPRS, ngi dng ch cn bit a
ch URL ca tp tin JAR.
6.7 Tp tin manifest.mf v tp tin JAD
Tp tin manifest.mf v tp tin JAD m t cc c im ca ng dng. Tp tin
manifest.mf nm bn trong tp tin JAR cn tp tin JAD nm ngoi tp tin JAR. Tp tin
JAD gip cho ngi dng c th bit c c im ca ng dng trc

khi ti. Vic ny gip lm gim lng ph ti nguyn v tin bc v trn thc t, mt ng
dng J2ME no ch c th chy trn mt s my nht nh.
Tp tin manifest.mf c ni dung nh sau:
Manifest-Version: //Phin bn tp tin manifest.mf
MIDlet-Name://Tn b MIDlet
MIDlet-Version: //Phin bn ca b MIDlet
MIDlet-Vendor: //Nh sn xut
MIDlet-<n>://Tn ca MIDlet chnh
MicroEdition-Profile:

//Phin bn hin trng

MicroEdition-Configuration:

//Phin bn cu hnh

6.8 Ti u m chng trnh v gim kch thc ng dng


Sau khi ng gi chng trnh thnh tp tin JAR chng ta thy rng cc file d liu
c nn li mt cch ng k. Tuy nhin ta c th gim kch thc file JAR ny thm mt
ln na bng cch dng mt cng c. Cng c ny thng bao gm cc c tnh sau:
- Loi b cc class khng dng n
-

Loi b cc hm v bin khng dng n

i tn class, package, hm v bin thnh cc tn n gin v ngn gn hn

- Thm vo file class mt s m chng trnh kh b dch ngc hn


Ba c tnh u dng gim kch thc cc file .class trong khi c tnh th 3 v
th 4 dng bo v chng trnh kh b dch ngc li thnh m ngun. Ngay c khi
b dch ngc li thnh m ngun th chng trnh cng kh b c hn v cc tn lp,
bin, hm, package b thay i. Cc cng c thng c dng ti u m chng
trnh l Jbuilder 9X, Retroguard, Jshrink.

6.9 Nhng kh khn khi lp trnh trn thit b di ng


S dng cng ngh J2ME cho vic lp trnh trn thit b di ng l mt vic khng kh i
vi cc lp trnh vin. Tuy vy khi lp trnh bng J2ME, lp trnh vin s gp phi mt s
kh khn c trng khng th trnh khi:
-

Khng h tr php tnh du phy ng (floating point):

Khng h tr b np class (Class loader).

Khng h tr t kha finalize()

Phn ln cc th vin API cho Swing v AWT khng th s dng c trong MIDP.

Khng h tr cc tnh nng qun l file v th mc: y c th lm bn ngc nhin

nhng thc t l cc thit b J2ME khng c h tr cc thit b lu tr thng thng nh


cng v.v. Tuy nhin, iu khng c ngha l bn phi mt i mi d liu quan trng mi
khi tt my, Sun cung cp mt chc nng khc tng ng gi l Record Management
system (RMS) cung cp kh nng lu tr cho cc thit b ny.
-

Cc thit b di ng b gii hn v kch thc ng dng.

V d nh: vi Series 40 ca Nokia, Samsung X100, V200,... c dung lng lu tr rt hn


ch. Sau y l kch thc ti a ca file JAR ci t trn mt s dng in thoi:
Loi in thoi

Kch thc ti a ca file JAR

Nokia series 40
Motorola T720
Panasonic X60

64 KB
64KB
80KB
128KB

Sony Ericssion T610, T630


Samsung X600

100KB

l mt s kh khn m cc lp trnh vin thng gp phi khi lp trnh cho in thoi


di ng.

10

CHNG II: LP TRNH VI J2ME


1. MIDlet vi tng Display
1.1 MIDlet - Vng i ca mt MIDlet
Nu ai vit Applet th chc hn thy hai ci tn ny na n nhau. MIDlet l vit tt
ca Mobile Information Device applet.Hu ht cc ng dng m ta thy trn in thoi di
ng u l MIDlet. Mt MIDlet k tha t lp javax.microedition.midlet.MIDlet v thc
thi t nht cc phng thc c bn sau: startApp(), pauseApp(), v destroyApp(). Trong
mt ng dng ca bn gm c nhiu lp th c th ch cn mt lp k tha MIDlet. Ta s i
vo phn tch tng on nh mt trong on code hon chnh ca mt MIDlet.
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class test extends MIDlet implements CommandListener{ private
Form mainForm; public test(){
mainForm = new Form("Lap trinh tren nen J2ME");
mainForm.append(new StringItem(null,"Hello J2ME"));
mainForm.addCommand(new Command("Exit",Command.EXIT,0));
mainForm.setCommandListener(this);
}
public void startApp(){
Display.getDisplay(this).setCurrent(mainForm);
}

public void pauseApp(){} public void destroyApp(boolean un){} public


void commandAction(Command c, Displayable s){ notifyDestroyed();

11

1) Pht biu import: dng np cc lp cn thit t th vin ca CLDC v MIDP


2) Dng khai bo lp: mt lp(class) test c th c gi t bt k lp khc (public), k
tha (extends) t lp MIDlet (hay d hiu hn l: lp test l mt MIDlet) v gi thc thi
(implements) cc phng thc ca mt interface c tn l CommandListener.
3) Hm to (Constructor):
To ra mt form c title l Lap trinh tren nen J2ME Gn vo form va to mt chui l
Hello J2ME To ra mt nt Exit trn form, tng tc ti nt 0, bn th thay 0 bng 1,2
xem sao setCommandListener: Gn s kin cho form. Hm to ch c gi mt ln khi
MIDlet khi to ln u tin, v ch cgi li khi thot ra khi MIDlet, ri khi ng
li
4) startApp():
Phng thc startApp() c gi khi MIDlet c khi to, v mi khi MIDlet tr v t
trng thi tm dng (pause). Cc bin ton cc s c khi to li tr hm to bi v cc
bin c gii phng trong hm pauseApp(). Nu khng th chng s khng c khi
to li bi ng dng.
5) pauseApp():
Phng thc pauseApp() c gi mi khi ng dng cn c tm dng (v d, trong
trng hp c cuc gi hoc tin nhn n). Cch thch hp s dng pauseApp() l gii
phng ti nguyn v cc bin dnh cho cc chc nng khc trong in thoi trong khi
MIDlet c tm dng. Cn ch rng khi nhn cuc gi n, h iu hnh trn in thoi
di ng c th dng KVM thay v dng MIDlet. Vic ny do nh sn xut thit b quyt
nh schn cch no.
6) destroyApp(boolean un):
Phng thc destroyApp() c gi khi thot MIDlet. (v d khi nhn nt exit trong ng
dng). N ch n thun l thot MIDlet.. Phng thc destroyApp() ch nhn mt tham s
Boolean. Nu tham s ny l true, MIDlet c tt v iu kin. Nu tham s l false,

12

MIDlet c thm ty chn t

chi

thot bng cch n nhn mt ngoi l

MIDletStateChangeException.
Di y l vng i ca mt MIDlet:

Ngoi tr cc phng thc ta quen l startApp(), pauseApp(), destroyApp() chng ta


thy c thm 3 phng thc na, l: resumeRequest(), notifyPaused(),
notifyDestroyed(). T s khi trn, ta thy:

13

MIDlet ang t trng thi PAUSED chuyn n thc thi phng thc startApp()
thng qua phng thc resumeRequest(): phng thc ny yu cu MIDlet chuyn
vo ch hot ng.
MIDlet ang trng thi hot ng chuyn n thc thi phng thc pauseApp() thng qua
phng thc notifyPaused(): phng thc ny cho bit MIDlet t nguyn chuyn sang
trng thi dng.
MIDlet ang trng thi no chuyn n thc thi phng thc destroyApp() thng qua
phng thc notifyDestroyed(): phng thc ny cho bit MIDlet sn sng hy. T
chng ta c th thy 3 phng thc mi ny t MIDlet vo trng thi trung gian gia
cc trng thi khc.
1.2 itng Display
Mi MIDlet c mt tham chiu n mt i tng Display. i tng ny cung cp
cc thng tin v mn hnh cng nh mt s phng thc cn cho vic hin th cc i
tng khc trn mn hnh. C th xem Display l i tng c nhim v qun l vic hin
th ca mn hnh. Chc nng ca n l quyt nh danh sch cc thnh phn cn xut hin
trn mn hnh cng nh thi im ph hp hin th chng.
1.3 i tng Displayable
Mc d mi MIDlet ch c duy nht mt i tng Display nhng n li c th c
rt nhiu i tng Displayable. iu c ngha l mt i tng Display c th hin th
bao nhiu i tng Displayable ty . i tng Displayable l i tng c th nhn thy
c mt cch trc quan trn mn hnh. Bn thn MIDP c cha 2 lp con ca Displayable
l Screen v Canvas:
public abstract class Displayable
public abstract class Canvas extends Displayable
public abstract class Screen extends Displayable

14

2. Giao din ngi dng cp cao


2.1 i tng Display, Displayable va Screens
Mt ng dng MIDlet ch c 1 i tng th hin Display. i tng ny dng ly
thng tin vi tng trnh by, v d mu c h tr, v bao gm cc phng thc yu cu
cc i tng c trnh by. i tng Display cn thit cho b qun l vic trnh by trn
thit biu khin thnh phn no sc hin th ln trn thit bMc d ch c mt i tng
Display ng vi mi MIDlet, nhng nhiu i tng trong mt MIDlet c thc hin th ra
trn thit b nhForms, TextBoxes, ChoiceGroups, .. Mt i tng Displayable l mt thnh
phn c hin th trn mt thit b. MIDP cha 2 lp con ca lp Displayable l Screen v
Canvas. Hnh di y m t mi quan h trn:

Mt i tng Screen khng phi l mt ci g hin ra trn thit b, m lp Screen ny


sc tha k bi cc thnh phn hin th mc cao, chnh cc thnh phn ny sc hin
th ra trn mn hnh. Hnh di y s m t mi quan h ca lp Screen v cc thnh phn
th hin mc cao.

15

Tm li, phn ny ch gii thiu h thng phn cp i tng dng th hin giao din ngi
dng trong MIDP.
2.2 Thnh phn Form v Items
Trong phn ny s gii thiu cc thnh phn c hin th ra trn mt Form. Mt Form ch
n gin l mt khung cha cc thnh phn, m mi thnh phn c tha k t lp Item.
Chng ta s xem qua cc thnh phn hin th trn thit b:
DateField
Gauge
StringItem
TextField
ChoiceGroup
Spacer
CustomItem
Image and ImageItem

a) DateField

16

Thnh phn DateField cung cp mt phng tin trc quan thao tc i tng Date c
nh ngha trong java.util.Date. Khi to mt i tng DateField, bn cn ch r l ngi dng
ch c th chnh sa ngy, chnh sa gi hay ng thi c hai. Cc phng thc dng ca lp
DateField gm:
DateField(String label, int mode)
DateField(String label, int mode, TimeZone timeZone)

Cc mode tng ng ca lp DateField gm:


DateField.DATETIME: cho php thay i ngy gi DateField.TIME: chi cho php thay i gi
DateField.DATE: chi cho php thay i ngy

VI du:
private DateField dfAlarm; // Tao doi tuong DateField cho thay doi ca ngay va gid dfAlarm =
new DateField("Set Alarm Time", DateField.DATE TIME); dfAlarm.setDate(new Date());
Di y l on chng trnh mu th nghim i tng DateField
import java.util.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.Timer;
import java.util.TimerTask;
public class DateFieldTest extends MIDlet implements ItemStateListener,
CommandListener {
private Display display; // Reference to display object
private Form fmMain; // Main form
private Command cmExit; // Exit MIDlet
private DateField dfAlarm; // DateField component
public DateFieldTest() {
display = Display.getDisplay(this); // The main form
fmMain = new Form("DateField Test"); // DateField with
todays date as a default
dfAlarm = new DateField("Set Alarm Time", DateField.DATE TIME);

17

dfAlarm.setDate(new Date());
fmMain.addCommand(cmExit);
fmMain.setCommandListener(this);
fmMain.setItemStateListener(this);
}
public void startApp () {
display.setCurrent(fmMain);
}

public voidpauseApp() {}
public void destroyApp(boolean unconditional) {} public
void itemStateChanged(Item item) {
System.out.println("Date field changed.");
}

public void commandAction(Command c, Displayable s) { if (c ==


cmExit) {
destroyApp(false); notifyDestroyed();
}
}

}
b) Gauge
Mt thnh phn Gauge l mt kiu giao din thng c dng m t mc hon
thnh mt cng vic. C 2 loi Gauge l loi tng tc v loi khng tng tc. Loi u cho
php ngi dng c th thay i Gauge, loi 2 th i hi ngi pht trin phi cp nht Gauge.
Di y l hm dng ca lp Gauge:
Gauge(String label, boolean interactive, int maxValue, int initialValue)
VI du:
private Gauge gaVolume; // iu chnh m lng
gaVolume = new Gauge("Sound Level", true, 100, 4);
Di y l on chng trnh mu minh ha cch s dng lp Gauge
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class InteractiveGauge extends MIDlet implements CommandListener {
private Display display; // Reference to display object
private Form fmMain; // The main form

18

private Command cmExit; // Exit the form private Gauge


gaVolume; // Volume adjustment public InteractiveGauge()
{
display = Display.getDisplay(this);
// Create the gauge and exit command
gaVolume = new Gauge("SoundLevel", true, 50, 4);
cmExit = new Command("Exit", Command.EXIT, 1);
// Create form, add commands, listen for events
fmMain = new Form("");
fmMain.addCommand(cmExit);
fmMain.append(gaVolume);
fmMain.setCommandListener(this);
}

// Called by application manager to start the MIDlet. public void


startApp() {
display.setCurrent(fmMain);
}

public voidpauseApp() {}
public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable s) { if (c ==
cmExit) {
destroyAppfalse); notifyDestroyed();
}
}
}

c) Stringltem
Mt thnh phn StringItem c dng hin th mt nhn hay chui vn bn. Ngi
dng khng th thay i nhn hay chui vn bn khi chng trnh ang chy. StringItem khng
nhn ra s kin Phng thc dng ca lp StringItem:
StringItem(String label, String text)
Duoi day la doan ma minh hoa viec su dung doi tuong Stringltem
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

19

public class StringItemTest extends MIDlet implements CommandListener{ private


Display display; // Reference to Display object private Form fmMain; // Main form
private StringItem siMsg; // StringItem
private Command cmChange; // Change the label and message private
Command cmExit; // Exit the MIDlet public StringItemTest() {
display = Display.getDisplay(this);
// Create text message and commands
siMsg = new StringItem("Website: ", "www.IBM.com");
cmChange = new Command("Change", Command.SCREEN, 1);
cmExit = new Command("Exit", Command.EXIT, 1);
// Create Form, add Command and StringItem, listen for events
fmMain = new Form("StringItem Test");
fmMain.addCommand(cmExit);
fmMain.addCommand(cmChange);
fmMain.append(siMsg);
fmMain.setCommandListener(this);
}

// Called by application manager to start the MIDlet. public void


startApp() {
display.setCurrent(fmMain);
}

public voidpauseApp() {}
public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable s) { if (c ==
cmChange) { // Change label siMsg.setLabel("Section: ");
// Change text
siMsg.setText("developerWorks");
// Remove the command fmMain.removeCommand(cmChange);
}

else if (c == cmExit) {
destroyApp(false); notifyDestroyed();

20

d) TextField
Mt thnh phn TextField th tng t nh bt k cc i tng nhp vn bn tiu biu
no. Bn c th ch nh mt nhn, s k t ti a c php nhp, v loi dliu c php
nhp. Ngoi ra TextField cn cho php bn nhp vo mt khu vi cc k t nhp vo s c
che bi cc k t mt n
Phng thc dng ca lp
TextField TextField(String label, String text, int maxSize, int constraints)
Thnh phn th 3 constraints l thnh phn m chng ta quan tm, v n l phng tin xc
nh loi d liu no c php nhp vo TextField. MIDP nh ngha cc tham s rng buc
sau cho thnh phn TextField:
- ANY: cho php nhp bt k k t no
- EMAILADDR: ch cho php nhp vo cc a ch email hp l
- NUMERIC: ch cho php nhp s
- PHONENUMBER: Ch cho php nhp sin thoi
- URL: Ch cho php nhp cc k t hp l bn trong URL
- PASSWORD: che tt c cc k t nhp vo
Di y l on m minh ha vic s dng thnh phn TextField
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class TextFieldTest extends MIDlet implements CommandListener{
private Display display; // Reference to Display object private Form fmMain; //
Main form private Command cmTest; // Get contents of textfield private
Command cmExit; // Command to exit the MIDlet private TextField tfText; //
Textfield public TextFieldTest() {
display = Display.getDisplay(this); // Create
commands
cmTest = new Command("Get Contents", Command.SCREEN, 1);

21

cmExit = new Command("Exit", Command.EXIT, 1); // Textfield for phone


number
tfText = new TextField("Phone:", "", 10, TextField.PHONENUMBER);
// Create Form, add Commands and textfield, listen for events fmMain = new
Form("Phone Number"); fmMain.addCommand(cmExit);
fmMain.addCommand(cmTest);
fmMain.append(tfText);
fmMain.setCommandListener(this);
}
// Called by application manager to start the MIDlet. public void
startApp() {
display.setCurrent(fmMain);
}

public voidpauseApp() {}
public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable s) { if (c ==
cmTest) {
System.out.println("TextField contains: " + tfText.getString());
}

else if (c == cmExit) {
destroyApp(false); notifyDestroyed();
}
}
}

on m trn ch mi p dng mt rng buc trn i tng TextField. Chng ta c th thm


mt rng buc th 2 bng cch thay on m sau:
tfText

new

TextField("Phone:",

"",

10,

TextField.PHONENUMBER

TextField.PASSWORD);

e) ChoiceGroup
Thnh phn ChoiceGroup cho php ngi dng chn t mt danh sch u vo c nh
ngha trc. ChoiceGroup c 2 loi:
multi-selection(cho php chn nhiu mc): nhm ny c lin quan n cc checkbox

22

exclusive-selection(chc chn mt mc): nhm ny lin quan n nhm cc radio button


Di y l on m minh ha cho vic s dng ChoiceGroup:
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class ChoiceGroupTest extends MIDlet implements ItemStateListener,
CommandListener {
private Display display; // Reference to display object
private Form fmMain; // Main form
private Command cmExit; // A Command to exit the MIDlet private
CommandcmView; // View the choice selected private int selectAllIndex; //
Index of the "Select All" option private ChoiceGroup cgPrefs; // Choice
Group of preferences private int choiceGroupIndex; // Index of choice
group on form public ChoiceGroupTest() {
display = Display.getDisplay(this); // Create a multiple
choice group
cgPrefs = new ChoiceGroup("Preferences", Choice.MULTIPLE);
// Append options, with no associated images
cgPrefs.append("Replace tabs with spaces", null);
cgPrefs.append("Save bookmarks", null);
cgPrefs.append("Detectfile type", null);
selectAllIndex = cgPrefs.append("Select All", null);
cmExit = new Command("Exit", Command.EXIT, 1);
cmView = new Command("View", Command.SCREEN,2);
// Create Form, add components, listen for events fmMain = new
Form("");
choiceGroupIndex = fmMain.append(cgPrefs);
fmMain.addCommand(cmExit);
fmMain.addCommand(cmView);
fmMain.setCommandListener(this);
fmMain.setItemStateListener(this);
}

public void startApp() {


display.setCurrent(fmMain);
}

public voidpauseApp() {}
public void destroyApp(boolean unconditional) {}

23

public void commandAction(Command c, Displayable s){ if (c ==


cmView) {
boolean selected[] = new boolean[cgPrefs.size()];
// Fill array indicating whether each element is checked
cgPrefs.getSelectedFlags(selected);
for (int i = 0; i < cgPrefs.size(); i++)
System.out.println(cgPrefs.getString(i) + (selected[i] ? ":
selected" : ": not selected"));
}
else if (c == cmExit) {
destroyAppfalse); notifyDestroyed();
}
}

public void itemStateChanged(Item item) { if (item ==


cgPrefs) {
//Is "Select all" option checked ? if
(cgPrefs.isSelected(selectAllIndex)) { // Set all checkboxes to true for
(int i = 0; i < cgPrefs.size(); i++)
cgPrefs.setSelectedIndex(i, true); //Remove the check by "Select All"
cgPrefs.setSelectedIndex(selectAllIndex, false);
}
}
}
}

f ) Spacer

Spacer l thnh phn khng nhn thy, c dng nh v tr cho cc i tng khc
trn mn hnh hin th. Chng ta c th dng Spacer ch r khong trng theo chiu dc v
chiu ngang gia cc thnh phn, n gin bng cch ch ra chiu di v chiu rng cho tng
ci. V Spacer l thnh phn khng nhn thy nn n khng c s kin.
g) Customltem

24

Thnh phn CustomItem cho php bn to ra nhng thnh phn Item ca chnh bn.
Nhng thnh phn ny cng ging nh nhng Item khc l cng c thc t vo trong
Form v c th nhn bit v x l s kin CustomItem c v ln mn hnh hin th bng
phng thc paint(). V th n s ty thuc vo on m c bn hin thc bn trong phng
thc paint(). Qu trnh to ra mt i tng CustomItem cng khng khc cc i tng c sn
trn nn Java.
on m di y minh ha sn ca vic to ra mt i tng CustomItem
public class NewItem extends CustomItem { public
NewItem(String label) { super(label);
}

protected voidpaint(Graphics g, int width, int height) {


}

protected int getMinContentHeight() {


}

protected int getMinContentWidth() { ... } protected int


getPrefContentHeight(int width) { ... } protected int
getPrefContentWidth(int height) {
}
..
}

h) Image and Imageltem


Hai lp c dng hin th hnh nh l: Image v ImageItem. Image c dng to ra
mt i tng hnh nh v gi thng tin nh l chiu cao v chiu rng, v d nh c bin i
hay khng. Lp ImageItem m t mt tm nh sc hin th nh th no, v d tm nh s
c t trung tm, hay t v pha bn tri, hay bn trn ca mn hnh.
MIDP a ra 2 loi hnh nh l loi nh khng bin i v nh bin i. Mt tm nh khng
bin i th khng th b thay i k t lc n c to ra. c trng ca loi nh ny l c
c t mt tp tin. Mt tm nh bin i v c bn l mt vng nh. iu ny ty thuc vo

25

vic bn to ni dung ca tm nh bng cch ghi n ln vng nh. Chng ta s lm vic vi


nhng tm nh khng bin i trong bng sau.
Cc phng thc dng cho lp Image va ImageItem
Image createImage(String name)
Image createImage(Image source)
Image createImage(byte[] imageDate, int imageOffset, int imageLength) Image
createImage(int width, int height)
Image createImage(Image image, int x, int y, int width, int height, int transform) Image

createImage(InputStream stream)
Image createRGBImage(int[] rgb, int width, int height, boolean processAlpha)
ImageItem(String label, Image img, int layout, String altText)
on m di y m t lm th no to mt tm nh t mt tp tin, v gn n vi mt i
tng ImageItem v thm mt bc nh vo mt Form:
Form fmMain = new Form("Images"); ... //
Create an image
Image img = Image.createImage("/house.png");
// Append to a form
fmMain.append(new ImageItem(null, img, ImageItem.LAYOUTCENTER, null));
Ch : PNG l loi nh duy nht c h tr bi bt k thit b MIDP no on m di y
m t vic s dng i tng Image v i tng ImageItem
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class ImageTest extends MIDlet implements CommandListener { private
Display display; // Reference to Display object private Form fmMain; // The
main form private Command cmExit; // Command to exit the MIDlet public
ImageTest() {

26

display = Display.getDisplay(this);
cmExit = new Command("Exit", Command.EXIT, 1);
fmMain = new Form("");
fmMain.addCommand(cmExit);
fmMain.setCommandListener(this);
try{

// Read the appropriate image based on color support Image im =


Image.createImage((display.isColor()) ?
"/imagecolor.png":"/image_bw.png");
fmMain.append(new ImageItem(null, im,
ImageItem.LAYOUT CENTER, null));
display.setCurrent(fmMain);
}
catch (java.io.IOException e) {
System.err.println("Unable to locate or read.png file");
}
}

public void startApp() {


display.setCurrent(fmMain);
}

public voidpauseApp() {}
public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable s) { if (c
== cmExit) {
destroyApp(false); notifyDestroyed();
}
}
}

27

2.3 Thnh phn List, Textbox, Alert, va Ticker


Trong phn ny chng ta s xem xt cc i tng ListBox, TextBox, Alert, v Ticker
trong cc thnh phn giao din cp cao ca ng dng MIDP. Chng ta hy cng xem li cy
phn cp cc thnh phn trnh by trn thit b mt cch hon chnh hn

a) List
Mt List cha mt dy cc la chn c th hin mt trong ba dng. Chng ta thy
loi cho php nhiu la chn v loi ch c php chn mt khi lm vic vi ChoiceGroup.
Dng th 3 l l dng khng tng minh. Cc List khng tng minh uc dng th hin
mt thc n cc chn la.
on m di y minh ha vic s dng mt danh sch khng tng minh
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class ImplicitList extends MIDlet implements CommandListener { private
Display display; // Reference to Display object private List lsDocument; // Main
list private Command cmExit; // Command to exit public ImplicitList() {
display = Display.getDisplay(this); // Create the
Commands

28

cmExit = new Command("Exit", Command.EXIT, 1);


try {
// Create array of image objects
Image images[] = {Image.createImage("/next.png");
Image.createImage("/previous.png");
Image.createImage("/new.png")};
// Create array of corresponding string objects
String options[] = {"Next", "Previous", "New"};
// Create list using arrays, add commands, listen for events
lsDocument = new List("Document Option:", List.IMPLICIT,
options, images);
//If you have no images, use this line to create the list // lsDocument = new
List("Document Option:", List.IMPLICIT, options, null);
lsDocument.addCommand(cmExit);
lsDocument.setCommandListener(this);
}

catch (java.io.IOException e) {
System.err.println("Unable to locate or read.png file");
}
}

public void startApp() {


display.setCurrent(lsDocument);
}

public voidpauseApp() {}
public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable s) { // If
an implicit list generated the event if (c == List.SELECT
COMMAND) {
switch (lsDocument.getSelectedIndex()) { case 0:
System.out.println("Next selected");
break;
case 1:
System.out.println("Previous selected");
break;
case 2:
System.out.println("New selected");
break;
}

29

else if (c == cmExit) {
destroyApp(false); notifyDestroyed();
}
}
}

b) TextBox
TextBox c dng cho php nhp nhiu dng. Thnh phn TextBox v

TextField c nhng rng buc ging nhau trong vic chnh loi ni dung c php nhp
vo. V d ANY, EMAIL, URI.
Di y l phng thc dng ca mt TextBox:
TextBox(String title, String text, int maxSize, int constraints)
c) Alert va AlertType
Mt Alert n gin l mt hp thoi rt nh. C 2 loi Alert:
Modal: l loi hp thoi thng bo c trnh by cho n khi ngi dng n nt ng
Non-modal: l loi hp thoi thng bo chc trnh by trong mt s giy nht nhCc
phng thc dng caAlert:
Alert(String title)
Alert(String title, String alertText, Image alertImage, AlertType alertType)
Thnh phn AlertType s dng m thanh thng bo cho ngi dng bit c mt s
kin xy ra. V d bn c th s dng AlertType m mt on m thanh no bo hiu cho
ngi dng bit khi c li xy ra Thnh phn AlertType bao gm 5 loi m thanh nh sn l:
thng bo, xc nhn, bo li, thng bo v cnh bo Ta thy cc phng thc dng ca Alert
cho bit l Alert c th bao gm 1 tham chiu n mt i tng AlertType..

30

Di y l on m minh ha vic s dng Alert v AlertType


import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class AlertTest extends MIDlet implements ItemStateListener,
CommandListener {
private Display display; // Reference to display object private Form
fmMain; // Main form private Command cmExit; // Command to exit the
MIDlet private ChoiceGroup cgSound; // Choice group public AlertTest() {
display = Display.getDisplay(this);
// Create an exclusive (radio) choice group
gSound = new ChoiceGroup("Choose a sound", Choice.EXCLUSIVE);
// Append options, with no associated images
cgSound.append("Info", null);
gSound.append("Confirmation", null);
gSound.append("Warning", null);
gSound.append("Alarm", null);
gSound.append("Error", null);
mExit = new Command("Exit", Command.EXIT, 1);
// Create Form, add components, listen for events
fmMain = new Form("");
fmMain.append(cgSound);
fmMain.addCommand(cmExit);
mMain.setCommandListener(this);
fmMain.setItemStateListener(this);
}
public void startApp() {
display.setCurrent(fmMain);
}

public voidpauseApp() {}
public void destroyApp(boolean unconditional) {} public void
commandAction(Command c, Displayable s) { if (c == cmExit) {
destroyApp(false);
notifyDestroyed();
}
}

public void itemStateChanged(Item item) { Alert al =


null;
switch (cgSound.getSelectedIndex()){ case 0:

31

al = new Alert("Alert sound", "Info sound", null, AlertType.INFO); break;


case 1:
al = new Alert("Alert sound", "Confirm", null, AlertType.INFO); break; case
2:
al = new Alert("Alert sound", "Warning", null, AlertType.INFO); break;
case 3:
al = new Alert("Alert sound", "Alarm", null, AlertType.INFO);
break; case 4:
al = new Alert("Alert sound", "Error", null, AlertType.INFO); break;
}

if (al != null) {
// Wait for user to acknowledge the alert al.setTimeout(A
lert.FOREVER); // Display alert, show main form when done
display.setCurrent(al, fmMain);
}
}
}

d) Ticker
Thnh phn Ticker uc dng th hin mt on chui chy theo chiungang.
Tham s duy nht ca thnh phn Ticker l on vn bn c trnh by. Tc v chiu
cun c xc nh bi vic ci t trn thit b no. Phng thc dng ca Ticker:
Ticker(String str);
T cy phn cp cc thnh phn th hin trn thit b, ta thy l thnh phn Ticker khng
l lp con ca lp Screen m Ticker l mt bin ca lp Screen. iu ny cngha l mt
Ticker c th c gn vo bt c lp con ca lp Screen bao gm c Alert
Duoi day la doan ma minh hoa viec su dung mot Ticker
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class TickerTest extends MIDlet implements CommandListener {
private Display display; // Reference to Display object private List
lsProducts; // Products private Ticker tkSale; // Ticker

32

private Command cmExit; // Command to exit the MIDlet public


TickerTest() {
display = Display.getDisplay(this);
cmExit = new Command("Exit", Command.SCREEN, 1);
tkSale = new Ticker("Sale: Real Imitation Cuban Cigars...10 for $10");
lsProducts = new List("Products", Choice.IMPLICIT);
lsProducts.append("Wicker Chair", null);
lsProducts.append("Coffee Table", null);
lsProducts.addCommand(cmExit);
lsProducts.setCommandListener(this);
lsProducts.setTicker(tkSale);
}
public void startApp() {
display.setCurrent(lsProducts);
}

public void pauseApp() {}


public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable s) { if (c ==
List.SELECTCOMMAND) { switch
(lsProducts.getSelectedIndex()) { case 0:
System.out.println("Chair selected"); break;
case 1:
System.out.println("Table selected"); break;
}

else if (c == cmExit) {
destroyApp(true); notifyDestroyed();
}
}
}

3. Giao din ngi dng cp thp


3.1Cc hm API mc thp
Mc d cc hm API cp cao cung cp mt tp y cc thnh phn xy dng
giao din ng dng ngi dng. Tuy nhin cc thnh phn cp cao khng cung cp phng
tin v trc tip ln thit b th hin. V thiu kh nng ny nn cc ng dng c to ra

33

s gp nhiu gii hn. V d hu ht cc nh pht trin game di ng da trn kh nng v


cc ng thng v cc hnh dng nh l mt phn tch hp qu trnh pht trin. Nu cc
hm API cp cao cho php chng ta to ra giao din cho cc ng dng theo chun, th cc
hm API cp thp cho php chng ta c th th hin cc tng ca mnh.
Canvas v Graphics l 2 lp tri tim ca cc hm API cp thp. Chng ta s lm tt c cc
cng vic bng tay. Canvas l mt khung v cho php ngi pht trin c kh nng v ln
thit b trnh by cng nh l vic x l s kin. Cn lp Graphics cung cp cc cng c
tht s v nh drawRoundRect() v drawString()
3.2 Lp Canvas v k thut x l ha:
Lp Canvas cung cp mt khung v cho php to ra giao din ty bin ngi dng.
Mt s lng ln cc phng thc trong lp ny c dng x l s kin, v nh v
chui ln thit b hin th. Trong phn ny s bao gm cc mc:
-

H thng ta

To i tng Canvas

V ln trn i tng Canvas

X l cc s kin hnh ng

X l cc s kin phm nhn

X l s kin hnh ng ca Game

X l s kin con tro


Chng ta s to ra 2 ng dng MIDlet minh ha kh nng ca lp Canvas. ng

dng u tin l KeyMapping s minh ha lm th no chp, nhn ra v x l m phm


nhn v cc s kin c lin quan n Game. ng dng cn li l ScratchPad sminh ha
lm th no thao tc cc s kin con tr to ra mt chng trnh v ng thng n
gin
a) H thng trc ta

34

Mc tiu u tin ca chng ta l lm quen vi h thng trc ta lm vic


vi thit b th hin. H thng ta cho lp Canvas c tm ta l im tri trn ca
thit b trnh by. Gi tr x tng dn v pha phi, gi tr y tng dn khi i xung pha di.
Khi v dy bt v l mt im nh

Cc phng thc sau y s gip xc nh chiu rng v chiu cao ca canvas:


int getWidth():xc nh chiu rng ca canvas
int getHeight ():xc nh chiu cao ca canvas
Chiu rng v chiu cao ca Canvas cng i din cho ton b din tch khung v c
th trn thit b trnh by. Ni cch khc, chng khng th ch nh kch thc cho canvas,
m phn mm trn mt thit b MIDP s tr v din tch ln nht c th c i vi mt thit
b cho trc.
b) To mt i tng Canvas
Bc u tin lm vic vi mt lp Canvas l to ra mt lp tha k t lp
Canvas:
class TestCanvas extends Canvas implements CommandListener { private
CommandcmdExit; ... display = Display.getDisplay(this); cmdExit = new
Command("Exit", Command.EXIT, 1); addCommand(cmdExit);
35

setCommandListener(this); ... protected voidpaint(Graphics g) { // Draw


onto the canvas
}
}
TestCanvas canvas = new TestCanvas(this);
c) V trn i tng Canvas
Phng thc paint ca lp Canvas cho php bn v cc hnh dng, v nh, xut
chui. on m sau minh ha vic xa mn hnh th hin bng mt mu trng:
protected voidpaint(Graphics g) {
// Set background color to white
g.setColor(255, 255, 255);
// Fill the entire canvas
g.fillRect(0, 0, getWidth(), getHeight());
Chng ta c th s dng mt tham chiu n mt i tung Graphics bn trong thn
phng thc paint() thc hin cng vic v thc s
d) S kin hnh ng
Cng nh cc thnh phn Form, List, v TextBox, mt Canvas c th x l cc
s kin Command. Chng ta c th x l cc s kin Command trn thnh phn Canvas
cung cch nh cc thnh phn khc on m sau minh ha vic x l s kin Command
trn thnh phn Canvas:
class TestCanvas extends Canvas implements CommandListener {
private Command cmdExit;

display = Display.getDisplay(this); cmdExit = new


Command("Exit", Command.EXIT, 1); addCommand(cmdExit);
setCommandListener(this); ... protected voidpaint(Graphics g) { //
Draw onto the canvas

36

public void commandAction(Command c, Displayable d) { if (c ==


cmdExit)

}
}
e) M phm
Trong trng hp x l cc hnh ng ca cc phm mm, mt Canvas c th truy
cp n 12 m phm. Nhng m ny c m bo lun lun c trn bt k cc thit b
MIDP no
KEYNUM0
KEYNUM1
KEYNUM2
KEYNUM3
KEYNUM4
KEYNUM5
KEYNUM6
KEY_NUM7
KEYNUM8
KEYNUM9
KEYSTAR
KEYPOUND

Nm phng thc x l cc m phm l:


void keyPressed(int keyCode)
void keyReleased(int keyCode)

37

void keyRepeated(int keyCode)


boolean hasRepeatEvents()
String getKeyName(int keyCode)

f) Cc hnh ng trong x l cc tr chi

38

MIDP thng c s dng to cc tr chi trn nn Java. Cc hng s sau c


nh ngha x l cc s kin c lin quan n tr chi trong MIDP UP, DOWN,
LEFT, RIGHT, FIRE, GAME_A, GAME_B, GAME_C, GAME_D Ni mt cch n
gin th cc gi tr ny c nh x thnh cc phm mi tn chhng ca thit b, nhng
khng phi tt c cc thit b di ng u c nhng gi trny. Nu mt thit b di ng
thiu cc phm mi tn th cc hnh ng ca tr chi sc nh x vo cc nt bm, v
d phm tri c nh x vo phm s 2, phm phi c nh x vo phm s 5, v c tip
tc nh th. Hnh di y cho thy cc hnh ng ca tr chi s c nh x ln mt
thit b di ng da trn kh nng ca cc phm ch hng

g) Xc nh cc hnh ng ca tr chi
on m sau y m t mt cch xc nh cc hnh ng ca tr chi t gi
cc phng thc thch hp da trn cc hnh ng xy ra

39

protected void keyPressed(int keyCode) {


switch (getGameAction(keyCode)) { case
Canvas.FIRE: shoot(); break; case
Canvas.RIGHT: goRight(); break;
...}
}

Mt la chn na l c th to mt tham chiu cho mi hnh ng ca tr chi thng qua


qu trnh khi to gi tr cho cc bin
// Initialization
keyFire = getKeyCode(FIRE);
keyRight = getKeyCode(RIGHT);
keyLeft = getKeyCode(LEFT); ... //
Runtime
protected void keyPressed(int keyCode) { if
(keyCode == keyFire) shoot(); else if
(keyCode == keyRight) goRight()

on m di y minh ha mt s chc nng ca Canvas v cch x l phm


import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class KeyMapping extends MIDlet {
private Display display; // The display
private KeyCodeCanvas canvas; // Canvas

40

public KeyMappingQ {
display = Display.getDisplay(this); canvas = new
KeyCodeCanvas(this);
}
protected void startApp() {
display.setCurrent( canvas );
}

protected voidpauseApp() {}
protected void destroyApp( boolean unconditional) {} public void
exitMIDlet() {
destroyApp(true);
notifyDestroyed();
}
}

/* -------------------------------- * Class KeyCodeCanvas* ------------------------------------ */


class KeyCodeCanvas extends Canvas implements CommandListener { private
Command cmExit; //Exit midlet private String keyText = null; // Key code text
private KeyCodes midlet;
public KeyCodeCanvas(KeyCodes midlet) { this.midlet =
midlet;
// Create exit command and listen for events cmExit = new
Command("Exit", Command.EXIT, 1); addCommand(cmExit);
setCommandListener(this);
}

protected voidpaint(Graphics g) {
// Clear the background (to white) g.setColor(255,
255, 255); g.fillRect(0, 0, getWidth(), getHeight());
// Set color and draw text if (keyText != null) { //
Draw with black pen g.setColor(0, 0, 0); // Center
text
g.drawString(keyText, getWidth()/2, getHeight()/2, Graphics.TOP |
Graphics.HCENTER);
}

}
public void commandAction(Command c, Displayable d) {

41

if (c == cmExit) midlet.exitMIDlet();
protected void keyPressed(int keyCode) { keyText =
getKeyName(keyCode); repaint();
}
}

h) S kin con tr
Trong phn ny chng ta s qun l s kin con tr trong mt Canvas. Nhng skin
ny c thit k lm thun tin cho vic tng tc vi cc thit b c dng con tr. Mt
s phng thc c cung cp nhm h tr cho vic x l s kin con tr:
boolean hasPointerEvents()
boolean hasPointerMotionEvents()
voidpointerPressed(int x, int y)
voidpointerReleased(int x, int y)
voidpointerDragged(int x, int y)
Cc phng thc trn c th t gii thch chc nng thng qua tn ca chnh mnh.
V d nh phng thc hasPointerMotionEvents() tr v mt gi tr c kiu boolean nhm
ch r rng thit b di ng c h tr khi nim nhp chut v r hay khng. on chng
trnh di y minh ha vic s dng cc s kin con tr thchin mt chng trnh v
n gin:
import javax.microedition.midlet.*; import
javax.microedition.lcdui.*; public class
ScratchPad extends MIDlet {
private Display display; // Display object private
ScratchPadCanvas canvas; // Canvas public
ScratchPad() {
display = Display.getDisplay(this); canvas = new
ScratchPadCanvas(this);
}

protected void startApp() {

42

display.setCurrent( canvas );
protected voidpauseApp() {}
protected void destroyApp( boolean unconditional){}
public void exitMIDlet() {
destroyApp(true); notifyDestroyed();
}
}

/* ------------* Class ScratchPadCanvas * * Pointer event handling * --------------------- */


class ScratchPadCanvas extends Canvas implements CommandListener {
private Command cmExit; // Exit midlet
private Command cmClear; // Clear display
private int startx = 0;
// Where pointer was clicked
starty = 0; currentx = 0;
// Current location
currenty = 0;
private ScratchPad midlet; private boolean clearDisplay =
true; public ScratchPadCanvas(ScratchPad midlet) {
this.midlet = midlet;
// Create exit command and listen for events
cmExit = new Command("Exit", Command.EXIT, 1);
cmClear = new Command("Clear", Command.SCREEN, 1);
addCommand(cmExit);
addCommand(cmClear);
setCommandListener(this);
}

protected voidpaint(Graphics g) {
// Clear the background (to white) if (clearDisplay)
{
g.setColor(255, 255, 255);
g.fillRect(0, 0, getWidth(), getHeight());
clearDisplay = false;
startx = currentx = starty = currenty = 0;
return;
}

// Draw with black pen g.setColor(0, 0,


0);

43

// Draw line
g.drawLine(startx, starty, currentx, currenty); // New starting point is
the current position startx = currentx; starty = currenty;
}
public void commandAction(Command c, Displayable d) { if (c == cmExit)
midlet.exitMIDlet(); else if (c == cmClear) {
clearDisplay = true;
repaint();
}
}

protected void pointerPressed(int x, int y) {


startx = x;
starty = y;
}
protected void pointerDragged(int x, int y) { currentx = x;
currenty = y; repaint();
}
}

3.3 Lp Graphics
Chng ta s dng i tng Graphics v ln mt Canvas.
a) H tr mu
Mt ng dng MIDP ch c mt i tng Display. i tng ny uc dng ly
thng tin ca mn hnh hin th hin ti, v d nh s mu h tr v cc phng thc yu
cu cc i tng c hin th. i tng Display n gin l mt b qun l s hin th ca
thit b v iu khin nhng g sc hin th ra trn thit b.
C hai phng thc chng ta cn quan tm n:
boolean isColor() int
numColors()
Phng thc u tin cho bit thit b c h tr hin th mu hay khng. Nu c th phng
thc th 2 s c gi xc nh s mu c h tr. Cc phng thc tip theo di y
ly v mu v thit lp mu a thch ca bn

44

void setColor(int RGB) void setColor(int red, int green,


int blue) int getColor() int getBlueComponent() int
getGreenComponent() int getRedComponent() void
setGrayScale(int value) int getGrayScale()
Ch ta c th xc nh mu bng 2 cch.
-

Cch 1: Xc nh mt s nguyn i din cho 3 gi tr ca mu l , xanh l cy v


xanh dng vi 8 bit cho mi mu.

Cch 2: Dng tng tham s ring bit xc nh mi mu. Khi s dng mt gi tr


lu gi mu, th mu s chim 8 bit u k t bn tri, tip theo l 8 bit dnh cho mu
xanh l cy, sau cng l mu xanh dng. Di y l cch thit lp mu ch s dng
mt s nguyn:

int red = 0, green = 128, blue = 255;

g.setColor((red << 16) | (green << 8) | blue);

V ta c th xc nh mu bng cch thit lp gi tr cho 3 tham s:


g.setColor(red, green, blue);

b) Loi nt ve
Bn c th chn nt khi vng thng, cung v hnh ch nht trn thit b hin th. Di y
l cc phng thc dng thit lp loi nt ve
int getStrokeStyle() void setStrokeStyle(int style) Hai kieu net ve duoc dinh nghia
trong lop Graphics la net cham, va net lien
g.setStrokeStyle(Graphics.DOTTED
g.setStrokeStyle(Graphics.SOLID);

c) V cung

45

Khi v mt cung, bn c th v n ch c ng bao xung quanh hay yu cu n c


t bn trong. Bn c th bt u bng cch chnh chiu bao quanh bn ngoi ca mt hnh
hp ch nht tng tng. Gc bt u xc nh v tr bt u vkhung, vi gi tr 0 c xc
nh ti thi im 3 gi. Gi tr dng tnh theo ngc chiu kim ng h. Gc ca cung ch
ra rng c bao nhiu c v tnh t gc ban u, i theo ngc chiu kim ng h.
hiu r nhng phn ny chng ta hy cng xem1 v d sau:
g.drawArc(10, 10, 100, 100, 0, 150);
on m trn yu cu v mt cung, cung ny c bao bi mt hnh ch nht c ta im
tri trn l (10, 10), chiu rng v chiu di l 100, gc bt u l 0, gc kt thc l 150
Mt s cc phng thc dng v cung

startAngle

'OC100

void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) void fillArc(int x, int
y, int width, int height, int startAngle, int arcAngle)
Di y l on m minh ha vic s dng cc hm trn v mt cung
import javax.microedition.midlet.*; import
javax.microedition.lcdui.*; public class DrawShapes
extends MIDlet { private Display display; // The display
46

private ShapesCanvas canvas; // Canvas public


DrawShapes() {
display = Display.getDisplay(this); canvas
ShapesCanvas(this);

new

protected void startApp() {


display.setCurrent( canvas );
}

protected voidpauseApp() {}
protected void destroyApp( boolean unconditional) {}
public void exitMIDlet() { destroyApp(true);
notifyDestroyed();
}
class ShapesCanvas extends Canvas implements CommandListener { private
Command cmExit; //Exit midlet private DrawShapes midlet; public
ShapesCanvas(DrawShapes midlet) { this.midlet = midlet;
// Create exit command and listen for events cmExit = new Command("Exit",
Command.EXIT, 1); addCommand(cmExit); setCommandListener(this);
}

protected voidpaint(Graphics g) { // Clear background to


white g.setColor(255, 255, 255); g.fillRect(0, 0, getWidth(),
getHeight()); // Black pen g.setColor(0, 0, 0);
//Start at 3 o'clock and rotate 15 degrees
g.drawArc(10, 10, 100, 100, 0, 150); // Fill the arc
// g.fillArc(10, 10, 100, 100, 0, 150);
//Start at 12 o'clock and rotate 150 degrees
// g.drawArc(10, 10, 100, 100, 90, 150);
// Change the size of the bounding box
//Start at 12 o'clock and rotate 150 degrees
//g.drawArc(15, 45, 30, 70, 90, 150);} public void commandAction(Command c,
Displayable d) { if (c == cmExit) midlet.exitMIDlet();
}
}

d) V hnh ch nht

47

Cng ging nh cung th hnh ch nht c th chc v vin bao quanh hoc t bn
trong. Bn cnh bn c th v hnh ch nht c 4 gc l trn hoc l vung. Di y l
mt s phng thc v hnh ch nht:
void drawRect(int x, int y, int width, int height)
void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight)
void fillRect(int x, int y, int width, int height)
void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight)
Khi v hnh ch nht c 4 gc l trn th bn phi xc nh ng knh theo chiu ngang
(arcWidth) v ng knh theo chiu dc (arcHeight). Nhng tham s ny c nh ngha
sc nt ca cung theo mi chiu. Gi tr cng ln th hin mt cung tng dn, ngc li l mt
ng cong hp.
e) Font ch
Phn sau y cng quan trng khng km l cch s dng font chc h tr bi giao din
cp thp ca ng dng MIDP. Sau y l mt s cc phng thc dng ca lp Font:
Font getFont(int face, int style, int size) Font
getFont(int fontSpecifier) Font getDefaultFont() Mot so
thuoc tinh cua lop Font FACESYSTEM
FACEMONOSPACE FACEPROPORTIONAL
STYLEPLAIN STYLEBOLD STYLEITALIC
STYLEUNDERLINED SIZESMALL SIZEMEDIUM
SIZELARGE
Cc tham s kiu dng c th c kt hp thng qua ton t | . V du
Font font = Font.getFont(Font.FACE_SYSTEM ,Font.STYLEBOLD |
Font.STYLE ITALIC, Font.SIZE SMALL);
Sau khi bn c mt tham chiu n mt i tng Font, bn c th truy vn n xc nh
thng tin ca cc thuc tnh ca n.
int getFace()
int getStyle()
int getSize()
boolean isPlain()
boolean isBold()
boolean isItalic()
boolean isUnderlined()
48

Kch thc ca cc font ch c xc nh bi chiu cao ca font ch, b di tnh bng im


nh ca mt chui k t trong mt font xc nh. Mt s cc phng thc sau h tr khi tng
tc vi mt i tng font:
int getHeight()
int getBaselinePosition()
int charWidth(char ch)
int charsWidth(char[] ch, int offset, int length) int
stringWidth(String str)
int substringWidth(String str, int offset, int length) f) Diem neo
xc nh ta x, y ca chui k tc hin th, th im neo cho php chng ta ch ra v
tr mun t ta (x,y) trn hnh ch nht bao quang chui k t

C 6 im neo c nh ngha trc, 3 theo chiu dc v 3 theo chiu thng ng. Khi xc
nh im neo v chui (cc im neo thng c s dng thnh tng cp), ta phi chn
mt im honh v mt im tung . Cc im neo c nh ngha nh di y:
Chieu ngang
-

LEFT (Ben trai)

HCENTER (Chinh giua cua chieu ngang)

RIGHT (Ben phai)

Chieu doc
-

TOP (d tren)

BASELINE (Dudng thang co sd)

BOTTOM (d duoi)
49

Khi s dng im neo th cn phi ch ra ta x, y ca hnh ch nht bao quanh.


Vi du:
g.drawString("developerWorks", 0, 0, Graphics.TOP | Graphics.LEFT);
Hnh di y m t kt qu ca hm trn:

Bng cch thay i im neo, chng ta c th thay i v tr hin th ca chui k t trn thit
b di ng. V d tip theo chng ta s minh ha tip khi thay i im neo th v tr ca chui
k t cng thay i theo:

g) V cc chui k t
Sau khi tm hiu v font v cc im neo, bn c th v chui k t ra mn hnh
thng qua mt s cc phng thc sau:
void drawChar(char character, int x, int y, int anchor)
void drawChars(char[] data, int offset, int length, int x, int y, int anchor)
void drawString(String str, int x, int y, int anchor)
void drawSubstring(String str, int offset, int len, int x, int y, int anchor)
Vi du:
protected voidpaint(Graphics g) { // Get
center of display int xcenter = getWidth() / 2,
ycenter = getHeight() / 2; // Choose a font
g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLEBOLD,
50

Font.SIZESMALL)); // Specify the center of the text (bounding box) using the anchor
point g.drawString("developerWorks", xcenter, ycenter, Graphics.BASELINE |
Graphics.HCENTER);
}
Tip theo l v d minh ha vic s dung font v xut chui ra thit b hin thi:
import javax.microedition.midlet.*; import
javax.microedition.lcdui.*; public class
FontViewer extends MIDlet {
protected Display display; // The display
protected PrefsForm fmPrefs; // Form to choose font prefs
protected FontCanvas cvFont; // Canvas to display text (in preferred font)
public FontViewer() {
display = Display.getDisplay(this);
cvFont = new FontCanvas(this);
fmPrefs = new PrefsForm("Preferences", this);
}

protected void startApp() {


showCanvas();
}

protected void showCanvas() {


display.setCurrent(cvFont);
}

protected voidpauseApp() {}
protected void destroyApp( boolean unconditional) {}
public void exitMIDlet() {
destroyApp(true); notifyDest
}
}

/*-----------------------------------------------------* FontCanvas.java
* __________________________________ */
import javax.microedition.lcdui.*;
class FontCanvas extends Canvas implements CommandListener { private
int
face, // Font face style, // style size; // size
private String text = "developerWorks"; // Text to display in preferred font private Command
cmExit; // Exit midlet private Command cmPrefs; // Call the preferences form private
FontViewer midlet; //Reference to the main midlet public FontCanvas(FontViewer midlet) {
this.midlet = midlet;
51

// Create commands and listen for events


cmExit = new Command("Exit", Command.EXIT, 1);
cmPrefs = new Command("Prefs", Command.SCREEN, 2);
addCommand(cmExit);
addCommand(cmPrefs);
setCommandListener(this);
}

protected voidpaint(Graphics g) { // Clear the


display
g.setColor(255, 255, 255); // White pen
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(0, 0, 0);
// Black pen
// Use the user selected font preferences
g.setFont(Font.getFont(face, style, size)); // Draw text at center
of display
g.drawString(text, getWidth()/2, getHeight()/2,Graphics.BASELINE | Graphics.HCENTER);
}

protected void setFace(int face) {


this.face = face;
protected void setStyle(int style) { this.style =
style;
}

protected void setSize(int size) { this.size =


size;
}

public void setText(String text) { this.text =


text;
}

public int getFace() { return face;


}

public int getStyle() { return style;


}

public int getSize() { return size;


}

public void commandAction(Command c, Displayable d) { if (c == cmExit)


midlet.exitMIDlet();
else if (c == cmPrefs) midlet.display.setCurrent(midlet.fmPrefs);
}
}

52

h) V nh
Lp Graphics cung cp 1 phng thc dng v nh:
drawImage(Image img, int x, int y, int anchor)
Chng ta cng p dng tng bc khi v nh cng ging nh khi xut chui ra mn
hnh. i vi c 2 th chng ta u phi bt u bng vic thit lp ta x, y cng nhim
neo. Danh sch cc im neo cho vic hin th nh cng khng khc my so vi vic xut
chui, tuy nhin khng ging vi vic xut chui th mt bc nh c mt im trung tm. V
thVCENTER c thay th cho gia tr BASELINE khi lm vic vi nh.
Chieu ngang
-

LEFT (Ben trai)

HCENTER (Diem chinh gitta theo chieu ngang)

RIGHT (Ben phai)

Chieu doc
-

TOP (Diem tren)

VCENTER (Diem chinh gitta theo chieu doc)

BOTTOM (Ben duoi

Trong cc phn trc, chng ta to ra cc ng dng MIDP cho vic trnh by mt tm nh


c t mt ngun ti nguyn l mt tp tin. Loi nh ny khng cho php thay i, v v vy
cn c bit vi tn l nh khng th thay i. i vi v d sau y, chng ta s to ra mt
tm nh bng cch cp pht b nh cho tm nh, ly tham chiu n mt i tng
Graphics, v chng ta s t v ni dung tm nh. Loi nh ny cn c bit vi mt ci tn l
nh c th bin thay i c

53

import javax.microedition.midlet.*; import


javax.microedition.lcdui.*; public class DrawImage
extends MIDlet { private Display display; // The display
private ImageCanvas canvas; // Canvas public
DrawImage() {
display = Display.getDisplay(this); canvas = new
ImageCanvas(this);
}

protected void startApp() {


display.setCurrent( canvas );
protected voidpauseApp(){}
protected void destroyApp( boolean unconditional) {}
public void exitMIDlet() {
destroyApp(true); notifyDestroyed();
}

}
/*

* Class ImageCanvas *
* _______________________________ */
class ImageCanvas extends Canvas implements CommandListener {
private Command cmExit; //Exit midlet
private DrawImage midlet;
private Image im = null;
private String message = "developerWorks";
public ImageCanvas(DrawImage midlet) {
this.midlet = midlet; // Create exit command and listen for events
cmExit = new Command("Exit", Command.EXIT, 1);
addCommand(cmExit);
setCommandListener(this);
try{
// Create mutable image
im = Image.createImage(100, 20);
// Get graphics object to draw onto the image
Graphics graphics = im.getGraphics();
// Specify a font face, style and size
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE PLAIN, Font.SIZE
MEDIUM); graphics.setFont(font);
// Draw a filled (blue) rectangle, with rounded corners graphics.setColor(0, 0, 255);
54

graphics.fillRoundRect(0,0, im.getWidth()-1, im.getHeight()-1, 20, 20);


// Center text horizontally in the image. Draw text in white graphics.setColor(255, 255, 255);
graphics.drawString(message, (im.getWidth() / 2)
font.stringWidth(message) / 2), (im.getHeight() / 2) -(font.getHeight() /2),
Graphics.TOP | Graphics.LEFT);
catch (Exception e) {
System.err.println("Error during image creation");
}
}

protected voidpaint(Graphics g) { // Clear the display


g.setColor(255, 255, 255);
g.fillRect(0, 0, getWidth(), getHeight()); // Center the image on the display
if (im != null)
g.drawImage(im, getWidth()/2, getHeight()/2,Graphics.VCENTER | Graphics.HCENTER);
}

public void commandAction(Command c, Displayable d) { if (c == cmExit)


midlet.exitMIDlet();
}
}

i) Mt s cc phng thc khc ca lp Graphics:


clip() v translate() l 2 phng thc ca lp Graphics. Mt vng hin th c ct xn
c nh ngha l khu vc hin th ca thit b di ng, vng ny s c cp nht trong sut
thao tc v li. Di y l mt s phng thc h tr cho vic xn mt vng hin thi
void setClip(int x, int y, int width, int height) void
clipRect(int x, int y, int width, int height) int getClipX() int
getClipY() int getClipWidth() int getClipHeight()
translate() l mt phng thc c s dng c lin quan n h thng trc ta .Chng ta c
th tnh tin h trc ta n mt im x, y khc. Mt s phng thc h tr cho vic tnh
tin h trc ta :
void translate(int x, int y) int
getTranslateX()
int getTranslateY()

55

56

Chng III: H THNG QUN L BN GHI


(Record Management System - RMS)
MIDP khng s dng h thng file lu tr d liu. Thay vo MIDP lu ton b thng tin
vo non-volatile memory bng h thng lu tr gi l Record Management System (RMS).
1. Lu tr c nh thng qua Record Store
RMS l h thng c t chc v qun l di dng cc record (bn ghi). Mi bn ghi
(sau ny gi l Record) c th cha bt k loi d liu no, chng c th l kiu s nguyn,
chui k t hay c th l mt nh v kt qu l mt Record l mt chui (mng) cc byte. Nu
bn m ho d liu ca bn di dng nh phn (binary), bn c th lu tr d liu bng
Record sau c d liu t Record v khi phc li d liu ban u. Tt nhin kch thc d
liu ca bn khng c vut qu gii hn qui nh ca thit b di ng. RMS lu d liu gn
nh mt c s d liu, bao gm nhiu dng, mi dng li c mt s nh danh duy nht. Mt
c s d liu kiu bn ghi:
Record ID Data
1
Array
bytes
2
Array
bytes
3
Array
bytes

of
of
of

Mt tp cc bn ghi (sau ny gi l RecordStore) l tp hp cc Record c sp xp c


th t. Mi Record khng thng c lp m n phi thuc vo mt RecordStore no , cc
thao tc trn Record phi thng qua RecordStore cha n. Khi to ra mt Record trong
RecordStore, Record c gn mt snh danh kiu s nguyn gi l Record ID. Record u
tin c to ra sc gn Record ID l 1 v setng thm 1 cho cc Record tip theo. Cn ch
rng Record ID khng phi l ch mc (index), cc thao tc xa Record trong RecordStore s
khng gy nn vic tnh ton li cc Record ID ca cc Record hin c cng nh khng lm

57

thay i Record ID ca cc Record c to mi, v d: khi ta xa record id 3 khi thm mt


record mi s c id l 4. Data l mt dy cc byte i din cho d liu cn lu.
Tn c dng phn bit cc RecordStore trong b cc MIDlet (MIDlet suite). Cn ch
khi nim MIDlet suite l tp cc MIDlet c chung khng gian tn (name space), c th chia
s cng ti nguyn (nh RecordStore), cc bin tnh (static variable) trong cc lp v cc
MIDlet ny sc ng gi trong cng mt file .jar khi trin khai. Nu ng dng ca bn
ch c mt MIDlet th cc RecordStore c s dng cng phn bit ln nhau bng cc tn.
Tn ca RecordStore c th di n 32 k t Unicode v l duy nht trong mt MIDlet suite.

ng lin th hin vic truy xut Record store do MIDlet to ra, ng nt t l


Record store do MIDlet khc to ra. Trong MIDLET Suite One, MIDlet #1 v MIDlet #2 cng
c th truy xut 4 Record store. MIDLET Suite One khng th truy xut Record store trong

58

Suite Two. Trong MIDlet Suite One tn ca cc Record store l duy nhy, tuy nhin Record
store trong cc MIDlet Suite khc nhau c th dng chung mt tn.
Record Store cn c 2 thuc tnh l Version Number v Date/time Stamp, cc gi tr ny thay
i khi thc hin thm, thay th hay xa mt record, ngoi ra cn coth dng c ch event
handler (Listener) pht hin mi khi Record store b thay i. Version number l mt s
integer, bit gi tr khi u cn gi hm getVersion() sau khi to mt Record store.
Date/time Stamp l s long integer, l s miliseconds k t ngy 1 thng 1 nm 1970, chng ta
c th bit c gi tr ny thng qua hm getLastModified().
2. Cc Vn Lin Quan n RMS
a) Hn ch v kh nng lu tr ca thit b di ng
Dung lng vng nh (non-volatile memory) dnh ring cho vic lu tr d liu trong
RMS thay i ty theo thit b di ng. c t MIDP yu cu rng cc nh sn xut thit b di
ng phi dnh ra vng nh c kch thc t nht 8K cho vic lu tr d liu trong RMS. c
t khng nu gii hn trn cho mi Record. RMS cung cp cc API xc nh kch thc ca
mi Record, tng dung lng ca RecordStore v kch thc cn li ca vng nh ny. Do
trong qu trnh pht trin cc ng dng J2ME lp trnh vin phi cn nhc trong vic s dng
vng nh ny.
b) Tc truy xut d liu
Cc thao tc trn vng nh ny (non-volatile memory) tt nhin s chm hn nhiu khi truy
xut d liu trn b nh RAM (volatile memory). N s ging nh tc c cng v tc
c t RAM ca my tnh. V vy trong k thut lp trnh phi thng xuyn cache d liu v
cc thao tc lin quan n RMS ch thc hin tp trung mt ln (lc khi ng hay ng ng
dng).
c) C ch lung an ton.

Nu RecordStore ca ch c s dng bi mt MIDlet th khng phi lo lng v vn ny v


RMS s dnh ring mt Thread thc hin cc thao tc trn RecordStore. Tuy nhin nu c

59

nhiu MIDlet v Thread cng chia s mt RecordStore th phi ch n k thut lp trnh


Thread m bo khng c s xung t d liu.
3. Cac Ham API Trong RMS
RecordStore khong co ham khoi tao.

60

Chng ta hy cng xem qua v d n gin ca vic c ghi record trong RecordStore. V d:
c v ghi i tng string (ReadWrite.java)
/*--------------------------------------------------------------------* ReadWrite.java
*/
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.*;
public class ReadWrite extends MIDlet {
private RecordStore rs = null;
static final String RECSTORE = ndb_1n;
public ReadWrite() {
openRecStore(); // Create the record store
// Write a few records and read them back
writeRecord("J2ME and MIDP");
writeRecord("Wireless Technology");
readRecords();
closeRecStore(); // Close record store
deleteRecStore();
//Remove the record store
61

}
public void destroyApp( boolean unconditional) {}
public void startApp() {
// There is no user interface, go ahead and shutdown
destroyAppfalse);
notifyDestroyed();}
public voidpauseApp() {}
public void openRecStore() {
try {
// Create record store if it does not exist
rs = RecordStore.openRecordStore(REC_STORE, true);
}

catch (Exception e) { db(e.toString());


}
}

public void closeRecStore() {


try {
rs.closeRecordStore();
}

catch (Exception e) { db(e.toString());


public void deleteRecStore() {
if (RecordStore.listRecordStores() != null) {
try {
RecordStore.deleteRecordStore(RECSTORE);
}

catch (Exception e) { db(e.toString());


}

}
}

public void writeRecord(String str) { byte[] rec =


str.getBytes();
try {
rs.addRecord(rec, 0, rec.length);
}

catch (Exception e) { db(e.toString());


}
}

public void readRecords() {


try {
byte[] recData = new byte[50]; int len;

62

for (int i = 1; i <= rs.getNumRecords(); i++) { len = rs.getRecord( i, recData,


0); System.out.println("Record #" + i + " + new
String(recData, 0, len));
System.out.println(" -------------------------------------------------------------- ");
}
}

catch (Exception e) { db(e.toString());


}
}

private void db(String str) {


System.err.println("Msg: " + str);}
}
}

Day la output cua vi du 1:

Hm m mtrecordstore
public void openRecStore() {
// Create record store if it does not exist
rs = RecordStore.openRecordStore(REC_STORE, true );
}
catch (Exception e) {
db(e.toString());
}

}
Vi tham s true, hm s to mt RecordStore nu n cha tn ti. Trong hm WriteRecord,
trc khi lu vo RecordStore, cn phi chuyn i kiu string thnh dy byte:
63

byte[] rec = str.getBytes();


rs.addRecord(rec, 0, rec.length);
Trong hm ReadRecord, chng ta cng cn c mt dy byte:
byte[] recData = new byte[50];
len = rs.getRecord( i, recData, 0);
Cn lu l trong v d trn do bit trc kch thc ca string nn khai bo dy byte
va , trong thc t ta nn kim tra kch thc ca record khai bo dy byte cn thit
trnh pht sinh li, do hm ReadRecord c th sa li nh sau:
for (int i = 1; i <= rs.getNumRecords(); { if
(rs.getRecordSize(i) > recData.length)
recData = new byte[rs.getRecordSize(i)];
len = rs.getRecord(i, recData, 0);
System.out.println("Record #" + i + ": " + new String(recData, 0, len));
System.out.println(" ------------------------------------------ ");
}

Nu ch cn c ghi nhng on text vo record, th v d trn l qu . Tuy nhin, thc


t l ta cn lu nhng gi tr khc: String, int, boolean, v.v... Trong trng hp ny, chng ta
cn s dng stream c v ghi record. Vic s dng stream gip chng ta linh ng v nng
cao hiu qu ca vic c v ghi d liu vo RecordStore. Chng ta s dng nextRecord()
duyt n record sau , ngoi ra cn c previousRecord() gip duyt v record trc . Nu
mun bt u ti v tr cui cng ca recordstore ta ch cn gi hm previousRecord() ngay khi
m recordstore, n s tr v dng cui cng.
RecordEnumeration c duy tr mt index ca cc record. Khi recordstore c s thay i
th RecordEnumeration c th hot dng khng chnh xc, do chng ta cn phi gi hm
reindex() mi khi recordstore c s thay i.
RecordEnumeration API
RecordEnumeration Interface:
javax.microedition.rms.RecordEnumeration
Method
Description
int numRecords()
So luong record trong enumeration
byte[] nextRecord()
Record tiep theo
int nextRecordId()
Record ID cua record tiep theo
64

byte[] previousRecord()
int previousRecordId()
boolean hasNextElement()
boolean hasPreviousElement()
void keepUpdated(boolean
keepUpdated)
boolean isKeptUpdated()
void rebuild()
void reset()
void destroy()

Record truoc do
Record ID cua record truoc do
Kiem tra enumeration co record ke tiep
Kiem tra enumeration co record truoc do
Dat enumeration reindex sau khi co
suthay doi
Kiem tra enumeration co tudong
reindex()
Tao lai index
Dua enumeration ve record dau tien
Giai phong tai nguyen duoc su dung boi
enumeration

4. Sp Xp Cc Record Vi interface RecordComparator


Interface ny gip ngi lp trnh so snh hai Record theo mt tiu ch no . Interface
ny nh ngha phng thc compare vi tr u vo l hai mng cc byte th hin hai Record
cn so snh. Phng thc ny tr v cc tr sau c nh ngha trong interface:
EQUIVALENT: Neu hai Record bang nhau
FOLLOWS: Neu Record thu 1 dung sau Record thu 2
PRECEDES: Neu Record thu 1 dung truoc Record thu 2
Do RecrdComparator l mt interface nn khi s dng cn phi implements n:
public class Comparator implements RecordComparator {
public int compare(byte[] rec1, byte[] rec2) { Stringstr1 = new
String(rec1), str2 = new String(rec2); int result =
str1.compareTo(str2);
if (result == 0) return RecordComparator.EQUIVALENT; else if (result <
0)
return
RecordComparator.PRECEDES;
else
return
RecordComparator.FOLLOWS;
}
}

Sau ta s dng lp Comparator bng cch gn kt n vi RecordEnumeration:


// Create a new comparator for sorting
Comparator comp = new Comparator();
// Reference the comparator when creating the result set
RecordEnumeration re = rs.enumerateRecords(null,comp,false);
//Iterate through the sorted results while (re.hasNextElement()) {
String str = new String(re.nextRecord()); .

65

Enumeration s s dng hm compare trong class Comparator sp xp cc record trong


RecordStore

V d: chng trnh sp xp c bn:


/*
* SimpleSort.java
*/
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.*;
public class SimpleSort extends MIDlet { private
RecordStore rs = null;
static final String RECSTORE = "db_1";
public SimpleSort() {
openRecStore(); // Create the record store
// Write a few records
writeRecord("Sand Wedge");
writeRecord("One Wood");
writeRecord("Putter");
writeRecord("Five Iron");
// Read back with enumerator, sorting the results
readRecords();
closeRecStore(); // Close record store deleteRecStore(); //Remove
the record store
}
public void destroyApp( boolean unconditional) {} public void
startApp() {
// There is no user interface, go ahead and shutdown
destroyApp(false);
notifyDestroyed();
}

public voidpauseApp() {} public void


openRecStore() {
try {
// Create record store if it does not exist
66

rs = RecordStore.openRecordStore(REC_STORE, true);
}

catch (Exception e) { db(e.toString());


}
}

public void closeRecStore() {


try {
rs.closeRecordStore();
catch (Exception e) { db(e.toString());
}
}

public void deleteRecStore() {


if (RecordStore.listRecordStores() != null) {
try {
RecordStore.deleteRecordStore(RECSTORE);
}

catch (Exception e) { db(e.toString());


}
}
}

public void writeRecord(String str) { byte[] rec =


str.getBytes();
try {
rs.addRecord(rec, 0, rec.length);
}

catch (Exception e) { db(e.toString());


}
}

public void readRecords() {


try {
if (rs.getNumRecords() > 0) {
Comparator comp = new Comparator(); RecordEnumeration re =
rs.enumerateRecords(null,comp, false); while (re.hasNextElement()) {
String str = new String(re.nextRecord());
System.out.println(str);
System.out.println(" ------------------------------------------------------------------- ");
}
}
}

catch (Exception e) { db(e.toString());


}

67

}
private void db(String str) {
System.err.println("Msg: " + str);
}
class Comparator implements RecordComparator { public
int compare(byte[] reel, byte[] rec2) { Stringstrl = new
String(recl), str2 = new String(rec2); int result =
str1.compareTo(str2);
if (result == 0) return RecordComparator.EQUIVALENT; else if (result < 0) return
RecordComparator.PRECEDES; else return RecordComparator.FOLLOWS;
}
}
Trong doan code tren trong ham readRecord(), khi tao Enumeration ta da tham chieu den doi
tuong comp cua lop Comparator
Comparator comp = new Comparator();

RecordEnumeration re = rs.enumerateRecords(null, comp, false);


while (re.hasNextElement()) {... } Khi enumerator tao index cho RecordStore no se su dung
ham compare() o tren de sap xep cac record.
V d trn ng trong trng hp d liu lu vo record l dng text, nu quay li ta ghi
nhiu kiu d liu vo trong mt record:
// Write Java data types to stream
strmDataType.writeUTF("Text 1");

68

strmDataType.writeBoolean(true);
strmDataType.writeInt(1);

th cc kiu d liu trn s c lu vo mt stream dng binary. Sau cc stream ny s


c chuyn thnh mng v a vo recordstore:
// Get stream data into an array record =
strmBytes.toByteArray(); // Write the array to a
record rs.addRecord(record, 0, record.length);
on code trong v d trn s chy sai khi p dng vi kiu d liu binary. gii quyt, ta cn
phi vit li hm compare() th c hin chc nng chuyn i chui byte v sp xp ng kiu
d liu. Trong thc t, chng ta cn phi lu nhiu trng d liu trong mt record nh trong
v d 2 (lu d liu kiu String, boolean, integer). Trong trng hp ny s c nhiu la chn
sp xp cc record, v vic la chn ny ty thuc vo ng dng.
Trong 2 v d sau y s thc thi interface RecordComparator sp xp record cha nhiu
kiu d liu. Nhng v d ny s s dng cng d liu u vo, tuy nhin v d 4 s sp xp
da vo kiu String, trong khi v d 5 s sp xp da vo kiu integer. y l d liu s lu vo
recordstore:
String[]pets = {"duke", "tiger", "spike", "beauregard"};
boolean[] dog = {true, false, true, true};
int[] rank = {3, 0, 1, 2};
Khi lu vo recordstore s c dng nh sau:
Record #1
"duke" true 3
Record #2
"tiger" false 0

69

Record #3 "spike" true 1


Record #4 "beauregard"
true 2

y l l do v d trn khng p ng c yu cu, do d liu lu vo khng cn l dng text,


v hm String.CompareTo() trn ni dung ca record khng th sp xp d liu theo mong
mun. Do cn phi ly ra t mi record trng d liu m ta mun sp xp.
Vi du 5: integer sort
/*--------------------------------------------------------------------* IntSort.java

---------------- */

import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.*; public
class IntSort extends MIDlet {
private RecordStore rs = null; // Record store
static final String RECSTORE = "db_4"; // Name of record store
public IntSort() {
openRecStore(); // Create the record store writeTestData(); //
Write a series of records readStream(); //Read back the records
closeRecStore(); // Close record store deleteRecStore(); //Remove
the record store
}

public void destroyApp( boolean unconditional) {} public void


startApp() {
// There is no user interface, go ahead and shutdown
destroyApp(false);
notifyDestroyed();
}

public voidpauseApp() {} public void


openRecStore() {
try {

70

// Create record store if it does not exist


rs = RecordStore.openRecordStore(REC_STORE, true);
catch (Exception e) {
db(e.toString());
}
}

public void closeRecStore() {


try {
rs.closeRecordStore();
}

catch (Exception e) {
db(e.toString());
}
}

public void deleteRecStore() {


if (RecordStore.listRecordStores() != null) {
try {
RecordStore.deleteRecordStore(RECSTORE);
}

catch (Exception e) { db(e.toString());


}
}
}

public void writeTestData() {


String[]pets = {"duke", "tiger", "spike", "beauregard"}; boolean[] dog =
{true, false, true, true}; int[] rank = {3, 0, 1, 2}; writeStream(pets, dog,
rank);
}

public void writeStream(String[] sData, boolean[] bData,int[] iData) {


try {
// Write data into an internal byte array
ByteArrayOutputStream strmBytes = new
ByteArrayOutputStream();
// Write Java data types into the above byte array DataOutputStream
strmDataType = new
DataOutputStream(strmBytes);
byte[] record; for (int i = 0; i < sData.length; i++) { // Write Java data
types

71

strmDataType.writeUTF(sData[i]);
strmDataType.writeBoolean(bData[i]);
strmDataType.writeInt(iData[i]); // Clear any buffered data
strmDataType.flush ();
// Get stream data into byte array and write record
record = strmBytes.toByteArray();
rs.addRecord(record, 0, record.length);
// Toss any data in the internal array so writes
// starts at beginning (of the internal array)
strmBytes.reset();
}

strmBytes.close();
strmDataType.close();
}

catch (Exception e) {
db(e.toString());
}
}

public void readStream() {


try {
byte[] recData = new byte[50];
// Read from the specified byte array
ByteArrayInputStream strmBytes = new
ByteArrayInputStream(recData);
// Read Java data types from the above byte array
DataInputStream strmDataType = new
DatalnputStream(strmBytes);
if (rs.getNumRecords() > 0) {
ComparatorInt comp = new ComparatorInt(); int i = 1;
RecordEnumeration re = rs.enumerateRecords(null,comp, false);
(re.hasNextElement()) {
// Get data into the byte array
rs.getRecord(re.nextRecordId(), recData, 0);
// Read back the data types
System.out.println("Record #" + i++);
System.out.println("Name: " +
strmDataType.readUTF());
System.out.println("Dog: " +
strmDataType.readBoolean());
System.out.println("Rank: " +

while

72

strmDataType.readInt()); System.out.println(" ------------------------------------------------------------------------------------------------------------------------------ ");


// Reset so read starts at beginning of array strmBytes.reset();
}
comp.compareIntClose(); //Free enumerator re.destroy();
}

strmBytes.close(); strmDataType.close();
}

catch (Exception e) { db(e.toString());


}
}
private void db(String str) {
System.err.println("Msg: " + str);
}
}

class ComparatorInt implements RecordComparator { private


byte[] recData = new byte[10]; // Read from a specified byte
array private ByteArrayInputStream strmBytes = null; // Read
Java data types from the above byte array private
DataInputStream strmDataType = null; public void
compareIntClose() {
try {
if (strmBytes != null) strmBytes.close();
if (strmDataType != null) strmDataType.close();
}

catch (Exception e) {}
}

public int compare(byte[] recl, byte[] rec2) { int xl, x2;


try {
// If either record is larger than our buffer, reallocate
int maxsize = Math.max(rec1.length, rec2.length);
if (maxsize > recData.length) recData = new byte[maxsize];
// Read record #1
// We want the integer from the record, which is // the last "field" thus we
must read the String

73

// and boolean to get to the integer


strmBytes = new ByteArrayInputStream(recl);
strmDataType = new DataInputStream(strmBytes);
strmDataType.readUTF();
strmDataType.readBoolean();
xl = strmDataType.readInt();
//Here's our data
// Read record #2
strmBytes = new ByteArrayInputStream(rec2);
strmDataType = new DataInputStream(strmBytes);
strmDataType.readUTF();
strmDataType.readBoolean();
x2 = strmDataType.readInt();
// Here's our data
// Compare record #1 and #2
if (x1 == x2) return RecordComparator.EQUIVALENT; else if (x1 < x2) return
RecordComparator.PRECEDES; else return RecordComparator.FOLLOWS;
}

catch (Exception e) {
return RecordComparator.EQUIVALENT;
}
}
}

Trong v d ny tiu ch sp xp l theo kiu integer, do trc ht ta phi ly d liu trong


dy byte. Tuy nhin, c mt lu l do d liu ta cn ly nm cui cng trong dy byte do
ra cn phi c theo th t, tc l phi c kiu String, boolean ri mi n integer:
// Read record #1
// We want the integer from the record, which is // the
last "field" thus we must read the String // and boolean
to get to the integer
strmDataType.readUTF();
strmDataType.readBoolean(); x1 =
strmDataType.readInt(); // Here's
our data // Read record #2
strmDataType.readUTF();
strmDataType.readBoolean();

74

x2 = strmDataType.readInt();
// Here's our data
// Compare record #1 and #2

5. Tm Kim Vi B Lc RecordFilter
Ngoi vic sp xp cc record (s dng RecordComparator), enumerator cn cung cp
c ch lc (tm kim cc record tha mn mt iu kin no ). Khi s dng
RecordComparator tt c cc record trong RecordStore u c lu trong mt result set.
Nhng khi dng RecordFilter, ch c nhng tha mn iu kin mi c trong enumerator result
set..
class SearchFilter implements RecordFilter { private String
searchText = null; public SearchFilter(String searchText) { //
This is the text to search for this.searchText =
searchText.toLowerCase();
}
public boolean matches(byte[] candidate) {
String str = new String(candidate).toLowerCase(); //Look for a match
if (searchText != null && str.indexOf(searchText) != -1) return true; else return false;
75

Trn y l mt class n gin thc thi interface RecordFilter. Class ny sc gn vi mt


enumerator, v khi enumerator s dng hm matches() duyt ht recordstore ly ra nhng
record cn tm:
// Create a new search filter
SearchFilter search = new SearchFilter("search text"); // Reference the filter
when creating the result set RecordEnumeration re =
rs.enumerateRecords(search,null,false); // If there is at least one record in result
set, a match was found if (re.numRecords() > 0) // Do something

Sau y ta s xem qua chng trnh tm kim n gin s dng interface RecordFilter:
Vi du:
/* -------------------------------------------------------------------* SimpleSearch.java *
*/
import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.rms.*; import
javax.microedition.lcdui.*;
public class SimpleSearch extends MIDlet implements CommandListener {
private Display display; // Reference to Display object
private Form fmMain; // The main form private
StringItem siMatch; // The matching text, if any
private Command cmFind; // Command to search record store
private Command cmExit; // Command to insert items
private TextField tfFind; // Search text as requested by user
private RecordStore rs = null; // Record store
static final String RECSTORE = "db_6"; // Name of record store public
SimpleSearch() {
display = Display.getDisplay(this);
tfFind = new TextField("Find", "", 10, TextField.ANY);
siMatch = new StringItem(null, null);
cmExit = new Command("Exit", Command.EXIT, 1);
cmFind = new Command("Find", Command.SCREEN, 2);
76

// Create the form, add commands


fmMain = new Form("RecordSearch");
fmMain.addCommand(cmExit);
fmMain.addCommand(cmFind);
// Append textfield and stringItem
fmMain.append(tfFind);
fmMain.append(siMatch);
// Capture events
fmMain.setCommandListener(this);
//- ----------------------------------------- // Open and write to record store //- -------------------------------------------- openRecStore();
// Create the record store
writeTestData();
// Write a series of records
}
public void destroyApp( boolean unconditional) {
closeRecStore(); // Close record store deleteRecStore();
}

public void startApp() {


display.setCurrent(fmMain);
}

public voidpauseApp() {} public void


openRecStore() {
try {
// Create record store if it does not exist
rs = RecordStore.openRecordStore(REC_STORE, true);
}

catch (Exception e) { db(e.toString());


}
}

public void closeRecStore() {


try {
rs.closeRecordStore();
}

catch (Exception e) { db(e.toString());


}
}

public void deleteRecStore() {


if (RecordStore.listRecordStores() != null) {
try {
77

RecordStore.deleteRecordStore(RECSTORE);
}

catch (Exception e) { db(e.toString());


}
}
}

public void writeTestData() {


String[] golfClubs = { "Wedge...good from the sand trap", "Truong dai hoc Cong nghe Thong
tin & Truyen thong ", "Putter...only on the green", "Hoc mon LT mobile rat bo ich!"};
writeRecords(golfClubs);
}

public void writeRecords(String[] sData) { byte[]


record;
try {
// Only add the records once
if (rs.getNumRecords() > 0) return;
for (int i = 0; i < sData.length; i++) {
record = sData[i].getBytes();
rs.addRecord(record, 0, record.length);
}
}

catch (Exception e) { db(e.toString());


}
}

private void searchRecordStore() {


try {
// Record store is not empty if (rs.getNumRecords() >
0) {
// Setup the search filter with the user requested text
SearchFilter search = new
SearchFilter(tfFind.getString()); RecordEnumeration re
= rs.enumerateRecords(search, null, false);
// A match was found using the filter
if (re.numRecords() > 0)
// Show match in the stringItem on the form siMatch.setText(new
String(re.nextRecord())); re.destroy(); //Free enumerator
}
catch (Exception e) { db(e.toString());
}
}

78

public void commandAction(Command c, Displayable s) { if (c ==


cmFind) {
searchRecordStore();
}

else if (c == cmExit) {
destroyApp(false); notifyDestroyed();
}
}

private void db(String str) {


System.err.println("Msg: " + str);
}
}

class SearchFilter implements RecordFilter { private String


searchText = null; public SearchFilter(String searchText) { //
This is the text to search for this.searchText =
searchText.toLowerCase();
}

public boolean matches(byte[] candidate) {


String str = new String(candidate).toLowerCase(); //Look for a match
if (searchText != null && str.indexOf(searchText) != -1) return true; else return false;
}
}

Sau khi vit class SearchFilter, ta to mt instance search, khi khai bo class
RecordEnumeration s tham chiu n instance trn. Khi ch c nhng record tha mn iu
kin (trong hm matches()) mi hin th trong result set:
// Setup the search filter with the user requested text
SearchFilter search = new SearchFilter(tfFind.getString());
RecordEnumeration re =rs.enumerateRecords(search,null,false);
// A match was found using the filter
if (re.numRecords() > 0) siMatch.setText(new String(re.nextRecord()));
Output:

79

6. Nhn Bit Thay i Vi RecordListener


pht hin cc thay i cng nh thm vo cc Record trong RecordStore, RMS
cung cp giao din RecordListener. Giao din ny nh ngha 3 phng thc, cc phng
thc c 2 tr vo l mt i tng kiu RecordStore v mt s int cha recordID. Cc
phng thc l:
RecordListener Interface:
javax.microedrtiQn.rins.RecordListener
void
recordAdded(RecordStore
recordStore, int recordId)
void
recordChanged(RecordStore
recordStore, int recordId)
void
recordDeleted(RecordStore
recordStore, int recordId)

Duoc goi khi them 1 record

Duoc goi khi record bi thay doi

Duoc goi khi record bi xoa

80

Vi du : su dung RecordListener
/*--------------------------------------------------------------------* RmsListener.java *
*/
import java.io.*;
import javax.microedition.midlet.*; import
javax.microedition.rms.*; public class RmsListener
extends MIDlet { private RecordStore rs = null; static
final String RECSTORE = "db_8"; public
RmsListener() {
// Open record store and add listener openRecStore();
rs.addRecordListener(new TestRecordListener());
//Initiate actions that will wake up the listener
writeRecord("J2ME and MIDP");
updateRecord("MIDP and J2ME");
deleteRecord();
closeRecStore();
// Close record store
deleteRecStore();
// Remove the record store
}
public void destroyApp( boolean unconditional) {} public void
startApp() {
// There is no user interface, go ahead and shutdown
destroyApp(false);
notifyDestroyed();
}

public voidpauseApp() {} public void


openRecStore() {
try {
// Create record store if it does not exist
rs = RecordStore.openRecordStore(REC_STORE, true);
}

catch (Exception e) { db(e.toString());


}
}

public void closeRecStore() {

81

try {
rs.closeRecordStoreQ;
}
catch (Exception e) {
db(e.toString());
}
}

public void deleteRecStore() {


if (RecordStore.listRecordStores() != null) {
try {
RecordStore.deleteRecordStore(RECSTORE);
}

catch (Exception e) { db(e.toString());


}
}
}

public void writeRecord(String str) { byte[]


rec = str.getBytes();
try {
rs.addRecord(rec, 0, rec.length);
}

catch (Exception e) {
db(e.toString());
}
}

public void updateRecord(String str) {


try {
rs.setRecord(1, str.getBytes(), 0, str.length());
}

catch (Exception e) {
db(e.toString());
}
}

public void deleteRecord() {


try {
rs.deleteRecord(1);
}

catch (Exception e) {
db(e.toString());

82

}
public void dbfString str) {
System.err.println("Msg: " + str);
}
}
class TestRecordListener implements RecordListener {
public void recordAdded(RecordStore recordStore, int recordId) {
try {
System.out.println("Record with ID#: " + recordId + "added to RecordStore: "
+ recordStore.getName());
}

catch (Exception e) {
System.err.println(e);
}
}

public void recordDeleted(RecordStore recordStore, int recordId) {


try {
System.out.println("Record with ID#: " + recordId + "deleted from RecordStore: " +
recordStore.getName());
}

catch (Exception e) {
System.err.println(e);
}
}

public void recordChanged(RecordStore recordStore, int recordId) {


try{
System.out.println("Record with ID#: " + recordId +
"changed in RecordStore: " recordStore.getName());
}

catch (Exception e) {
System.err.println(e);
}
}
}

83

7. Cc Ngoi L Pht Sinh Trong RMS


Cc phng thc trong API ca RMS ngoi vic pht sinh cc ngoi l thng thng
n mi trng chy (runtime enviroment). RMS cn nh ngha thm cc ngoi l trong gi
javax.microedition.rms nh sau:

84

ChngIV: KHUNG KT NI CHUNG


(Generic Connection Framework - GCF)
Trong phin bn J2SE, h tr cc giao thc kt ni mng c cc gi java.io v
java.net vi tng dung lng hn 200KB bao gm hn 100 lp v giao din. Qa tht vi
b nh nh b v hn ch trong x l, vic a nhng gi ny vo trong ng dng vit bng
J2ME l mt iu hon ton khng kh thi. Chnh v vy, khi m rng phm vi h tr giao
thc mng v h thng tp tin, ngoi ta khng dng li cc lp ca J2SE m xy dng mt
khi nim mi c gi l Khung kt ni chung (Generic Connection Framework - GCF).
GCF l mt tp hp cc lp v giao din c thit k nhm ta thun tin cho vic
truy xut n cc h thng lu tr v kt ni mng. Mc tiu ca GCF khng phi l to ra
mt tp cc lp mi hon ton m n cung cp mt tp con ca J2SE mt cch c chn lc.
Tp con ny c gii hn v ti u ph hp vi nhng rng buc v khc bit ca
nhng thit b di ng.
1. Cy phn cpConnection
Khi a ra khi nim cy phn cp, ngi ta ch to ra mt lp c kh nng m
mi loi kt ni bao gm: file, http, datagram, ... Tn ca lp ny l Connector. Nh vy
nu s dng Connector m kt ni, chng ta ch cn gi mt phng thc open c nh
dng nh sau:
Connector.Open("protocol:address; parameter")
C ch m GCF dng m nhiu loi giao tip ch bng mt phng thc chung
duy nht ny chng minh tnh uyn chuyn ca GCF. C ch ny hot ng nh sau:
Trong thi gian thc thi, mi khi c yu cu m mt giao thc, Connector s tm n
lp tng ng ci t giao thc y. Qu trnh tm kim ny c thc hin thng qua
phng thc Class.forName(). V d nh yu cu m kt ni HTTP trong J2ME, yu cu
s c vit nh sau:

85

Class.forName("com.sun.midp.io.j2me.http.Protocol");
Khi tm thy lp tng ng, Class.forName() s tr v mt i tng c ci
t giao din Connection (trong lp Connector v giao din Connection c
nh ngha sn trong CLDC) Sau y l cy phn cp Connection, n bao gm cc
lp

mi

lp

nh

ngha

nh

mt

giao

din:

Trong kin trc ca cy phn cp, ci t tht s ca c giao thc u nm mc


hin trng. Trong MIDP 1.0, HttpConnection h tro mt tpj con HTTP phin bn 1.0.
Do khi lp ny m rng ContentConnection, n c cung cp sn hn 20 phng
thc chuyn bit giao tip thng qua giao thc HTTP.
Mc d DatagramConnection cng xut hin trong cy phn cp nhng ngi ta khng
bt buc ci t MIDP h tr giao thc ny..

86

2. Kt ni HTTP
HTTP l giao thc duy nht chc chn c h tr bi MIDP 1.0. Chng ta c th giao tip
vi my ch hay bt k thit b t xa no c h tr giao thc ny nh vo lp
HttpConnection. Lp Connector cung cp cho ngi dng by phng thc to kt ni
ti my ch. Ba phng thc trong s l cc bin th ca phng thc open(). Cc
phng thc ny c m t trong bng sau:

Cac phuong thuc cua lop javax.microedition.io.Connector


Phuong thuc
Mo ta
static Connection open(String

Tao mot ket noi co che do

name)

READWRITE

static Connection open(String name, int Tao mot ket noi voi che do duoc
mode)

chi dinh
Tao mot ket noi voi che do

static Connection open(String name, int


duoc chi dinh, them ngoai le
mode, boolean timeouts)
time out
static InputStream

Tao ket noi luong nhap

openInputStream(String name)
static OutputStream

Tao ket noi luong xuat

openOutputStream(String name)
static DataInputStream

Tao ket noi luong nhap kieu

openDataInputStream(String name)

DataInputStream

static DataOutputStream
Tao ket noi luong xuat kieu
openDataOutputStream(String
DataOutputStream
name)

87

Duoi day la doan code md ket noi thong qua stream


// Create a ContentConnection
String url = "http://www.corej2me.com";
ContentConnection connection = (ContentConnection) Connector.open(url);
// With the connection, open a stream
InputStream iStrm = connection.openInputStream();
// ContentConnection includes a length method
int length = (int) connection.getLength();
if (length != -1) {
byte imageData[] = new byte[length];
// Read the data into an array
iStrm.read(imageData);
}
Tht ra chng ta c th ta mt kt ni InputStream m khng cn s c mt ca
ContentConnection. Tuy nhin, phng php ny c hn ch l khng cung cp phng
thc xc nh chiu di d liu.
Di y l cch m mt kt ni dng HttpConnection:
String url = "http://www.corej2me.com/midbook_v1e1/ch14/duke.png";
HttpConnection http = (HttpConnection) Connector.open(url);
Sau khi c m, kt ni ny cung cp truy xut n rt nhiu loi lung m
InputStream v DataInputStream l hai trong s . Tuy nhin th mnh thc s ca kt ni
HttpConnection li nm ch n c kh nng gip cho lp trnh vin loi b cc gnh nng
ca cc cu lnh HTTP.
Di y l v d n gin, u tin MIDlet s download v hin th hnh nh ti
v. MIDlet s d dng ByteArrayOutputStream cha d liu ti v bi v ta khng dng
ContentConnection nn khng th bit kch c d liu ti v

88

/* --------------------------------------------------------------------* DownloadImage.java *
*/
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*; import
javax.microedition.io.*; import java.io.*;
public class DownloadImage extends MIDlet implements CommandListener {
private Display display;
private TextBox tbMain;
private Form fmViewPng;
private Command cmExit;
private Command cmView;
private Command cmBack;
public DownloadImage() {
display = Display.getDisplay(this);
// Create the textbox, allow maximum of 50 characters
tbMain = new TextBox("Enter url", "http://localhost/intel.png", 55, 0);
// Create commands and add to textbox
cmExit = new Command("Exit", Command.EXIT, 1);
cmView = new Command("View", Command.SCREEN, 2);
tbMain.addCommand(cmExit);
tbMain.addCommand(cmView );
// Set up a listener for textbox
tbMain.setCommandListener(this);
// Create the form that will hold the image
fmViewPng = new Form("");
// Create commands and add to form
cmBack = new Command("Back", Command.BACK, 1);
fmViewPng.addCommand(cmBack);
// Set up a listener for form
fmViewPng.setCommandListener(this);
}
public void startApp() {
display.setCurrent(tbMain);
}

public voidpauseApp() {}
public void destroyApp(boolean unconditional) {}
public void commandAction(Command c, Displayable s) {

89

// If the Command button pressed was "Exit" if (c == cmExit) {


dstroyAppfalse); notifyDestroyed();
}

else if (c == cmView) {
// Download image and place on the form
try {
Image im;
if ((im = getImage(tbMain.getString())) != null) {
ImageItem ii = new ImageItem(null, im,ImageItem.LAYOUTDEFAULT, null);
// If there is already an image, set (replace) it
if fmViewPng.size() != 0)
fmViewPng.set(0, ii);
else // Append the image to the empty form
fmViewPng.append(ii);
}
else fmViewPng.append("Unsuccessful download.");
// Display the form with image
display.setCurrentfmViewPng);
}
catch (Exception e) {
System.err.println("Msg: " + e.toString());
}
}

else if (c == cmBack) {
display.setCurrent(tbMain);
}
}

private Image getImage(String url) throws IOException {


InputStream iStrm = (InputStream) Connector.openInputStream(url);
Image im = null;
try {
ByteArrayOutputStream bStrm = new ByteArrayOutputStream();
int ch;
while ((ch = iStrm.read()) != -1)
bStrm.write(ch);
// Place into image array
byte imageData[] = bStrm.toByteArray();
// Create the image from the byte array
im = Image.createImage(imageData, 0, imageData.length);

finally {
// Clean up
if (iStrm != null)
iStrm.close();
}

return (im == null ? null: im);


}
}

Mt textbox s cho php nhp a ch URL

Sau khi ti v, hnh nh sc hin th

3. Client Request va Server Response


C HTTP v HTTPS u gi request v response. My client gi request, cn server s tr
v response. Client request bao gm 3 phn sau:
-

Request method

Header

Body

Request method nh ngha cch m d liu s c gi n server. C 3 phng thc


c cung cp sn l GET, POST, HEADER. Khi s dng Get, d liu cn request s nm
trong URL. Vi Post d liu gi t client sc phn thnh cc stream ring bit. Trong khi
, Header s khng gi d liu yu cu ln server, thay vo header ch request nhng
meta information v server. GET v POST l hai phng thc request kh ging nhau, tuy
nhin do GET gi d liu thng qua URL nn s b gii hn, cn POST s dng nhng
stream ring bit nn s khc phc c hn ch ny.
V d v vic m HTTP Connection thng qua GET
String url = "http://www.corej2me.com?size=large";
HttpConnection http = null;
http = (HttpConnection) Connector.open(url);
http.setRequestMethod(HttpConnection.GET);
Nhng Header field s cho php ta truyn cc tham s t client n server. Cc
header field thng dng l If-Modified-Since, Accept, and User Agent. Bn c tht cc
field ny thng qua phng thc setRequestProperty(). Di y l v d dng
setRequestProperty(), ch c nhng d liu thay i sau ngy 1 thng 1 nm 2005 mi c
gi v t server:
String url = "http://www.corej2me.comXsomefile.txt";
HttpConnection http = null;
http = (HttpConnection) Connector.open(url);
http.setRequestMethod(HttpConnection.GET);
// Set header field as key-value pair

92

http.setRequestProperty("If-Modified-Since", "Sat, 1 Jan 2005 12:00:00


GMT");Body cha ni dung m bn mun gi ln server. V d v s dng POST v gi d
liu tclient thng qua stream:
String url = "http://www.corej2me.com";
tmp = "test data here";
OutputStream ostrm = null;
HttpConnection http = null;
http = (HttpConnection) Connector.open(url);
http.setRequestMethod(HttpConnection.POST); // Send
client body ostrm = http.openOutputStream(); byte bytes[]
= tmp.getBytes(); for(int i = 0; i < bytes.length; {
os.write(bytes[i]);
}

os.flush();
Sau khi nhn c v s l yu cu t pha client, server s ng gi v gi v pha client.
Cng nh client request, server cng gm 3 phn sau:
Status line
Header
Body
Status line s thng bo cho client kt qu ca request m client gi cho server. HTTP phn
loi status line thnh cc nhm sau y:
1xx is informational
2xx is success
3xx is redirection
4xx is client error
5xx is server error
Status line bao gm version ca HTTP trn server, status code, v on text i din cho
status code.
Vi du: "HTTP/1.1 200 OK" "HTTP/1.1 400 Bad Request" "HTTP/1.1 500 Internal Server
Error"
Header.
Khng ging nh header ca client, server c th gi data thng qua header.
93

Sau y l nhng phng thc dng ly thng tin Header m server gi v:


String getHeaderField(int n)
index
String getHeaderField(String name)
name
String getHeaderFieldKey(int n)

Get header field value looking up by


Get header field value looking up by
Get header field key using index

Server c th tr v nhiu Header field. Trong trng hp ny, phng thc u tin s
cho ly header field thng qua index ca n. Cn phng thc th hai ly ni dung header
field da vo tn ca header field. Cn nu mun bit tn (key) ca header field, c th dng
phng thc th 3 trn.
Sau y l v d v 3 phng thc trn, trong trng hp server gi v chui "contenttype=text/plain".

Body: Cng ging nh client, server gi hu ht nhng thng tin trong phn body cho client.
Client dng input stream c kt qu tr v t server. The HttpConnection API Nh
cp trn, ta s s dng HttpConnection API thit lp kt ni trong MIDP. Di y l
nhng API trong HttpConnection:
Method
long getDate()
long getExpiration()

Description
Get header field date
Gets header field expiration

94

String getFile()
int getHeaderField(int n)
String getHeaderField(String name)

Gets filename from the URL


Gets header field value looking up by index
Gets header field value looking up by name

long getHeaderFieldDate(String

Gets named field as a long (representing the

name, long def)

date)

int getHeaderFieldInt(String name, int


def)
String getHeaderFieldKey(int n)
String getHost()
long getLastModified()
String getPort()
String getProtocol()
String getQuery()
String getRef()
String getRequestMethod()

Gets named field as an integer


Gets header field key using index
Gets host from the URL
Gets last-modified field value
Gets port from the URL
Gets protocol from the URL
Gets the query string (only valid with GET
request)
Gets the reference portion of URL
Gets the current setting of the request
method (GET, POST or HEAD)

String getRequestProperty(String key)

Gets the current setting of a request

int getResponseCode()
String getResponseMessage()
String getURL()

property
Gets the response code (numeric value)
Gets the response message (text value)
Gets the entire URL

void setRequestMethod(String

Sets the request method (GET, POST or

method)

HEAD)
Sets a request property (header information)

void setRequestProperty(String key,


String value)

95

Ti liu tham kho them


[1]. Phuong Lan, Java tap 3, NXB Lao dong Xa hoi, 2006.
[2]. Nguyen Thi Bich Nga, Nen tang cong nghe J2Me & MIDP, NXB Giao thong Van
tai, 2006.
[3]. Nguyen Huu Mai, Tng quan ve J2ME, javavietnam.org, 2004.
[4]. Le Ngoc Quoc Khanh, Phat trien ung dung J2ME va J2ME Wireless Toolkit,
2004.
[5]. John W. Muchow, Core J2METM Technology & MIDP, Prentice Hall PTR
publisher, 2001.
[6]. Kim Topley, J2Me in a Nutshell, O'Reilly publisher, 2002.
[7]. Gwenael Le Bodic, Mobile Messaging Technologies and Service, John Wiley & Sons
publisher, 2003.

96

You might also like