View
272
Download
5
Embed Size (px)
Citation preview
交通大學資訊工程系蔡文能 第 1頁
Programming in Java
J2ME
汪益賢 蔡文能交通大學資訊工程學系
http://www.csie.nctu.edu.tw/~tsaiwn/java/
Java J2ME
交通大學資訊工程系 9-第 2頁
Outline
Java ME
Java ME Architecture
Java ME Specification
Learning J2ME CLDC 1.0 / MIDP 2.0 APIs
User Interface (lcdui)
Input/Output (RMS)
Networking
練習: Calculator or Monty Hall (手機版 )
Java J2ME
交通大學資訊工程系 9-第 3頁
Java ME (formerly J2ME)
Java Platform, Micro Edition Provides a robust, flexible environment for applications running
on a broad range of other embedded devicesMobile phones
PDAs
TV set-top boxes
Printers
Applications based on Java ME specifications are written once for a wide range of devices, yet exploit each device’s native capabilities. Java Mobile Games
Java J2ME
交通大學資訊工程系 9-第 4頁
Java ME Games
The most popular application Java-enabled devices grow rapidly. Java mobile games almost become the name of Java mobile
applications.
Nokia Snake ThinkNewIdea MJ16 JoyPark-Rich
Java J2ME
交通大學資訊工程系 9-第 5頁
Java J2ME
交通大學資訊工程系 9-第 6頁
3D Mobile Java Game
Java J2ME
交通大學資訊工程系 9-第 7頁
Pac-Manhattan
http://www.pacmanhattan.com/
Java J2ME
交通大學資訊工程系 9-第 8頁
Java ME Architecture
VMs
Configurations
Profiles
Optional Packages
Java J2ME
交通大學資訊工程系 9-第 9頁
Java Platform Editions
Java J2ME
交通大學資訊工程系 9-第 10頁
J2ME Architecture
Source: http://www.j2mer.idv.tw
多層次的架構 (一堆很容易搞混的名詞 ) 基本上,把 Profile, Configuration 都當作是 Package 來思考
Java J2ME
交通大學資訊工程系 9-第 11頁
VMs for Java ME
KVM (K Virtual Machine) for CLDC 16-bit or 32-bit processor with a clock speed of 16MHz or higher At least 160KB memory (128KB for VM and the CLDC library +
32KB for runtime heap space) Low power consumption (battery) Wireless with limited bandwidth
JVM (Java Virtual Machine) for CDC 32-bit processor More than 512KB memory + 128KB runtime heap space Unlimited power supply Fast network Target devices: smartphones, TV set-top boxes, and so on.
Java J2ME
交通大學資訊工程系 9-第 12頁
Configurations
Specifies the Java programming language features supported.
Specifies the Java virtual machine features supported.
Specifies the basic Java libraries and APIs supported.
Two configurations are defined: CLDC (Connected, Limited Device Configuration) CDC (Connected Device Configuration)
Java J2ME
交通大學資訊工程系 9-第 13頁
Profiles
Provide specific APIs for a certain device type. CLDC
MID Profile (Mobile Information Device Profile) Screen resolution: 96x54. Memory: 256KB for MIDP components,
128KB runtime space, 8KB persistent space.
PDA Profile Screen resolution: 160x160.
CDCFoundation Profile
No GUI
Personal Basis Profile Lightweight component
Personal Profile Full AWT and Applet (No Swing and Java 2D)
Java J2ME
交通大學資訊工程系 9-第 14頁
Optional Packages
A set of technology-specific APIs that extends the functionality of a Java application environment. Ex:
Wireless Messaging API (WMA) For CLDC 1.0 / MIDP 2.0 Provides access to wireless communication resources like Short Message
Service (SMS).
Mobile Media API (MMAPI) For CLDC 1.0 / MIDP 1.0 Provides audio, video and other time-based multimedia support.
JDBC For CDC / FP 1.0
Java J2ME
交通大學資訊工程系 9-第 15頁
Focused Specifications in This Course
The CLDC Specification Currently version 1.1 (JSR 139) No Floating point in version 1.0 (CLDC 1.0 不支援實數 )
The MIDP Specification Currently version 2.0 (JSR 118)
Note that JSR (Java Specification Request) is the actual description of proposed and final specifications for a new Java API that is submitted to the JCP (Java Community Process). (註 : JSR 類似 RFC)
Java J2ME
交通大學資訊工程系 9-第 16頁
Relationship between CDC/CLDC and J2SE
J2SE CDC CLDC
Java J2ME
交通大學資訊工程系 9-第 17頁
The CLDC Specification
Java language and VM features
Security Classfile verification
Reduced APIs Core Java libraries (java.lang.*, java.util.*) IO Networking
Java J2ME
交通大學資訊工程系 9-第 18頁
Constraints on Java Language Specification
No floating point (float and double) But CLDC 1.1 support floating point
No finalization (Object.finalize())
Limited error handling
Java J2ME
交通大學資訊工程系 9-第 19頁
Constraints on KVM
No JNI
No user-defined class loader
No reflection
No thread groups and daemon threads
No weak references java.lang.ref.WeakReference
Java J2ME
交通大學資訊工程系 9-第 20頁
Classfile Verification
Java J2ME
交通大學資訊工程系 9-第 21頁
Sun Java Wireless Toolkit for CLDC Buffer Overflow Vulnerabilities
http://www.vupen.com/english/advisories/2008/3439
Two vulnerabilities have been identified in Sun Java Wireless Toolkit (WTK) for CLDC (Connected Limited Device Configuration), which could be exploited by local attackers to gain elevated privileges. These issues are caused by unspecified buffer overflow errors which may allow a malicious program downloaded and executed in the WTK to execute arbitrary code with the privileges of the WTK process.
Affected: Sun Java Wireless Toolkit for CLDC version 2.5.2 and prior.
Solution: Upgrade to Sun Java Wireless Toolkit for CLDC version 2.5.2_01 :http://java.sun.com/products/sjwtoolkit/
Java J2ME
交通大學資訊工程系 9-第 22頁
The MIDP Specification
Application Life-cycle Management
User Interface
Event Handling
Record Management System (RMS)
Java J2ME
交通大學資訊工程系 9-第 23頁
MID Profile
MIDP 1.0 Packages: javax.microedition.lcdui.* javax.microedition.rms.* javax.microedition.midlet.* javax.microedition.io.*
MIDP 2.0 Added Packages: java.microedition.lcdui.game.* javax.microedition.media.* javax.microedition.media.control.* javax.microedition.pki.*
MIDP 2.0 supports socket connection that is not available in 1.0.
Java J2ME
交通大學資訊工程系 9-第 24頁
Constraints on Libraries
Only majority of the class libraries are included. ex:
No java.io.BufferedReader/Writer,java.io.FileReader/Writer/ InputStream/OutputStream
No java.awt.*
…
Java J2ME
交通大學資訊工程系 9-第 25頁
Hardware Consideration
The screen size is small.
Different mobile devices have different constraints. Different screen size. Different Input Method
No mouse
ITU keyboard (0~9, *, #, 上下左右 , …)
Touch pad
Different available memory
Java J2ME
交通大學資訊工程系 9-第 26頁
Learning Java ME (CLDC 1.0 / MIDP 2.0)
Development Environment Sun Java Wireless Toolkit (currently WTK 2.5.2)
http://java.sun.com/products/sjwtoolkit/
The Wireless Toolkit has been integrated into Java ME SDK 3.0.
Deployment
Your First MIDP Program class HelloMidlet extends MIDlet
Java J2ME
交通大學資訊工程系 9-第 27頁
Sun Java Wireless Toolkit
A toolbox for developing wireless applications that are based on CLDC and MIDP. Cell phones Mainstream personal digital assistants Other small mobile devices
The toolkit includes the Emulation environments Performance optimization and tuning features Documentation Examples
Java J2ME
交通大學資訊工程系 9-第 28頁
Deployment
There are two ways to deploy a MIDlet suite. Direct uses some direct connection between the device and the
development platformcommonly cable, infrared, or Bluetooth link
Over-The-Air provisioning (OTA) uses the device’s built-in browser to install a MIDlet suite from a remote server
Java J2ME
交通大學資訊工程系 9-第 29頁
JAD and JAR Files
The basic components of any MIDlet suite you will deliver Java Application Descriptor (JAD) file
the location and size of the JAR file
the configuration and profile requirements
attributes
Java Archive (JAR) file
在 product deployment 主題中討論
Java J2ME
交通大學資訊工程系 9-第 30頁
Your First MIDP Program: Hello MIDPimport javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class HelloMidlet extends MIDlet implements CommandListener
{
private Form mainForm;
public HelloMidlet() //no-argument constructor
{
mainForm = new Form("HelloMIDlet");
mainForm.append(new StringItem(null, "Hello, MIDP!"));
mainForm.addCommand(new Command("Exit", Command.EXIT, 0));
mainForm.setCommandListener(this);
}
protected void startApp()
{
Display.getDisplay(this).setCurrent(mainForm);
}
protected void pauseApp() {}
protected void destroyApp(boolean b) {}
public void commandAction(Command c, Displayable s)
{
notifyDestroyed(); //destroy the MIDlet
}
}
Java J2ME
交通大學資訊工程系 9-第 31頁
The Life Cycle of A MIDletWhen a MIDlet begins execution, the application management software (AMS) first calls the zero-argument constructor to create a new instance of the MIDlet. Then, the AMS places the MIDlet in the Paused state.
startApp() shift the MIDlet to the Active state allocate resources, such as record stores, network
connections, and UI components.
pauseApp() The MIDlet is not being terminated, but it should
release some resources.
destroyApp(boolean b) The MIDlet is terminated. Release any resources
acquired.
Java J2ME
交通大學資訊工程系 9-第 32頁
Controlling the MIDlet State
notifyPaused() – enter the Paused state.
notifyDestroyed() – inform the AMS that the MIDlet can now be considered Destroyed.
destroyApp(boolean b) If this boolean is true, the MIDlet will be in the Destroyed state when
destroyApp() returns. If this boolean is false, the MIDlet can request not to enter the Destroyed
state by throwing a MIDletStateChangeException.
Java J2ME
交通大學資訊工程系 9-第 33頁
Essential APIs
User Interface (lcdui) javax.microedition.lcdui High-Level API: Form, Alert/List/TextBox Low-Level API: Canvas/GameCanvas, Font/Graphics/Image Sound
Input/Output (RMS)
Networking HttpConnection StreamConnection SocketConnection
Java J2ME
交通大學資訊工程系 9-第 34頁
Essential APIs1. User Interface
The GUI classes included in the MIDP are not based on AWT/Swing. The AWT is designed for desktop computers and optimized for these devices,
such as window management. The AWT assumes certain user interaction models, such as mouse.
The MIDP UI consists of two APIs. High-Level API
Portability Gives you little control over its look and feel
Implemented by subclasses of the Screen class
Low-Level APIControl of graphic elements and input events
Implemented by the Canvas and Graphics classes
All the UI classes are placed in the javax.microedition.lcdui package.
Java J2ME
交通大學資訊工程系 9-第 35頁
javax.microedition.lcdui Package
Java J2ME
交通大學資訊工程系 9-第 36頁
The MIDP GUI Programming Model
The Display class is the display manager Instantiated for each active MIDlet Provides information about the device’s display capabilities.
Only one screen can be visible at a time, and the user can traverse only through the items on that screen. A screen is made visible by calling the Display.setCurrent() method.
There are three types of screens: Screens that encapsulate a complex user interface component
Alert, List, or TextBox (High-level API)
Generic screens Form (High-level API)
Screens used within the context of the low-level APICanvas (Low-level API)
Java J2ME
交通大學資訊工程系 9-第 37頁
Example of High-Level API
GuiTest.java Screens that encapsulate a complex user interface component
TextBox
List
Alert Generic screens
Form
Java J2ME
交通大學資訊工程系 9-第 38頁
GuiTests: Main Menu (List)import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
public class GuiTests extends MIDlet implements CommandListener {
private List mainMenu;
private static final Command exitCommand = new Command("Exit", Command.STOP, 2); //priority:2
public GuiTests() {
mainMenu = new List("Test Components", Choice.IMPLICIT);
mainMenu.append("Test TextBox", null);
mainMenu.append("Test List", null);
mainMenu.append("Test Alert", null);
mainMenu.append("Test Form", null);
mainMenu.addCommand(exitCommand);
mainMenu.setCommandListener(this); //見下一頁 mainMenu.setTicker(new Ticker(“Test GUI Components”)); //跑馬燈 showMainMenu();
}
public void startApp() {}
public void pauseApp() {}
/*略 */
private void showMainMenu() {
Display.getDisplay(this).setCurrent(mainMenu);
currentMenu = "Main";
}
}
Java J2ME
交通大學資訊工程系 9-第 39頁
GuiTests: TextBoxpublic class GuiTests extends MIDlet implements CommandListener {
private TextBox textBoxf = new TextBox("Enter Some Text:", "", 10, TextField.ANY);
private static final Command backCommand = new Command("Back", Command.BACK, 0); //priority:0
private String currentMenu;
public GuiTests() {
textBox.addCommand(backCommand);
textBox.setCommandListener(this);
textBox.setTicker(new Ticker("Testing TextBox")); //跑馬燈 }
private void showTextBox() {
textBox.setString("");
Display.getDisplay(this).setCurrent(textBox);
currentMenu = "input";
}
public void commandAction(Command c, Displayable d) {
List down = (List)Display.getDisplay(this).getCurrent();
switch(down.getSelectedIndex()) {
case 0: showTextBox(); break;
case 1: showList(); break;
case 2: showAlert(); break;
case 3: showForm(); break;
}
}
}
Java J2ME
交通大學資訊工程系 9-第 40頁
GuiTests: Listpublic class GuiTests extends MIDlet implements CommandListener {
private List list = new List("Choose Items", Choice.MULTIPLE);
private static final Command backCommand = new Command("Back", Command.BACK, 0); //priority:0
public GuiTests() {
list.addCommand(backCommand);
list.setCommandListener(this);
list.setTicker(new Ticker("Testing List"));
list.append("Item 1", null);
list.append("Item 2", null);
list.append("Item 3", null);
}
private void showList() {
Display.getDisplay(this).setCurrent(list);
currentMenu = "list";
}
public void commandAction(Command c, Displayable d) {
List down = (List)Display.getDisplay(this).getCurrent();
switch(down.getSelectedIndex()) {
case 0: showTextBox(); break;
case 1: showList(); break;
case 2: showAlert(); break;
case 3: showForm(); break;
}
}
}
Java J2ME
交通大學資訊工程系 9-第 41頁
GuiTests: Alertpublic class GuiTests extends MIDlet implements CommandListener {
private Alert soundAlert = new Alert("sound Alert");
private void showAlert() {
soundAlert.setType(AlertType.ERROR);
soundAlert.setString("** ERROR **");
Display.getDisplay(this).setCurrent(soundAlert); //Play Sound
}
}
Java J2ME
交通大學資訊工程系 9-第 42頁
GuiTests: Form (1/2)public class GuiTests extends MIDlet implements CommandListener {
private Form form = new Form("Form for Stuff");
private Gauge gauge = new Gauge("Progress Bar", false, 20, 9);
private DateField date = new DateField("Today's date: ", DateField.DATE);
private TextField textfield = new TextField("TextField Label", "abc", 12, 0);
private ChoiceGroup choice = new ChoiceGroup("choice", Choice.EXCLUSIVE,
new String[]{"choice 1", "choice 2"}, null);
private static final Command backCommand = new Command("Back", Command.BACK, 0); //priority:0
private static final Command mainMenuCommand = new Command("Main", Command.SCREEN, 1);
private static final Command exitCommand = new Command("Exit", Command.STOP, 2); //priority:2
private String currentMenu;
public GuiTests() {
form.append(new Spacer(2, 2));
form.append(new StringItem("label", "text"));
form.append(choice);
form.append(gauge);
form.append(textfield);
form.append(date);
form.addCommand(backCommand);
form.addCommand(mainMenuCommand);
form.addCommand(exitCommand);
form.setCommandListener(this);
}
//接下頁
Java J2ME
交通大學資訊工程系 9-第 43頁
//接上頁 private void showForm() {
Display.getDisplay(this).setCurrent(form);
java.util.Date now = new java.util.Date();
date.setDate(now);
currentMenu = "form";
}
public void commandAction(Command c, Displayable d) {
String label = c.getLabel();
if(label.equals("Exit")) {
try { destroyApp(true); }
catch(Exception e) {}
} else if(label.equals("Back")) {
if(currentMenu.equals("form")) {
int index = choice.getSelectedIndex();
mainMenu.setTitle("Form choice: " + index + " text:" + textfield.getString());
}
showMainMenu();
} else if(label.equals("Main")) {
showMainMenu();
} else {/*略 */}
}
}
GuiTests: Form (2/2)
Java J2ME
交通大學資訊工程系 9-第 44頁
Low-level APIs
Canvas Not component and container architecture It is really a canvas.
GameCanvas Add double buffering support. MIDP 2.0
Graphics
Font
Image
Java J2ME
交通大學資訊工程系 9-第 45頁
Using Graphics
The Graphics object is obtained in the paint() method of the Canvas class.
The Graphics class is similar to that of AWT, but with limited capabilities. Two basic kinds of drawing
Primitive graphics (shapes and text)
PNG Images (opaque, transparent, and translucent)
Provides a drawing contextThe current drawing area
The current drawing color
The Coordinate System
The Two Forms of the Canvas’s repaint() Method public void repaint()
public void repaint(int x, int y, int width, int height)
Canvas
x
y
(0,0)
(width-1, height-1)
Java J2ME
交通大學資訊工程系 9-第 46頁
Painting Shapes and Text
The Graphics class can draw the following kinds of shapes: Lines: drawLine() Triangle: fillTriangle() MIDP 2.0 Rectangles: drawRect(), fillRect() Round-edged rectangles:
drawRoundRect(), fillRoundRect() Arcs: drawArc(), fillArc() Text:
drawChar(), drawChars(), drawString(), drawSubstring()
Java J2ME
交通大學資訊工程系 9-第 47頁
Using Fonts
static Font getFont(int face, int style, int size); Face: FACE_SYSTEM, FACE_MONOSPACE, or FACE_PROPORTIONAL Style: STYLE_PLAIN or a combination of STYLE_BOLD, STYLE_ITALIC, and
STYLE_UNDERLINED Size: SIZE_SMALL, SIZE_MEDIUM, or SIZE_LARGE
Get font information:
Font font1 = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_ITALIC | Font.STYLE_BOLD, Font.SIZE_LARGE);Font font2 = Font.getFont(Font.FACE_MONOSPACE, Font.STYLE_UNDERLINED, Font.SIZE_SMALL);Font font3 = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_MEDIUM);protected void paint(Graphics g){ g.setFont(font1); g.drawString("Proportional", 10, 10, anchor); g.setFont(font2); g.drawString("Monospace", 10, 35, anchor); g.setFont(font3); g.drawString("Default Font", 10, 60, anchor);}
Enjoy J2ME getHeight()
stringWidth()
getBaseLinePosition()
Java J2ME
交通大學資訊工程系 9-第 48頁
Anchor
The drawing of text and images is based on “anchor points.” Anchor points are used to minimize the amount of computation required when placing text.
void drawString(String text, int x, int y, int anchor);
boolean drawImage(Image img, int x, int y, int anchor);
Anchor value (bit mask)Horizontal: LEFT, HCENTER, RIGHT
Vertical: TOP, VCENTER, BASELINE, BOTTOM
EX: Graphics.LEFT | Graphics.TOP
LEFT HCENTER RIGHT
TOP
VCENTER
BASELINE
BOTTOM
Java J2ME
交通大學資訊工程系 9-第 49頁
Using Images
Loading Images
Displaying Images
Performing Animation
Double Buffering
Java J2ME
交通大學資訊工程系 9-第 50頁
Loading ImagesUsing the Image.createImage() static methods It is easy to get an Image object if image data is in PNG format.
Image Types: Immutable images: cannot obtain Graphics object from them
createImage(String pngFileName)createImage(Image source, int x, int y, int w, int h, int transform)createImage(InputStream stream)createImage(Image source)createImage(byte[] data, int imageOffset, int imageLength)createRGBImage(int[] rgb, int w, int h, boolean processAlpha)
Mutable images: can obtain Graphics object from themcreateImage(int w, int h)
Java J2ME
交通大學資訊工程系 9-第 51頁
Displaying Images
Draw normal sized images boolean drawImage(Image img, int x, int y, int
anchor)
Draw rotated, mirrored images createImage(srcImage, 0, 0, w, h, transform) MIDP 2.0
Transform constants are defined in Sprite class TRANS_NONE, TRANS_MIRROR TRANS_ROT90, TRANS_ROT180, TRANS_ROT270 TRANS_MIRROR_ROT90, TRANS_MIRROR_ROT180, TRANS_MIRROR_ROT270
Draw clipped images Use translate() and setClip() of Graphics to perform.
Draw scaled images No support!
Java J2ME
交通大學資訊工程系 9-第 52頁
Translation and ClippingTranslates the origin of the graphics context to the given point.translate(int x, int y)
Sets the current clip to the specified rectangle. Rendering operations have no effect outside of the clipping area. setClip(int x, int y, int w, int h)
Canvas
x
y
(-a,-b)
(width-a-1, height-b-1)
(0,0)
After call g.translate(a, b)and g.setClip(0, 0, w, h)
Canvas
w
h
Java J2ME
交通大學資訊工程系 9-第 53頁
Performing Animation
Creating the Animation Loop Every program needs an animation loop to perform animation by
drawing at regular intervals. This loop should be in its own thread and never be in the paint() method.
duke0.png, duke1.png, … , duke9.png
Java J2ME
交通大學資訊工程系 9-第 54頁
Double Buffering
MIDP 1.0 Do it by yourself.
if(offImage == null)
{
offImage = Image.createImage(getWidth(), getHeight());
offG = offImage.getGraphics();
}
//performing painting
g.drawImage(offImage, 0, 0, Graphics.TOP | Graphics.LEFT);
MIDP 2.0 The GameCanvas class do it for you.
flushGraphics();
flushGraphics(int x, int y, int w, int h);
Java J2ME
交通大學資訊工程系 9-第 55頁
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class AnimationMidlet extends MIDlet
{
private AnimationCanvas canvas;
public AnimationMidlet()
{
try { canvas = new AnimationCanvas(); } catch(Exception e) {}
}
public void startApp()
{
Display.getDisplay(this).setCurrent(canvas);
}
public void pauseApp()
{
}
public void destroyApp(boolean unconditional)
{
}
}
Animation Canvas (1/3)
Java J2ME
交通大學資訊工程系 9-第 56頁
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;
public class AnimationCanvas extends Canvas {
private int dukeIndex = 0;
private Image[] duke = new Image[10];
private Image[] dukeMirrored = new Image[10];
private Image offImage;
private Graphics offG;
public AnimationCanvas() throws Exception {
for(int i = 0; i < duke.length; i++) {
duke[i] = Image.createImage("/res/duke" + i + ".png"); //immutable image
dukeMirrored[i] = Image.createImage(duke[i], 0, 0, duke[i].getWidth(), duke[i].getHeight(), Sprite.TRANS_ROT180); //製造旋轉後的圖
}
new MyThread().start(); // 產生一個 thread 來執行動畫 }
protected void paint(Graphics g) {
if(offImage == null) {
offImage = Image.createImage(this.getWidth(), this.getHeight()); //mutable image
offG = offImage.getGraphics();
}
//清除背景 offG.setColor(255, 255, 255);
offG.fillRect(0, 0, this.getWidth(), this.getHeight());
//接下頁
Animation Canvas (2/3)
Java J2ME
交通大學資訊工程系 9-第 57頁
Animation Canvas (3/3) //接上頁 offG.drawImage(duke[dukeIndex], 0, 0, Graphics.TOP | Graphics.LEFT);
offG.drawImage(dukeMirrored[dukeIndex], 0, 70, Graphics.TOP | Graphics.LEFT);
drawClippedDuke(offG, 60, 0); //繪製切割過的圖 g.drawImage(offImage, 0, 0, Graphics.TOP | Graphics.LEFT);
}
private void drawClippedDuke(Graphics g, int x, int y) {
g.setClip(x, y, duke[dukeIndex].getWidth()/2, duke[dukeIndex].getHeight()); //設定 clipper
g.drawImage(duke[dukeIndex], x, y, Graphics.TOP | Graphics.LEFT);
g.setClip(0, 0, this.getWidth(), this.getHeight()); //恢復 }
class MyThread extends Thread {
public void run() {
while(true) {
dukeIndex = (dukeIndex + 1) % duke.length;
repaint();
//等待 100 milliseconds,等於每秒更新 10次 try { Thread.sleep(100); }
catch(Exception e) {}
}
}
}
}
Java J2ME
交通大學資訊工程系 9-第 58頁
Processing Input Events
The Canvas class defines the following ITU Key codes: KEY_NUM{0-9} KEY_STAR (*) KEY_POUND (#) UP, DOWN, LEFT, RIGHT (logic key event) GAME_{A-D} (logic key event)
Override the following method to process key events: For keyboard:
keyPressed(), keyRepeated(), keyReleased()
Use getGameAction() to get logic key event
For touch pad:pointerPressed(), pointerDragged(), pointerReleased()
Java J2ME
交通大學資訊工程系 9-第 59頁
Example: Key Events (1/2)public class AnimationCanvas extends Canvas {
private int x = 30, y = 60;
private int code = 0;
private int action = 0;
private long interval = 100L;
private boolean bAnimation = true;
protected void paint(Graphics g)
{
if(offImage == null)
{
offImage = Image.createImage(this.getWidth(), this.getHeight());
offG = offImage.getGraphics();
}
offG.setColor(255, 255, 255);
offG.fillRect(0, 0, this.getWidth(), this.getHeight());
offG.setColor(0, 0, 0);
offG.drawImage(duke[dukeIndex], x, y, Graphics.TOP | Graphics.LEFT);
offG.drawImage(dukeMirrored[dukeIndex], x, y + 70, Graphics.TOP | Graphics.LEFT);
drawClippedDuke(offG, x + 60, y);
offG.drawString("code = " + code + " action = " + action + " interval = " + interval, 0, 0, Graphics.TOP | Graphics.LEFT);
g.drawImage(offImage, 0, 0, Graphics.TOP | Graphics.LEFT);
}
//接下頁
Java J2ME
交通大學資訊工程系 9-第 60頁
Example: Key Events (2/2) class MyThread extends Thread {
public void run() {
while(true) {
if(bAnimation) { dukeIndex = (dukeIndex + 1) % duke.length; repaint(); }
try { Thread.sleep(interval); } catch(Exception e) {}
}
}
}
protected void keyPressed(int keyCode) {
code = keyCode;
action = getGameAction(keyCode);
switch(action) {
case UP: y -= 5; break;
case DOWN: y += 5; break;
case LEFT: x -= 5; break;
case RIGHT: x += 5; break;
}
switch(code) {
case KEY_NUM0: case KEY_NUM1: case KEY_NUM2:
case KEY_NUM3: case KEY_NUM4: case KEY_NUM5:
case KEY_NUM6: case KEY_NUM7: case KEY_NUM8:
case KEY_NUM9: interval = (keyCode - KEY_NUM0 + 1) * 50; break;
case KEY_STAR: bAnimation = !bAnimation; break;
}
}
}
Java J2ME
交通大學資訊工程系 9-第 61頁
Playing Sound
MIDP 1.0 does not specifies any relative APIs! Use vendor specified APIs to play sound. Use alert sound defined in AlertType class.
INFO, WARNING, ERROR, ALARM, CONFIRMATION
Ex: AlertType.INFO.playSound(Display display)
MIDP 2.0 Use javax.microedition.media.Player to play sound.
Wave
MIDI
Java J2ME
交通大學資訊工程系 9-第 62頁
Example: Sound Playerimport javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import java.io.*;
public class SoundMidlet extends MIDlet {
public SoundMidlet() {
try { //MIDP 2.0
Player player;
InputStream is = getClass().getResourceAsStream("/res/start.wav");
player = Manager.createPlayer(is, "audio/X-wav");
player.prefetch(); // 把聲音資料預先讀到 buffer 中,這樣開始播放時不會 delay
//player.setLoopCount(-1); //一直重複播放 player.start();
Thread.sleep(3000);
} catch(Exception e) {}
}
public void startApp() {
Display.getDisplay(this).setCurrent(canvas);
//MIDP 1.0
AlertType.INFO.playSound(Display.getDisplay(this));
}
}
Java J2ME
交通大學資訊工程系 9-第 63頁
Guidelines for Programming UI for MID Devices
Make the MIDlets’ user interface simple and easy to use.
Use the high-level API so your MIDlets are portable across handheld devices.
If your application requires you to use the low-level API, keep to the platform-independent part of the low-level API. This means your MIDlets should not assume any other keys than defined in the the Canvas class.
MIDlets should not depend on any specific screen size; they should query the size of the display and adjust accordingly.
Entering data through a handheld device can be tedious. If possible, provide a list of choices that the user can select from.
Java J2ME
交通大學資訊工程系 9-第 64頁
Essential APIs 2. Input/Output in MIDP
Review IO classes in Java SE Byte streams are used to read and write binary data such as
images and sounds. Character streams can handle any 16-bit characters in the
Unicode character set.
However, neither CLDC nor MIDP provides APIs for access to file systems on mobile devices or external memory cards. Not all MIDP devices have file systems, and the creators of those that do may not want to expose them to
applications.
Java J2ME
交通大學資訊工程系 9-第 65頁
Character Stream Family in MIDP
Java J2ME
交通大學資訊工程系 9-第 66頁
Byte Stream Family in MIDP
System.in
System.outSystem.err
Java J2ME
交通大學資訊工程系 9-第 67頁
Alternatives to File IO
The alternative to FileInputStream getClass().getResourceAsStream(file) returns an InputStream instance.
Example:
InputStream inputStream = getClass().getResourceAsStream("myPicture.jpg");
How about FileOutputStream? MIDP Record Management System (RMS)
Java J2ME
交通大學資訊工程系 9-第 68頁
MIDP RMS
Record Management System (RMS) is a persistent storage for MIDlets. In Java SE, they are JDBC and Object Serialization APIs.
RMS consists of a collection of records. Data written into those records will remain persistent after the
MIDlet exits. When you invoke the MIDlet again, it can retrieve data from the
persistent record store.
RMS APIs provides the following functionality: Manipulate (add and remove) records within a record store. Share records in the same application. MIDP 2.0 allows you to share records in different applications.
Java J2ME
交通大學資訊工程系 9-第 69頁
Using RMS (1/2)
Package: javax.microedition.rms
Usages: Open a Record Store
RecordStore db = RecordStore.openRecordStore("name", true); the name is case sensitive, and cannot be more than 32 characters long. true means that create the record store if not exist.
Create a New Record (ID is started from 1)byte[] data = textfield.getString().getBytes();
int id = db.getNextRecordID(); // 取得新增資料時,會被指定的 ID
db.addRecord(data, 0, data.length); //新增資料, ID 是 db 指定的
Java J2ME
交通大學資訊工程系 9-第 70頁
Using RMS (2/2)
Read Data from the Record Storebyte[] data = db.getRecord(1); // 取得 ID = 1 的資料if(data != null)
{
textfield.setString(new String(data));
}
Delete a Record from the Record StroeUse record ID to deleted the record
db.deleteRecord(1); // 刪除 ID = 1 的資料
Java J2ME
交通大學資訊工程系 9-第 71頁
Example: RMSimport javax.microedition.rms.*;
public class RmsTests extends MIDlet implements CommandListener {
private RecordStore db;
public RmsTests() {
try {
db = RecordStore.openRecordStore("mydb", true);
System.out.println("SizeAvailable = " + db.getSizeAvailable());
System.out.println("Size = " + db.getSize());
System.out.println("Num of Records " + db.getNumRecords());
System.out.println("Next Record ID " + db.getNextRecordID());
if(db.getNumRecords() == 1) {
byte[] data = db.getRecord(1);
if(data != null) textfield.setString(new String(data));
}
} catch(Exception e) {}
}
public void destroyApp(boolean unconditional) {
byte[] data = this.textfield.getString().getBytes();
try {
if(db.getNumRecords() == 0) db.addRecord(data, 0, data.length);
else db.setRecord(1, data, 0, data.length);
} catch(Exception e) {}
}
}
First time output:SizeAvailable = 996689Size = 48Num of Records 0Next Record ID 1
Second time output:SizeAvailable = 996737Size = 80Num of Records 1Next Record ID 2
Java J2ME
交通大學資訊工程系 9-第 72頁
Essential APIs 3. Network
Package: javax.microedition.io
MIDP 1.0 HttpConnection StreamConnection
MIDP 2.0 HttpsConnection SocketConnection
Use Connector to open connectionc = (StreamConnection)Connector.open(“http://localhost/index.html”);
c = (SocketConnection)Connector.open("socket://localhost:4444");
Java J2ME
交通大學資訊工程系 9-第 73頁
Example: URL Readerimport javax.microedition.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import java.io.*;
public class HttpMidlet extends MIDlet {
private TextBox t;
public HttpMidlet() {
try {
String url = "http://java.sun.com:80/j2se/1.5.0/docs/api/java/net/URL.html";
StreamConnection c = null;
InputStream s = null;
StringBuffer b = new StringBuffer();
try {
c = (StreamConnection)Connector.open(url);
s = c.openInputStream();
int ch;
while((ch = s.read()) != -1) b.append((char)ch);
t = new TextBox("hello....", b.toString().substring(0, 1024), 1024, 0);
} finally {
if(s != null) s.close();
if(c != null) c.close();
}
} catch(Exception e) {}
}
public void startApp() { Display.getDisplay(this).setCurrent(t); }
}
Java J2ME
交通大學資訊工程系 9-第 74頁
Example: Echo Client MIDletimport javax.microedition.midlet.*;
import javax.microedition.io.*;
import java.io.*;
public class EchoClientMidlet extends MIDlet {
public EchoClientMidlet() {
try {
SocketConnection sc = (SocketConnection)Connector.open("socket://localhost:4444");
sc.setSocketOption(SocketConnection.LINGER, 5);
InputStream is = sc.openInputStream();
OutputStream os = sc.openOutputStream();
os.write("hello\n".getBytes());
int ch = 0;
while(ch != -1) System.out.print((char)is.read());
is.close();
os.close();
sc.close();
} catch(Exception e) {}
}
public void startApp() {}
public void pauseApp() {}
public void destroyApp(boolean unconditional) {}
}
Output:hello
Java J2ME
交通大學資訊工程系 9-第 75頁
練習: Monty Hall
1. 使用 MIDlet
2. 可選 3 ~6 個門3. 按鍵 1~6表示要打開門的編號4. 某個門有寶藏,找到時,獲得獎金,且全部的門都要打開 (贏 )
5. 某個門裡面是炸彈,打開時立刻結束遊戲 (輸 )
6. 獎金:門的數量 *100。第一次開門就找到寶藏,可以全拿。每多開一次門,獎金就會減半。看到提示炸彈訊息時,獎金也會減半。獎金可以累計,但不能低於 0
7. (進階 +10)必須防止畫面閃爍8. (進階 +10)顯示動畫9. (進階 +10)播放音效
Java J2ME
交通大學資訊工程系 9-第 76頁
練習: Calculator
1. 使用 MIDlet
2. 提供整數的 "加法、減法、乘法、除法 "。輸入數值最多 8位數3. 加減乘除都是立即運算,不需要管四則運算4. 運算過程若發生錯誤,要顯示錯誤訊息。如 overflow 、除數為
0、輸入過大的數等等5. 按鍵對應: 0~9, # 清除 , 上下左右對應到 +,-,*,/
6. (進階 +10) 支援 M+, M-, Mr, Mc 的功能7. (進階 +10)支援小數運算8. (進階 +10)* 鍵連按切換 +, -, *, /
Java J2ME
交通大學資訊工程系 9-第 77頁
Introduction to Java Programming
謝謝捧場http://www.csie.nctu.edu.tw/~tsaiwn/java/
蔡文能