Download MIDlet - GENTS.it

Document related concepts
no text concepts found
Transcript
Developing Wireless
Applications Using Java™
Technology – Day 2
Bill Day
[email protected]
www.billday.com
Review: Day One
l
l
l
l
l
l
l
l
l
Wireless 101
Java™ 2 Platform and J2ME™ Platform
J2ME Applications in WAP and i-mode
Networks
Connected Device Configuration
and PersonalJava™ Technologies
Related Technologies
J2ME CLDC Introduction
Implementing the CLDC with the
K Virtual Machine
J2ME MIDP Introduction
Availability and Resources
1
Q&A from Day 1
Day Two Agenda
l
l
l
l
l
l
l
l
l
MIDP Review and Runtime Environment
MIDP Application Life Cycle
MIDP Development Tools
MIDP User Interface: High Level APIs
MIDP User Interface: Low Level APIs
MIDP Persistent Storage APIs
MIDP Networking APIs
Advanced Topics: Wireless Security, XML
Access from MIDlets, Utility APIs,
Comprehensive Example, and MIDP for
PalmOS and Motorola iDEN Devices
Summary
2
MIDP Review and Runtime
Environment
Mobile Information Device
Profile
l
l
l
l
The first J2ME profile
Addressed in JSR-0037
Targets devices implementing CLDC
Profile addresses:
u Display
toolkit, user input methods
data storage
u Messaging and networking over wireless
network connection
u Sun provides Reference Implementation
u FCS in September 2000
u Persistent
3
J2ME MIDP 1.0 Expert Group
(MIDPEG)
u America
Online
u Ericsson
u Fujitsu
u J-Phone
u Mitsubishi
u NEC
u NTT
DoCoMo
u RIM
u Sharp
u Sony
u Symbian
DDI
Espial Group
Hitachi
Matsushita
Motorola
Nokia
Palm
Samsung
Siemens
Sun Microsystems
Telcordia
Mobile Information Device
characteristics
Minimum Mobile Information Device (MID)
characteristics
u Display
n
u
96x54 screen size, 1-bit depth, aspect ratio
approx. 1:1
Device input:
n
One or two handed keyboard, optional touch
screen
uMemory:
n
n
n
128kb non-volatile memory for MIDP components
8kb non-volatile memory for persistent data.
32 kb volatile memory for java runtime (heap, etc)
uNetworking:
n
Two-way, wireless, possibly intermittent, limited
bandwidth
4
MIDP Scope
l
l
l
Define the architecture and the
associated APIs to enable an open
application development environment
for Mobile Information Devices(MID)
Simplicity, rather than completeness a
main goal
What is NOT in MIDP Scope
How an application actually gets on the
device
u End-to-end security model
u System or OEM specific application needs
u Any particular implementation
u
MIDP Architecture
5
Application Management
Software
l
Application Management Software
assumed to be present on the
MIDs. It has the following
properties:
u Device
Specific
u Install, interact with, and Remove
MIDlet(s)
For example: Loading via wireless
network from a web server
n Be able to upgrade MIDlet(s)
n
MIDP assumptions on MIDs
l
MIDP was developed with the following
assumption on MID’s System software
uA
minimal kernel to manage hardware with
at least one schedulable entity to run the
Java Virtual Machine (JVM)
u A mechanism to read and write from nonvolatile memory
u A minimal capability to write to a bitmapped graphics display
u Read and write access to the device's
wireless networking
u A mechanism to provide a time base for
use in time stamping the records written to
persistent storage
6
MIDP Class Libraries
l
MIDP defines the following set of class
libraries that map to the aforementioned
assumptions.
u Application
n
u User
n
Lifecycle Package
javax.microedition.midlet
Interface Package
javax.microedition.lcdui
u Persistence
n
javax.microedition.rms
u Networking
n
Package
javax.microedition.io
u Language
n
Package
and Utility Packages
java.lang and java.util
MIDlet (MIDP Application)
• A MIDP application is called a MIDlet
• MIDlets:
– Have a well-defined lifecycle
– Provide descriptive information about themselves
– Extend
javax.microedition.midlet.MIDlet
• Permanent MIDlets
– Reside, at least in part, in nonvolatile memory
such as ROM or EEPROM
– Can be downloaded and written into persistent
storage on the MID
– A user may run a permanent MIDlet repeatedly
without downloading the MIDlet again
7
MIDP User Interaction
• Designed with consumer devices in mind
• Defined in javax.microedition.lcdui package
• High-level, portable API
– Screen and widget oriented
– Applications which use this API should work on all devices
– No direct access to device features (colors, sizes, input)
– Much simpler and less powerful than AWT
• Low-level API
– Drawing primitives
– Key events
– Developers may compromise portability for better user
experience
MIDP Persistence
• Simple record-oriented database (RMS)
• Device-independent API
• Records are arrays of bytes
• Records live in record stores
• Record stores are shared within MIDlet suite
• Support for enumeration, sorting, and filtering
• Atomic update for single records
• Defined in javax.microedition.rms
package
8
MIDP IO
l
Implements the CLDC Generic
Connection framework defined in
javax.microedition.io package
l
– Requires support for opening
connections via the “http” URL
scheme (RFC 2616)
Adds HttpConnection
MIDP Utilities
• Helpful classes and interfaces
• Specified in CLDC in java.util package
– Calendar, Date, TimeZone
– Enumeration, Hashtable, Vector
– Random
– Stack
– Timer,TimerTask
9
MIDP Internationalization
ISO Latin 1 character encoding must be
supported (ISO8859-1)
Locale of device defined in
microedition.locale system property
Localization provided by implementation
Application providers provide separate
JAR files per locale with locale-specific
resources
l
l
l
l
How To Get the MIDP
Reference Implementation
l
Available from:
http://java.sun.com/products/midp
– emulator binary (Win32)
– classes and source for libraries (Java
l
& native)
– documentation (PDF and javadoc)
– sample code
Requires acceptance of the Sun
Community Source License (SCSL) another license is needed for
development, too.
10
MIDP Status
l
l
MIDP 1.0 spec., RI and TCK available
MIDP for Palm OS in beta
– Based on MIDP 1.0 specification
• MIDP RI 1.0.2 in development
– Based on MIDP 1.0 specification
– To be available later this year
• J2ME Wireless Toolkit 1.0.3 in beta
– Based on CLDC RI 1.0.2 and MIDP RI 1.0.2
What’s next with MIDP?
•
MIDP NG JSR submitted
– http://java.sun.com/jcp/jsr/jsr_118_midpng.
html
– Final spec, RI and TCK should be available
within 6 to 9 months (H1 2002)
– Commercially available on real devices
later in 2002
11
MIDP Application Life Cycle
MIDlet Architecture and
Life Cycle
New() from a Source
Application Management Software retrieves MIDlet
1. Retrieval
DestroyApp()
2. Installation
Paused
3. Launching
StartApp()
Destroyed
3a. MIDlet Instance creation – Paused
3b. MIDlet initialization – Active
3c. MIDlet termination – Destroyed
PauseApp()
Active
DestroyApp()
4. Version Management
Application Management Software installs MIDlet onto device.
Security policy verified
Application Management Software upgrades the
MIDlet to a new version, if one is available
12
MIDP Application Lifecycle
• The MIDlet Lifecycle:
– Retrieved from server to device
– Installed on device
– Run on device (paused, active, destroyed states)
– Upgraded with new version
– Removed by user
• Device-specific application management
software performs lifecycle operations
• MIDP defines mechanisms which support the
lifecycle operations
– Jar and Jad file formats, MIDlet descriptors,
javax.microedition.midlet package API
MIDP Application Lifecycle
Server
MIDlet
publish
retrieve
install
create
MIDlet
MIDlet
remove
Develop
Development
Environmaent
run
Device
13
MIDlet Lifecycle - Retrieval
• The MID retrieves the MIDlet from some
source.
• A medium might be identified (whether the
MID supports retrieval via a serial cable, Infra
Red Data Access (IRDA) port, or the wireless
network)
• A negotiation may occur between the MID
and the MIDlet source whereby information
on the MID’s capabilty, the size of the MIDlet
and the cost to download takes place
• A retrieval process occurs which reads the
MIDlet into the MID’s memory
MIDlet Lifecycle - Installation
l
l
l
The application management software
installs the MIDlet on the MID
The MIDP implementation may verify
that the MIDlet does not violate the
MID’s security policies.
A transformation of the MIDlet may take
place to convert the MIDlet from its
public format to a device specific format.
14
MIDlet Lifecycle - Launching
l
The user selects and launches the
MIDlet. At this point, the MIDlet enters
the VM and the lifecycle methods of the
MIDlet are invoked.
destroyApp()
startApp()
new()
Paused
destroyApp()
Active
Destroyed
pauseApp()
MIDlet Lifecycle - Version
Management
• A new version of the MIDlet may become
available after installation
• The application management software must
keep track of what MIDlets have been
installed and their version number
• Using this information the older version of the
MIDlet can be upgraded to a newer version
• MIDlet attributes, including version numbers
are contained either in the MIDlet’s descriptor
or in the manifest file that is included with the
MIDlet in its JAR file
15
MIDlet Lifecycle - Removal
l
l
The application management software
removes a previously installed MIDlet.
The application management software
deletes the installed image of the
MIDlet, and possibly related resources
such as records it has written to
persistent storage
MIDP Support for Application
Lifecycle
l
l
l
MIDlet jar file and manifest
MIDlet descriptor
Javax.microedition.midlet
package
16
MIDlet JAR File
• MIDlet class files and resources are deployed
in JAR files
• A JAR file may contain multiple MIDlets;
MIDlets within the same JAR file are known
as a MIDlet suite
• MIDlet suite JAR files use the standard JAR
format
• MIDP defines attributes that go into the JAR
file’s manifest
MIDlet Descriptor
•
•
•
•
•
•
•
Each MIDlet JAR file may be accompanied by an application
descriptor
Allows application management software to verify that the
MIDlet suite is suitable before downloading
Also provides configuration-specific attributes
Allows for packaging multiple MIDlets (MIDlet Suite)
MIDlet descriptors are stored in .jad files
The MIME type for .jad files must be
text/vnd.sun.j2me.app-descriptor
Configuring a Browser:
Description:
MIME Type:
Extension:
Application:
MIDP app descriptor
text/vnd.sun.j2me.app-descriptor
jad
d:\midp\bin\midp.exe -transient file://%1
17
MIDP Application Suite
Descriptor
MIDlet-Name: SunSamples
MIDlet-Version: 1.0
MIDlet-Vendor: Sun Microsystems, Inc.
MicroEdition-Profile: MIDP-1.0
MicroEdition-Configuration: CLDC-1.0
MIDlet-1: Sokoban,
/icons/Sokoban.gif,example.sokoban.Sokoban
MIDlet-2: Tickets, /icons/Auction.gif, TicketAuction
MIDlet-3: Colors, /icons/ColorChooser.gif, example.Color
MIDlet-4: Stock, /icons/Stock.gif,
example.stock.StockMIDlet
MIDlet-5: Tiles, /icons/Tiles.gif, example.tiles.Tiles
MIDlet-6: ManyBalls, /icons/ManyBalls.gif,
example.ManyBalls
MIDlet-7: Sampler, /icons/App.gif, Sampler
MIDlet-8: Properties, /icons/App.gif, example.PropExample
MIDlet-9: HttpTest, /icons/App.gif, example.HttpTest
MIDlet Descriptor attributes
Attribute Name
MIDlet-Name
JAD
File
Req.
Description
Name of the MIDlet suite.
MIDlet-Version
Req.
Version number of the MIDlet suite.
MIDlet-Vendor
Req.
Organization that provides the MIDlet suite.
MIDlet-Description
Opt.
Description of this MIDlet suite.
MIDlet-Info-URL
Opt.
URL for further information on the MIDlet suite.
MIDlet-Jar-URL
Req.
Name, icon, and class of the <n>th MIDlet in the
JAR file, separated by ",".
URL from which to download the JAR file.
MIDlet-Jar-Size
Req.
Number of bytes in the JAR file.
MIDlet-Data-Size
Opt.
Minimum number of bytes of persistent data
required by the MIDlet.
The required J2ME Profile.
MIDlet-<n>
MicroEdition-Profile
MicroEditionConfiguration
The required J2ME Configuration.
18
javax.microedition.midlet
Package
l
Provides the classes and interfaces
necessary to create a MIDlet and to
define interactions between MIDlets and
the application manager. This package
is comprised of the following
– javax.microedition.midlet.MIDlet:
subclass to implement to create a MIDlet
– javax.microedition.midlet.MIDletStateChangeExcepti
on
Class that signals that requested state change of MIDlet has
failed
Javax.microedition.midlet.MIDlet
• Abstract base class for all MIDlets
–
protected MIDlet()
no-argument constructor to create MIDlet
– protected abstract void startApp()
throws MIDletStateChangeException
Called when MIDlet starts (paused -> active state)
– protected abstract void pauseApp()
Called to pause MIDlet (active -> paused state)
– protected abstract void destroyApp(boolean
unconditional)throws MIDletStateChangeException
Called when MIDlet starts (paused -> active state)
– public final void notifyDestroyed()
Notifies application manager that the MIDlet has cleaned up and is done
– public final void notifyPaused()
Notifies application manager that the MIDlet has paused
– public final String getAppProperty(String key)
Called by MIDlet to get its properties
19
First MIDlet (MIDP
Application)
l
Here are the steps you ‘d follow to
create and execute your MIDlet
–
–
–
–
–
–
Write the Java code
Compile it
Preverify the class
Package it into a Jar file
Create the MIDlet Descriptor file
Run the MIDlet on the emulator
HelloMIDlet.java
import javax.microedition.midlet.*;
public class HelloMIDlet extends MIDlet {
public void startApp() {
System.out.println( “Hello J2ME Camp…” );
pauseApp();
}
public void pauseApp() {
System.out.println( “In pauseApp…” );
destroyApp( true );
}
public void destroyApp(boolean
unconditional) {
System.out.println( “In destroyApp…” );
} }
20
2. Compiling the Source
javac –g:none –bootclasspath c:\midpfcs\classes HelloMIDlet.java
3. Preverifying the class
c:\midp-fcs\bin\preverify -classpath
.;c:\midp-fcs\classes HelloMIDlet
21
4. Jar up the Preverified
Class
cd output
jar cf Hello.jar *.class
5. Create the MIDlet
Descriptor file Hello.jad
MIDlet-1:
FirstMIDlet,,HelloMIDlet
MIDlet-Description: Simple MIDlet
MIDlet-Jar-Size: 922
MIDlet-Jar-URL: FirstMIDlet.jar
MIDlet-Name: FirstMIDlet
MIDlet-Vendor: Sun Microsystems
MIDlet-Version: 1.0
22
6. Running the MIDlet
c:\midp-fcs\bin\midp -classpath
Hello.jar -descriptor Hello.jad
Command line arguments
-classpath <path>
directories and zip files to search
-descriptor <jad file>
MIDlet app descriptor file to use
-transient <url> <app_name>
run app_name from descriptor at url
-autotest <url> <app_name>
repeatedly run application
-verbose
enable classloading information
-debug
enable debugging info
-help show this message
23
MIDlet Runtime Variables
Option
Default Description
HTTP_PROXY
Null
CLASSPATH
Proxy server setting
User defined classes
ENCODING
Null
DOUBLE_BUFFERING
True
SCREEN_DEPTH
1 (b/w)
Specify character
encoding
Whether to use
double buffering
when writing to
display
2, 4, 8, for 4,16,256
colors
Demo: Create a simple MIDlet,
compile, preverify, package and
run it
24
MIDP Development Tools
kToolBar IDE in J2ME Wireless
Toolkit
l
l
l
l
Minimal development environment
that lets you perform application
development from a GUI tool
Use kToolBar to compile, build,
and execute a MIDlet with the
Emulator.
Need a Third-party tool for editing
source file.
See Appendix C, for step-by-step
instructions on using kToolBar for
MIDlet development
25
KtoolBar (in J2MEWTK)
Emulators in J2ME Wireless Toolkit
26
Emulators in J2MEWTK contd.
Forte for Java in J2ME
Wireless Toolkit
l
l
l
l
Forte for Java is a comprehensive
IDE for java
URL:
http://www.sun.com/forte/ffj/ce
User can edit, compile, build, and
execute a Java application with the
Emulator all from within the IDE
See Appendix C, for step-by-step
instructions
27
Forte for Java with the
J2ME Wireless Toolkit
Demo: Using J2ME Wireless Toolkit
28
Motorola SDK
l
l
l
Software Development Kit for Motorola
StarTec Family of Phones
Download URL: http://www.idendev.com
System Requirements
u Pentium-100
MHz Processor
u 64
MB RAM
u Windows NT Workstation (SP3) or Win 98
u Approximately 10 MB diiskspace
u JDKTM 1.2.2
Motorola SDK Contents
l
l
l
Bytecode Verifier
J2METM Emulators
Configuration Tool
uA
tool that allows you to create and modify
device profiles
29
Emulators in Motorola SDK
Motoi1000
Emulators (StarTac, IDEN)
30
Emulator Configuration Tool
Motorola SDK Environment
l
The following tools are available in
Motorola SDK to help application
development
u compileall.bat
// compile & Preverify
u runEmul.bat // Default Emulator
u runStarTac.bat // StarTac emulator
u runMotoiDEN.bat // iDEN emulator
u runMotoi1000 // Motoi1000 Emulator
31
Using MotoSDK
l
l
l
l
l
l
l
Copy HelloMIDlet.java to <sdk-installdir>\demo\midlets
compileAll HelloMIDlet.java
cd ..\..\scripts // directory contains
emulators
runEmul HelloMIDlet // default emulator
runStarTac HelloMIDlet // StarTac emulator
runMotoiDEN HelloMIDlet // iDEN emulator
runMotoi1000 HelloMIDlet // i1000 emulator
CodeWarrior 6.0 for Java
l
l
Can develop/debug/test MIDlets
using the familiar CodeWarrior IDE.
Test with Motorola Emulators
32
Whiteboard from Zucotto
l
From Zucotto Wireless
Other J2ME Tools
l
Borland's jBuilder 5.0 Personal/Mobilset
edition supports development for Nokia
MIDP powered phones. More info from:
http://www.borland.com/jbuilder
33
MIDP User Interface:
High Level APIs
UI Programming Issues for
Mobile Information Devices
l
l
l
l
l
MIDs are resource constrained
(memory, networking, etc )
Inputs, usually one handed, voice,
touch screen, etc. are common
Extremely constrained output devices
User Profile: Consumer product
users. App should be very
straightforward
User experience should be consistent
between the native and the Java
apps.
34
User Interface design
principles
l
Usable in all devices
u Majority
of wireless devices are one hand operated
l
Keep target devices in mind
u Small
screen (tens of pixels x tens of
pixels)
u Not all devices have a pointing
device
u Drastically varying button sets.
QWERTY to ITU-9 keypads
l
Think of end users:
u Consumer
products - not computers
UI: Design considerations
35
Two layers of UI APIs in
MIDP
l
High- level API for high portability
u Applications
should run on all devices
u Applications should be usable in all devices
u No direct access to device features
n
l
Colors, screen sizes, input devices
Low- level API for applications like
games
u Drawing
primitives
u Key events
u Developers may compromise portability for
better game - experience
High-level APIs
l
l
l
l
l
High-level APIs employ a high
level of abstraction for portability
Actual drawing to the MID’s display
is performed by the implementation
Apps. don’t define visual
appearance
Navigation, scrolling, and other
interaction encapsulated by the
implementation
App. can not access concrete input
devices like specific individual keys
36
Screen based design
l
l
l
l
Central abstraction for MIDP’s UI
is a Screen
Screen encapsulates devicespecific graphic rendering and user
input
Only one screen may be visible at
a time
Screen takes care of handling all
the events as the user navigates in
a screen
3 types of Screens
l
l
l
l
Generic Screens ( class Form )
applications can populate with text and
images, and related UI components
Screens that encapsulate a UI
component (Example: List, TextBox
classes)
Screens used in Low-level APIs(
Example: Subclass of Canvas class)
A screen is made visible by calling the
setCurrent() method of Display.
The class Display acts as the display
manager
37
Class Display
l
l
l
Represents the manager of the display
and the input devices of a system
Exactly one instance of a Display
object per MIDlet. App. can get that
reference by calling getDisplay()
method
setCurrent() method used for
setting the Current Displayable
(Canvas, and Screen are
Displayable types)
l
If current Displayable is visible,
application is considered to be in the
foreground
MIDP UI Class Hierarchy:
javax.microedition.lcdui
Displayabl
e
Canvas
0-n Command
Screen
Choice
TextBox
ChoiceGroup
List
DateField
1-n
Alert
Item
TextField
Gauge
Form
ImageItem
TextItem
38
UI and MIDlet Lifecycle
startApp()
l
method called for the first
screen if it has not already been called
u Application Management Software makes
Displayable visible when startApp() returns
u Can be called multiple times. So, no
Initialization should take place
u SetCurrent()
pauseApp()
l
u App
can resume with another screen, when
it is reactivated.
u New screen is set using setCurrent()
method
destroyApp()
l
u App
frees its resources including UI
components
Programming for MIDs: Key
points
l
l
l
l
l
l
l
Every byte counts
Don’t string String concats. Use
StringBuffer instead
Less Hashtable/Vectors
Reuse Buttons, and other resources
Use Code packer/obfuscator
Recycle objects
Keep track of memory
u Use
l
Runtime.getRuntime.get…()
Use any utility you may have to
optimize the heap size
39
HelloMIDlet.java with UI
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class HelloMIDlet extends MIDlet {
private Display display; // Display for
MIDlet
public HelloMIDlet() {
display = Display.getDisplay(this);
}
public void startApp() {
TextBox t = new TextBox("Hello MIDlet",
"Hello J2MECamp!", 256, 0);
display.setCurrent(t);
}
public void pauseApp() {
}
public void destroyApp(boolean
unconditional){}
}
Command
l
l
Objects that help in MIDlet event handling.
CommandListener attached to a command
does the actual work
l
Applied to a screen or Canvas with
addCommand()
Command class has 3 parameters
u Label: Shown to the user as hint
u CommandType: Meaning of the command
n Allows the MIDP implementation to
select these
n SCREEN, BACK, HELP, OK, CANCEL,
STOP
u Priority: Priority of one command over the
other in the same UI context
u commandAction( Command c, Screen s )
l
40
Command examples
l
If an implementation has 2 soft
buttons, the following set of code
will result as shown below
new Command( “Buy”, Command.Screen,
1);
new Command( “Info”, Command.Screen,
1);
new Command( “Back”, Command.Back,
1);
Pressing "options"
opens a menu
Command examples (Contd)
l
If another implementation had 3
soft buttons, the same code in the
previous slide will result in screens
as shown below
41
HelloMIDlet.java with Events
public class HelloMIDlet extends MIDlet implements
CommandListener {
private Command exitCommand; // The exit command
private Display display;
// Display for this
MIDlet
public HelloMIDlet() {
display = Display.getDisplay(this);
exitCommand = new Command("Exit",
Command.EXIT, 2);
}
public void startApp() {
TextBox t= new TextBox("Hello","Hello
Camp",256,0);
t.addCommand(exitCommand);
t.setCommandListener(this);
// CommandAction
code shown in the next slide
display.setCurrent(t);
}
HelloMIDlet.java (contd)
public void commandAction(Command c,
Displayable s){
if (c == exitCommand) {
destroyApp(false);
notifyDestroyed();
}
}
public void pauseApp() { }
public void DestroyApp( boolean conditional ) {
}
}
42
Demo of MIDlet with High level
UI APIs and Events
MIDP User Interface:
Low Level APIs
43
Low-level APIs
l
l
l
l
l
Low-level APIs, unlike the High-level
APIs provide very little abstraction
API set designed for applications that
need placement and control of graphic
elements
Provides access to low-level input
events
Apps using Low-level APIs can have full
control of what is drawn on the display
These applications are not guaranteed
to be portable
Canvas
l
l
l
Base class for writing applications using
Low-level APIs. Subclass of
Displayable
Application can mix and match Canvas
with a High level screen as needed
Provides developers with methods to
u Handle
game actions, key events, etc.
u Obtain device capabilities and keyboard
mapping
l
Like other subclass of Displayable,
allows applications to register a listener
for commands
44
Canvas class methods
l
paint() method is declared
abstract Applications must provide
implementation
l
l
l
l
Default implementation for other event
reporting methods are empty
Every key for which events are reported
is assigned a keyCode
Game Application should use game
actions
Applications can translate a keyCode to
a game action using
getGameAction( int keyCode )
Key Events
l
MIDP defines the following Keys
u KEY_NUM0,
KEY_NUM1, KEY_NUM2,
KEY_NUM3, KEY_NUM4, KEY_NUM5,
KEY_NUM6, KEY_NUM7, KEY_NUM8,
KEY_NUM9, KEY_STAR, KEY_POUND
l
l
Devices may notify applications about
other keys as well, but applications
relying on those are not portable
Abstract game events
u Actions
that the device can map either to 4way scrolling keys or to numeric keys
u UP, DOWN, RIGHT, LEFT, FIRE,
GAME_A, GAME_B, GAME_C, GAME_D,
etc.
45
Mapping game actions
Canvas Event Delivery
l
Canvas delivers the following methods
for event delivery. Called serially in the
order below:
u showNotify()
u hideNotify()
u keyPressed()
u keyRepeated()
u keyReleased()
u pointerPressed()
u pointerDragged()
u pointerReleased()
u paint()
u The
CommandListener's
commandAction()
46
Case Study: Low Level UI APIs
Tiles.java
public class Tiles extends MIDlet
Board b;
public Tiles() {
b = new Board(this);
}
public void startApp() {
{
Display.getDisplay(this).setCurrent(b);
}
public void pauseApp() { }
public void destroyApp( boolean unc ) { }
}
Board.java
public class Board extends Canvas implements
CommandListener {
MIDlet midlet;
Command exitCommand;
Font font;
// Character Position
int xPos, yPos;
// Chracter Height and Width in pixels
int charW, charH;
public Board(MIDlet midlet_) {
int i;
midlet = midlet_;
Display dpy = Display.getDisplay(midlet);
int letterWidth = 4;
font = Font.getFont(Font.FACE_SYSTEM,
Font.STYLE_PLAIN, Font.SIZE_MEDIUM);
charW = font.charWidth('M') + 7;
charH = font.getHeight() + 1;
// contd. On next slide
47
Board.java
// from previous slide
xPos = (getWidth() - ( letterWidth*charW) + 1) / 2;
yPos = 1;
exitCommand = new Command( "Exit", Command.SCREEN, 2
);
addCommand( exitCommand );
setCommandListener(this);
repaint();
}
public void commandAction( Command c, Displayable d )
{
// Exit if exit is pressed.
}
public void paint(Graphics g) {
g.setColor(0);
g.drawRect(4, 4, 4*charW + 2, 4*charH + 2);
}
// Continued on next slide…
Board.java
}
// from previous slide
public void keyPressed(int code) {
int game = getGameAction( code )
switch ( game ) {
case Canvas.UP:
System.out.println( "Canvas.UP" );
break;
case Canvas.DOWN:
System.out.println( "Canvas.DOWN" );
break;
case Canvas.LEFT:
System.out.println( "Canvas.LEFT" );
break;
case Canvas.RIGHT:
System.out.println( "Canvas.RIGHT" );
break;
default:
System.out.println( "default" );
// do a switch on code to capture the keyPressed events
}
// End of class Board.java
48
Demo of Low level APIs
MIDP Persistent
Storage APIs
49
MIDlet Persistence: Record
Management System
l
l
l
Persistence APIs allow Persistent
storage and retrieval of data
Modeled after simple Record
Oriented database
Called Record Management
System
RMS APIs
l
l
Package:
javax.microedition.rms
Lightweight record- oriented database
(RMS)
u Device
independent API
u Shared within MIDlet suite
u Support for enumeration, sorting and
filtering
l
Platform responsible for:
u Data
Integrity during reboots, battery
changes, etc.
u Storage in flash or other device memory
50
Records
l
l
l
Records are Array of Bytes
Each record has unique identifier
(integer value)
Following classes can be used to
pack/unpack different data types into
and out of Records
u DataInputStream
u DataOutputStream
u ByteArrayInputStream
u ByteArrayOutputStream
l
These methods are part of java.io
package in CLDC
RecordStore
l
l
l
l
l
l
l
l
Consists of a collection of records
Persistent across multiple invocations of a MIDlet
Created in platform-independent locations
Naming space controlled by MIDlet Suite
When a MIDlet suite is removed, the associated
RecordStore must be removed by the platform
MIDlet responsible for handling multiple threads
accessing a RecodStore
Time stamped with the last time it was modified
Maintains a version, that is incremented for each
operation that modifies RecordStore contents
u Useful in synchronization
51
Contents of
javax.microedition.rms
• RecordStore
– A collection of records
• RecordComparator
– Compares two records in an implementation
dependent manner to see if they match
• RecordEnumeration
– A birectional RecordStore enumerator
• RecordFilter
– Defines filter to specify matching criteria
• RecordListener
– Listener for Record changed/deleted/added
events
RecordStore Operations
• Open a record store, optionally create if it
doesn’t exist
– openRecordStore(name, create)
• Remove a record store, deleting all its
records
– DeleteRecordStore(name)
• Get the names of all record stores known to
the MIDlet suite
– listRecordStores()
52
Record Access
• Add a record to the record store
– addRecord(byte[] data, int offset,
int numBytes)
• Replace the contents of a record
– setRecord(int recordId, byte[]
newData, int offset, int numBytes)
• Delete a record
– deleteRecord(int recordId)
• Retrieve a record
– getRecord(int recordId)
– getRecord(int recordId, byte[]
buffer, int offset)
Enumerating Records
•
•
•
•
•
RecordStore has a method for enumerating records which
returns a RecordEnumeration object
– EnumerateRecords(RecordFilter rf,
RecordComparator rc, boolean keepUpdated)
RecordFilter is an interface with one method,
– boolean matches(byte[] candidate)
RecordComparator is an interface with one method,
– int compare(byte[] rec1, byte[] rec2)
The RecordEnumeration returns all records for which the filter
returns true, in the order defined by the RecordComparator.
The keepUpdated parameter to enumerateRecords tells
whether the enumeration has to keep track of inserts and
deletes that happen while the enumeration is open
53
Record Change Tracking
• Get the time the record store was modified
– getLastModified()
• Each insert, update, delete increments a
version counter
– GetVersion()
• Register a listener to be notified of insert,
delete, update events
– addRecordListener(RecordListene
r)
Case Study: RMS APIs
RMSGameScores.java
public class RMSGameScores extends MIDlet implements
RecordFilter, RecordComparator {
private RecordStore recordStore = null;
public static String playerNameFilter = null; // Filter
String
public RMSGameScores() {
try {
recordStore = RecordStore.openRecordStore(
"scores", true );
} catch( RecordStoreException rse ) { }
public void startApp() throws
MIDletStateChangeException {
RMSGameScores rmsgs = new RMSGameScores();
rmsgs.addScore( 100, "Alice" ); // Add more like this
RMSGameScores.playerNameFilter = "Farnsworth";
rmsgs.printScores(); // Print all scores & filter
scores
}
54
Case Study: RMS APIs
RMSGameScores.java
public void addScore( int score, String
playerName ) {
ByteArrayOutputStream baos = new
ByteArrayOutputStream();
DataOutputStream outputStream = new DataOutputStream(
baos);
try {
// Push the score, and name to the ByteArray
outputStream.writeInt(score);
outputStream.writeUTF( playerName );
}
catch ( IOException ioe ) { }
// Extract ByteArray from the DataOutputStream
byte[] b = baos.toByteArray();
try {
recordStore.addRecord( b, 0, b.length );
//Add more data
} catch ( RecordStoreException rse ) { }
}
Case Study: RMS APIs
RMSGameScores.java
public void printScores() {
// Print all scores
try {
RecordEnumeration re =
recordStore.enumerateRecords( null, this, true );
printScoresHelper( re );
// create enumeration object with RecordFilter set to
// this object
recordStore.enumerateRecords( this, this, true );
printScoresHelper( re );
} catch ( RecordStoreException rse )
{ }
}
55
Case Study: RMS APIs
RMSGameScores.java
public void printScoresHelper( RecordEnumeration re ) {
try {
while( re.hasNextElement() ) {
int id = re.nextRecordId();
ByteArrayInputStream bais = new ByteArrayInputStream(
recordStore.getRecord( id ) );
DataInputStream inputStream = new
DataInputStream(bais);
try {
int score = inputStream.readInt( );
String playerName = inputStream.readUTF();
System.out.println( playerName + " = " + score );
} catch ( EOFException eofe ) { }
} } catch ( RecordStoreException rse ) { }
catch ( IOException ie ) { }
}
Case Study: RMS APIs
RMSGameScores.java
// Part of the RecordFilter interface
public boolean matches(byte[] candidate) throws
IllegalArgumentException {
// If no filter set, nothing can match it.
if ( this.playerNameFilter == null ) { return false; }
ByteArrayInputStream bais =
new ByteArrayInputStream( candidate );
DataInputStream inputStream = new DataInputStream( bais
);
String name = null;
try {
int score = inputStream.readInt();
name = inputStream.readUTF();
} catch ( EOFException eofe ) { }
catch ( IOException eofe ) { }
return( this.playerNameFilter.equals( name ) );
}
56
Case Study: RMS APIs
RMSGameScores.java
public int compare(byte[] rec1, byte[] rec2) {
// Construct DataInputStreams to extract scores from records
ByteArrayInputStream bais1 = new ByteArrayInputStream(rec1);
DataInputStream inputStream1 = new DataInputStream( bais1 );
ByteArrayInputStream bais2 = new ByteArrayInputStream(rec2);
DataInputStream inputStream2 = new DataInputStream(bais2);
int score1 = 0;
int score2 = 0;
try { // Extract the scores
score1 = inputStream1.readInt();
score2 = inputStream2.readInt();
} catch ( EOFException eofe ) { }
catch ( IOException eofe ) { }
// Sort by score
if ( score1 < score2 ) return RecordComparator.PRECEDES;
else if ( score1 > score2 ) return RecordComparator.FOLLOWS;
else return RecordComparator.EQUIVALENT;
}
Case Study: RMS APIs
RMSGameScores.java
public void pauseApp() { }
// Close the open RecordStore when destroyed
public void destroyApp( boolean cond ) {
System.out.println( "destroyApp( )");
try {
if( recordStore != null )
recordStore.closeRecordStore();
} catch ( Exception ignore ) { // ignore
this }
}
57
MIDP Networking APIs
MIDP Networking
l
l
l
l
Extends CLDC Connectivity support
Supports a subset of HTTP protocol,
which can be implemented using IP
protocols such as TCP/IP
Non IP protocols (WAP & I-mode) can
also implement using a Gateway to
HTTP access
MIDP implementations must support
HTTP1.1
58
Generic Connection
Framework
Connection
Stream
Connection
Notifier
Input
Connection
Output
Connection
Datagram
Connection
Stream Connection
Content Connection
HTTP Connection
HttpConnection
l
l
l
Generic Connection Framework
from CLDC provides the base
stream and content interfaces
HttpConnection defines the
necessary methods and constants
for an HTTP connection
HTTP, a request-response protocol
in which the parameters of request
must be set before the request is
sent
59
HttpConnection - states
l
Connections exists in one of the
following states:
u Setup
n
n
Connection has not been made to the server
setRequestMethod(),
setRequestProperty() methods called
u Connected
n
Connection has been made. Request
parameters have been set. Response expected
u Closed
n
Connection has been closed. Methods will throw
IOException, if called
HttpConnection - states
l
Transition from Setup to Connected
state caused by any method that
requires data to be sent or received
u openInput[Output]Stream(),
getLength(), getType(),
getHeaderField(), getEncoding(),
getResponseCode(),getDate(), etc…
l
Following methods may be called when
Connection is open
u close(),
getRequestMethod(),
getURL(), getHost(), getFile(),
getPort() etc
60
HttpConnection Example
public class HttpTest extends MIDlet {
private Display display;
String url = "http://developer.java.sun.com/
cgi-bin/getgrade.cgi?name=1820";
public HttpTest() {
display = Display.getDisplay( this );
}
public void startApp() {
try {
getGrade( url ); // use HTTP.GET
getGradeWithPost( url ); // use HTTP.POST
} catch( IOException e ) { e.printStackTrace();
}
void getGrade( String url ) throws IOException {
HttpConnection c = null;
StringBuffer b = new StringBuffer();
// continued…`
HttpConnection Example
// continued from the previous slide
try {
c = ( HttpConnection )Connector.open( url );
c.setRequestMethod( HttpConnection.GET );
c.setRequestProperty( "IF-Modified-Since",
"10 Nov 2000 17:29:12 GMT" );
c.setRequestProperty( "User-Agent",
"Profile/MIDP-1.0 Configuration/CLDC-1.0" );
c.setRequestProperty( "Content-Language", "en-CA" );
InputStream is = c.openDataInputStream();
while( ( int ch = is.read() ) != -1 ) {
b.append( (char) ch );
TextBox t = new
TextBox("Grades",b.toString(),1024,0);
}
} finally { if ( is != null )is.close();
if ( c != null ) c.close();
}
display.setCurrent( t ); }
61
HttpConnection Example
void getGradeWithPost( String url ) {
try {
c = ( HttpConnection )Connector.open( url );
c.setRequestMethod( HttpConnection.POST );
// setRequestProperty as in the previous slide
OutputStream os = c.openOutputStream();
String str = "?idnum=182016";
byte postmsg[] = str.getBytes();
for int( i = 0; i < postmsg.length; i++ )
os.writeByte( postmsg[i] );
os.flush();
InputStream is = c.openDataInputStream();
while( ( int ch = is.read() ) != -1 ) {
b.append( (char) ch );
TextBox t = new
TextBox("Grades",b.toString(),1024,0);
}
} finally { /* as per previous slide */
}
display.setCurrent( t ); }
Summary
l
l
l
l
MIDP networking builds on the Generic
Connection Framework in CLDC
MIDP implementations must support HTTP 1.1
or higher
Easy for the non-ip based devices to
support HTTP as they can use a HTTP
gateway
MIDP implementations may choose to
implement network protocols above and
beyong HTTP
62
Advanced Topics:
Wireless Security
Objectives
Background,vision and goal
l Security architecture for existing
wireless data services
l SSL and its evaluation for small devices
l Current status and availability
l Summary
l
63
Original Vision and Goal
Make handheld devices more useful in an
enterprise setting. Better integration with
Intranet (currently non-existent or
insecure).
Guiding goal: mobile access to Sun's
enterprise portal for remote access.
Requires several components - local apps
on mobile device, appropriate content
generation, secure transport
Research Challenge: Can we effectively
reuse popular security standards from the
wired world?
l
l
l
Security situation – Then
l
l
WAP's "wireless is different" philosophy:
UDP->WDP, TLS->WTLS, HTTP->WSP,
HTML->WML, ECMAScript->WMLScript
No good faith feasibility study of a
standards based approach: optimized TCP
[PILC], optimized TLS, HTTP or HTTP-ng,
XHTML-Basic [XHTML-B]
64
Proxy-based Architecture
A proxy inserted between mobile device
and content server performs protocol
conversions, e.g. WAP, Palm.net
All communication forced through service
provider's (single, pre-programmed)
proxy/gateway creating a "walled garden"
Concerns:
t Scalability: single choke point, no end-toend flow control
t Legal: antitrust issues
t Security: built-in "man-in-the-middle"
l
l
l
Secure Socket Layer (SSL)
l
l
l
By far, the dominant security protocol on
the web (https=http over ssl)
Deserves full credit for the emergence of ecommerce and other security sensitive
services on the web (banking, stock
trading)
Both the protocol and its implementation
have benefited from several years of public
scrutiny.
65
SSL Overview
l
l
l
Operates on top of a bi-directional, reliable
byte stream (in order delivery without
duplication or loss). Typically this is
provided by TCP.
Offers end-to-end security even when the
underlying reliable byte stream is proxied.
An HTTPS proxy is not privy to information
exchanged (acts as a TCP relay).
Has seen several revisions - SSLv2.0,
SSLv3.0, SSLv3.1 (aka TLSv1.0). Most
clients/servers support multiple versions.
SSL's Layered Architecture
66
Common Thinking (Re: SSL
for Small Devices)
l
l
l
l
Too heavyweight for ``weak'' CPUs (by
PC/Workstation standards) and lowbandwidth, high latency wireless networks.
RSA operations used in key exchange are
of special concern.
Handshake is chatty and involves long
messages (particularly X.509 certificates).
SSL memory requirements, both static and
runtime, believed to be high
Unfortunately, these hadn't been quantified
But Consider This ...
l
Some constraints ease others, e.g. CPU only
needs to be fast enough for bulk encryption/MAC
computation at (low) network speeds.
l
RSA operations typically required at an SSL
client are quick, even compared to ECC
t Fast hardware implementations available on
smartcards. RSA now in public domain.
l
There are several opportunities to amortize
the cost of expensive operations by reusing
their results multiple times.
67
New Security Classes for
J2ME
Interfaces and Classes
l
l
com.sun.ksecurity: Key*, KeyStore‡,
PrivateKey*, PublicKey*, RSAPrivateKey*,
RSAPublicKey*, Certificate‡, KeyBuilder*,
MessageDigest*, RandomData*, SecretKey*,
CryptoException*
com.sun.kssl: SSLStreamConnection,
HandshakeListener, Cipher**, Signature*,
X509Certificate‡
*modeled after javacard.security
**modeled after javacardx.crypto
‡modeled after J2SE java.security
68
Supported Features
Keys: Symmetric keys (different lengths),
RSA Public/Private Keys with modulus
lengths up to and including 1024
Ciphers
Message Digests
Signatures
Certificates:
t Only supports X.509 certificates
containing RSA keys
t KeyStore: can only store certificates
l
l
l
l
l
Supported Features
(Certificates and KeyStores)
l
l
Certificates:
t Only supports X.509 certificates
containing RSA keys and signed using
RSA_MD5 or RSA_SHA.
t X.509v3 extensions are handled
correctly KeyStore: can only store certificates (no
private keys or symmetric keys).
69
Supported Features (SSL)
l
l
Client-side implementation of SSLv3.0.
Supports session reuse.
Supports two most common and fast
cipher suites - RSA_RC4_ 128_ MD5
and RSA_RC4_40_MD5
l
l
l
No client-side authentication(rare). Server
authenticated through RSA signatures
No restrictions on cert chain length
Maintains extensible set of trusted
Certification Authorities covering > 95% of
SSL server certificates
API Usage (Example 1)
public class MyApp {
public static void main(String[] args) {
MyApp myapp;
...
StreamConnection sc = (StreamConnection)
Connector.open("sslsocket://xyz.com:443" +
";CertificateErrorHandling=warn" +
";HandshakeCommentary=on");
InputStream in = sc.openInputStream();
OutputStream out=sc.openOutputStream();
// send data by writing to out, receive by
// reading from in
...
in.close(); out.close(); sc.close();
}
}
70
API Usage (Example 2)
public class MyApp implements HandshakeListener {
public void SSLHandshakeUpdate(String s) {...}
public boolean SSLCertificateOk(
X509Certificate c, byte error) {...}
public static void main(String[] args) {
MyApp myapp;
...
StreamConnection sc = new
SSLStreamConnection("xyz.com", 443, myapp);
InputStream in = sc.openInputStream();
OutputStream out=sc.openOutputStream();
// send data by writing to out, receive by
// reading from in
...
in.close(); out.close(); sc.close();
}
}
API Usage (Example 3)
public class MyApp {
byte[] mod = ...; byte[] exp = ...;
byte[] data = ...;
RSAPrivateKey priv = (RSAPrivateKey)
KeyBuilder.buildKey(KeyBuilder.
TYPE_RSA_PUBLIC, (short) 1024, false);
priv.setModulus(mod, 0*, mod.length*);
priv.setExponent(exp, 0*, exp.length*);
Signature sig = Signature.getInstance(Signature.
ALG_RSA_SHA_PKCS1, false);
byte[] res = new byte[sig.getLength()];
sig.init(priv, Signature.MODE_SIGN);
sig.sign(data, (short) 0, (short) data.length,
res, (short) 0);
// send data along with signature in res
...
}
71
Memory Requirements
l
l
The addition of com.sun.ksecurity and
com.sun.kssl packages increases KVM
size (on Palm) from 272KB to 359KB
(original prototype was 64KB). Can use
hardware implementation on Javacard
instead.
A J2ME application, SNMail, that uses an
SSL-based VPN to communicate with mail
servers on Sun's Intranet runs in less than
128KB heap on Palm.
KSSL Performance on
Palm
Bulk encryption and hashing adequately
quick: RC4 (100 Kbits/s), MD5 (63 Kbits/s),
SHA (57 Kbits/s)
l SSL handshake delay across a CDPD
network (a) 20 sec for full handshake when
client parses & verifies server certificate, (b)
cert caching reduces this to ~15 sec, (c)
abbreviated handshake takes 5 sec, (d) } 0
with persistent HTTP
l Offloading RSA to smartcard can reduce
(a) (b) by 30-50%
l
72
Current Status and Next
Steps
l
l
l
l
Presented at 48th IETF and WAP's SRC &
WSG as input for the proposed merger of
TLS and WTLS. New IETF draft on wireless
friendly extensions to TLS.
HTTPS functionality in reference MIDP1.0.2
implementation scheduled for Sep 2001.
Demo applications available for mobile
access to Sun's Intranet portal. MIDP port
in progress.
Exploring Javacard-based prototype of
KSSL and support for Elliptic Curve
Cryptography.
Summary
l
l
l
Careful implementations of Internet security
standards have acceptable performance on
today's wireless, mobile devices.
Technology trends will soon alleviate any
remaining concerns w.r.t performance.
End-to-end security, full compatibility with
large installed base of secure web servers
are compelling reasons to consider
SSL/TLS as the solution for next generation
smartphones/PDAs. Recent WAP Secuirty
Group (WSG) decision to embrace TLS for
WAP is highly commendable.
73
Advanced Topics:
XML Access from MIDlets
Objectives
l
l
l
XML is a very powerful markup language
Learn about different ways to access XML data
from MIDP applications
Case study of an XML parser written for MIDP
(where XML Parsing happens on the MIDP client
side)
74
MIDP and XML – Issues to
be aware of
l
l
l
l
l
MIDP networking allows access to data formats
such as XML, WML, etc.
XML Parsing == Heavy String Manipulation.
Keep in mind that all the string manipulation has to
happen on MIDP devices
Adding an XML parser to the MIDP client, adds to
the footprint. MIDP_NG proposal includes a
proposal to include an XML parser
Of course, as always think about alternatives
u Example: XML parsing on the Server instead of
the MIDP Client
Be aware of what you ask for – you might get it !!!
XML Parsers for MIDP
l
l
l
KXML
u Available from http://www.kxml.org
u Supports both SAX and DOM Parsing
u Written exclusively for J2ME/CLDC/MIDP
NanoXML
u Available from
http://nanoxml.sourceforge.net/kvm.html
u Supports DOM Parsing
u Ported to CLDC/MIDP
XSLT supported in both the parsers to convert the
data to formats such as WML, HTML
75
Sample XML Midlet:
Interaction with the Middletier
l
XML data (StockQuotes) is providaed by a
Servlet which is identified by a known URL
u Example:
http://127.0.0.1:8080/ServletXML/ServletXML
l
l
l
XML obtained as Streaming data and
subsequently converted to a String for
further processing
SAX Parsing (Event driven) done for the
project
Following MIDP UI elements used for
input/output of data:
u Form, TextField, Command, List
MIDlet/KXML development:
Steps
l
l
l
l
Obtain kxml from http://www.kxml.org and
install the kxml classes in a directory called
classes under the current directory. This
is where we will write our MIDP client code
Compile & Preverify(including kxml classes)
We use TomCat 3.2 to create, build and
deploy our servlet that generates the XML
data. For more information, please refer to
http://java.sun.com/products/servlet
Be sure to start the servlet and test the
servlet from a Web Browser (Example URL:
http://127.0.0.1:8080/ServletXML/ServletXML)
76
HttpConnection Example
public class HttpTest extends MIDlet {
private Display display;
String url = "http://developer.java.sun.com/
cgi-bin/getgrade.cgi?name=1820";
public HttpTest() {
display = Display.getDisplay( this );
}
public void startApp() {
try {
getGrade( url ); // use HTTP.GET
getGradeWithPost( url ); // use HTTP.POST
} catch( IOException e ) { e.printStackTrace();
}
void getGrade( String url ) throws IOException {
HttpConnection c = null;
StringBuffer b = new StringBuffer();
// continued…`
Servlet Code Example
// Respond to the HTTP.POST request
public void doPost(HttpServletRequest request,
HttpServletResponse response) throws IOException,
ServletException {
String ticker = request.getParameter("Ticker");
String price = request.getParameter("price");
String company = request.getParameter("Company");
System.out.println("Got a POST: Ticker = " + ticker + ",
New price = " +
price + " Company Name = " + company );
response.setContentType("text/html");
PrintWriter out = response.getWriter();
// Processing is simply a call to with
// appropriate parameters. For now return TRUE
out.println( "true" );
System.out.println( " HTTP Post returned True...!!" );
}
77
Servlet Code Example
private void generateXML( PrintWriter out ) throws
IOException {
out.println("<?xml vesion=\"1.0\"?>");
out.println("<QUOTELIST>");
out.println("<STOCKQUOTE>");
out.println("<ticker>SUNW</ticker>");
out.println("<price>20.0</price>");
out.println("<company>Sun Microsystems, Inc</company>");
out.println("<date-open>April 1981</date-open>");
out.println("<reco>Highly Recommended</reco>");
out.println("</STOCKQUOTE>");
out.println("<STOCKQUOTE>");
out.println("<ticker>NOK</ticker>");
out.println("<price>35</price>");
out.println("<company>Nokia Systems</company>");
out.println("<date-open>November 191</date-open>");
out.println("<reco>Recommended</reco>");
out.println("</STOCKQUOTE>");
out.println( "</QUOTELIST>"); } }
MIDP Client code
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*; import java.io.*;
import org.kxml.*;
import org.kxml.parser.*;
public class HelloMIDlet extends MIDlet implements
CommandListener {
private Command exitCommand; // The exit command
private Command xmlCommand;
private Display display;
// The display for this MIDlet
private final static String SERVLET_URL =
"http://127.0.0.1:8080/ServletXML/ServletXML";
private static TextBox t;
private static String textBoxString = "";
public HelloMIDlet() {
display = Display.getDisplay(this);
exitCommand = new Command("Exit", Command.EXIT, 2);
xmlCommand = new Command( "XML", Command.SCREEN, 1 );
}
78
MIDP Client code
public void startApp() {
t = new TextBox("MIDlet XML", "kXML:Using SAX", 256, 0);
t.addCommand(exitCommand); t.addCommand( xmlCommand );
t.setCommandListener(this); display.setCurrent(t); }
public void pauseApp() { }
public void destroyApp(boolean unconditional) {
}
public void commandAction(Command c, Displayable s) {
if (c == exitCommand) { destroyApp(false);
notifyDestroyed(); }
else if ( c == xmlCommand ) {
try {
String xmlString = getXML();
byte[] xmlByteArray = xmlString.getBytes();
ByteArrayInputStream xmlStream = new
ByteArrayInputStream(xmlByteArray);
InputStreamReader xmlReader = new
InputStreamReader(xmlStream);
XmlParser parser = new XmlParser(xmlReader);
traverse( parser, "" ); }
catch( Exception e ){e.printStackTrace();} } }
MIDP Client code
// Traverses the XML file. Implemented in KXML
public static void traverse (XmlParser parser, String indent)
throws IOException {
boolean leave = false; String st = new String();
do {
ParseEvent event = parser.read ();
switch (event.getType ()) {
case Xml.START_TAG:
// see API doc of StartTag for more access methods
st = indent + "start tag: '"+event.getName () +
"'; attributes: "+event.getAttributes ();
System.out.println( st );
textBoxString += st;
traverse (parser, indent + "."); // recursion
break;
case Xml.END_TAG:
st = indent + "/end tag: '"+event.getName ()+"'";
textBoxString += st; leave = true;
break;
79
MIDP Client code
case Xml.END_DOCUMENT:
st = indent + "Document end reached!";
textBoxString += st; leave = true; break;
case Xml.TEXT:
st = indent + "text: "+event.getText ();
textBoxString += st; break;
case Xml.WHITESPACE:
break; // ignored
default:
}
} while (!leave);
t.setString( textBoxString );
}
MIDP Client code
public String getXML() throws IOException {
HttpConnection conn = null;
InputStream servletStream = null; OutputStream os = null;
StringBuffer xmlBuffer = new StringBuffer();
String xmlString = null;
try {
conn = (HttpConnection)Connector.open(SERVLET_URL);
conn.setRequestMethod(HttpConnection.GET );
os = conn.openOutputStream(); os.flush();
servletStream = conn.openDataInputStream(); int ch;
while ((ch = servletStream.read()) != -1)
xmlBuffer.append((char)ch);
xmlString = xmlBuffer.toString();
/* Ensure that we tidy everything up */
if (servletStream != null) servletStream.close();
if (conn != null)
conn.close();
if (os != null) os.close();
System.out.println( "Instructions are: " + xmlString );
return xmlString; } catch (IOException e) { /*Tidy */ }}}
80
Building MIDP Client
l
To compile
u javac -g:none -classpath
%classpath%;\.\classes -bootclasspath
%MIDP_CP% HelloMIDlet.java -d .\classes
l
To preverify
u %MIDP_HOME%\bin\preverify.exe -classpath
%MIDP_CP% classes
l
To Create the .jar file
u Jar HelloMIDlet.jar -C classes -cvf
l
To run with the J2ME emulator
u %MIDP_HOME%\bin\midp.exe -classpath
HelloMIDlet.jar -descriptor run.jad
Building MIDP Client (Contd)
l
MIDlet Descriptor File
MIDlet-Name: HelloMIDlet
tMIDlet-Version: 1.0
tMIDlet-Vendor: Sun Microsystems, Inc.
tMIDlet-Description: Sample XML MIDlet
tMicroEdition-Profile: MIDP-1.0
tMicroEdition-Configuration: CLDC-1.0
tMIDlet-1: MIDletXML,,HelloMIDlet
tAuthor: Srikanth Raju
t
l
Alternately, use the J2ME Wireless Toolkit.
Copy the MIDlet sources AND the kxml
sources to the <projName>\src
directory. Build, and Run.
81
Summary
l
l
l
l
l
XML Parsers are available for the J2ME
Platform
XML access is popular/desirable for MIDP
applications
HTTP access from MIDP enable XML access
Issues/compromises should consider the
amount of XML data to be parsed. If it is high,
parsing XML on the server side is a valid
alternative
Case study included a look at kxml parser
Advanced Topics:
Utility APIs
82
Objectives
l
l
l
Learn the utility classes available for
MIDP applications through CLDC
Case study of a MIDlet with time-slicing
needs
Can be thought of as foundation for more
complex applications
Contents of the java.util package
l
MIDP defines the following classes
and interfaces of java.util
u Classes:
n
Timer, TimerTask, Calendar, Date,
HashTable, Random, Stack,
TimeZone, Vector
u Interfaces
n
Enumeration
u Exceptions
n
EmptyStackException,
NoSuchElementException
83
java.util.Timer
l
l
Schedules tasks for future execution in a
background thread
Tasks may be scheduled for one time
execution or repeated execution
u Timer.schedule(
TimerTask, Date )
u Timer.schedule(TimerTask, Date,
period)
u Timer.schedule( TimerTask, long
delay, long period )
l
Thread-safe. Multiple threads can share a
Timer object
java.util.TimerTask
l
l
A task that can be scheduled by
java.util.Timer for execution
Abstract class.
public abstract TimerTask
extends Object implements
Runnable
l
Methods
u public
boolean cancel()
u public abstract void run()
84
Case Study: TimerMIDlet.java
import java.util.*;
public class TimerMIDlet extends MIDlet implements CommandListener {
//
private Display display = null;
private Ticker stockTicker = null;
private String[] _stocks = {"SUNW", "ORCL","NOK","MOT" };
private String[] _prices = {"105.1","75","40.25","35.5"};
Create exitCommand, backCommand, and doneCommand
private Timer stockRefresh = null;
private StockRefreshTask stockRefreshTask = null;
private int refresh_interval = 10000; // 1000 = 1 second
private List menu
= null;
private ChoiceGroup _updatesChoices = null;
private Form _updatesForm = null;
Case Study: TimerMIDlet.java
public TimerMIDlet() {}
public void startApp() throws MIDletStateChangeException {
display = Display.getDisplay(this);
menu = new List("Stock Menu", Choice.IMPLICIT);
menu.append("Updates", null);
menu.append("Add Stocks", null);
menu.append("Remove Stocks", null);
menu.addCommand( exitCommand );
menu.setCommandListener( this );
// Make the ticker
stockTicker = new Ticker( makeTickerString() );
menu.setTicker(stockTicker);
display.setCurrent( menu );
// rest of startApp() in the next slide
85
Case Study: TimerMIDlet.java
_updatesForm = new Form("Updates");
_updatesChoices = new ChoiceGroup("Update Interval:",
Choice.EXCLUSIVE);
_updatesChoices.append("Continuous", null);// 10 sec
// Add some more elements to _updateChoices
_updatesForm.setTicker(stockTicker);
_updatesForm.append( _updatesChoices);
_updatesForm.addCommand(backCommand);
_updatesForm.addCommand(doneCommand);
_updatesForm.setCommandListener( this );
//Set up and start the timer to refresh the stock quotes
stockRefreshTask = new StockRefreshTask();
stockRefresh = new Timer();
stockRefresh.schedule(stockRefreshTask,0,refresh_interval);
} // End of startApp()
Case Study: TimerMIDlet.java
class StockRefreshTask extends TimerTask
{
public void run() {
try {
// This method could read stock quotes from a URL
if ( _stocks.length == 0) { return; }
else {
for ( int i = 0; i < _stocks.length; i++ ) {
System.out.println( "Stock price for symbol: " +
_stocks[i] + " is: " + _prices[i] );
}
}
} catch (Exception e)
{
System.out.println( “Error. Update Failed" );
}
}
86
Case Study: TimerMIDlet.java
public String makeTickerString()
{
String retString = new String();
for ( int i = 0; i < _stocks.length; i++ ) {
retString += _stocks[i] + “ @ “ + _prices[i] + “ “;
}
return retString;
}
public void pauseApp() {
// free memory used by display, stockRefresh
// stockRefreshTask objects by setting them to null
}
public void destroyApp(boolean unconditional){
notifyDestroyed();
}
Case Study: TimerMIDlet.java
public void commandAction(Command c, Displayable d) {
if (c == exitCommand)
{
destroyApp(false);
notifyDestroyed();
} else if ( c == backCommand ) {
display.setCurrent( menu );
} else if ( c == doneCommand ) {
switch( _updatesChoices.getSelectedIndex() ) {
case 0: refresh_interval = 10000;
break;
case 1: refresh_interval = 900000;
break;
case 2: refresh_interval = 1800000; break;
case 3: refresh_interval = 3600000; break;
case 4: refresh_interval = 10800000; break;
default: break;
}
stockRefresh.cancel();
stockRefresh.schedule(stockRefreshTask,0,refresh_interval);
display.setCurrent( menu );
} // See next slide
87
Case Study: TimerMIDlet.java
else { // Still in Stock Menu.
List shown = ( List )display.getCurrent();
switch ( shown.getSelectedIndex()) {
case 0: // Updates
display.setCurrent( _updatesForm );
break;
case 1: // Add Stock
System.out.println( "Add Stock... ");
break;
case 2: // Remove Stock
System.out.println("Remove Stock...");
break;
}
}
}
Summary
l
l
MIDP applications can use the
java.util package (like java.io,
and java.lang from CLDC)
TimerTask and Timer classes
provide valuable APIs for time-slicing
applications
88
Advanced Topics:
Comprehensive Example
Objectives
l Case study of an application that uses all the
MIDlet APIs such as
u MIDlet
UI components, events
u Networking (Open a URL for stock
quotes)
u Use RMS APIS for storage
u Use Timer and TimerTask for
scheduling
89
Stock Example
A Open a HTTP connection to a Quote Server
A Provide a ticker with quotes for selected stocks
A Obtain detailed Trading information on a selected
stock ( Last Trade, High, Low, Open, %Change )
A Provide Whatif scenarios for various purchase
prices on a given stock
A Provide an ability to:
– Add and Remove stock symbols
– Determine the time interval at which stock
updates should take place
– Add/Remove Alerts for a given stock
Application Snapshots: Stock
Tracker
90
Application Snapshots: What If
Application Snapshots: Alert
91
Application Snapshots: Settings
Application Classes
A StockMIDlet
– Main MIDlet.class. Provides all UI components, and
event handling code.
– Contains the TimerTask class
A StockDatabase
– Wrapper for the RecordStore class. Handles
addition/deletion and updating a stock
A Stock
– Utility class that parses data from the quoteServer
or the database for easy use
A AlertDatabase
– Handles associating an Alert with a Stock
92
StockMIDlet.java
public void startApp() {
// Open the Stocks, Alerts, and Settings databases
// Make the tickerString
// Make the initial Stock Menu, and other UI components
// Initialize the TimerTask with the given default
// refresh_interval
}
public void pauseApp() {
// Release any resources that can be re-acquired by called
// startApp
}
public void destroyApp() {
// Cancel the refreshTask
// Close the databases that were open in startApp()
// call notifyDestoryed()
}
StockMIDlet.java
private void commandAction() {
// Event handling code for all the UI
}
private class StockRefreshTask extends TimerTask {
// For all the symbols stored in the stock database
// call getStockQuote() followed by stock.update()
// to update the info on the database
// Call checkAlerts to see if any alert conditions are met
}
private String getStockQuote() {
StreamConnection c = (StreamConnection)
Connector.open(quoteURL, Connector.READ_WRITE);
InputStream is = c.openInputStream();
StringBuffer sb = new StringBuffer();
while (( int ch = is.read()) != -1) { sb.append((char)ch);
Stock.parse(sb.toString()); return sb.toString();
}
}
93
StockMIDlet.java
private void addStock() {
// call stock.addS()
}
private void deleteStock() {
// call stock.delete()
}
private void setAlert() {
// For a given stock symbol, call alerts.add()
}
private void checkAlerts() {
// For a given symbol, call alert.enumerateRecords() to see
// if any alert has been set.
}
private void removeAlert() {
// call alerts.delete()
}
Stock.java
public static void parse( String quoteString ){
// Utility method to split up quoteString into Fields
}
public static String getName( String ticker)
public static int getPrice( String ticker)
public static int getTime( String ticker)
public static int getHigh( String ticker) // 52 week high
public static int getLow( String ticker) // 52 week low
public static int getOpen( String ticker) // opening price
public static int getPrev( String ticker) // Previous ask
94
StockDatabase.java
public void open( ) {
// Open the RecordStore. If it is not a new database
// load the recorrdId of the last record
}
public void close() {
// Close the database and remove it from persistence
// storage
public void cleanup() {
// Remove the database from persistent storage
}
public synchronized void add( String record ) {
// Add record to the database. Update the database’s last
// ID Counter. Add the recordId to our vector
}
public synchronized void delete( String record ) {
// Delete the stock from database, and remove its recordId
}
public synchronized void update(String symbol, byte[] data) {
// Update the stock(symbol) with the data in the Byte Array }
public synchronized void add( String record ) {
}
StockDatabase.java
public void open( ) {
// Open the RecordStore. If it is not a new database
// load the recorrdId of the last record
}
public void close() {
// Close the database and remove it from persistence
// storage
}
public void cleanup() // Remove the database from persistent storage
public synchronized void add( String record ) {
// Add record to the database. Update the database’s last
// ID Counter. Add the recordId to our vector
}
public synchronized void delete( String record ) {
// Delete the stock from database, and remove its recordId
}
public synchronized void update(String symbol, byte[] data) {
// Update the stock(symbol) with the data in the Byte Array }
95
StockDatabase.java
public synchronized String search( String symbol ) {
// Return the record we are looking for a given symbol
}
public synchronized RecordEnumerationn enumerateRecords () {
// Get a RecordEnumeration of Records in the database who
// match the stockFilter
}
public int getNumRecords {
// Return the number of Records in the database
}
private class stockFilter implements RecordFilter() {
public boolean matches( byte[] data ) {
return ( ( data.length < 5 ) ? : true ? False ); }
}
private class stockComparator implements RecordComparator() {
public int compare ( byte[] rec1, byte[] rec2 ) {
// Check to see if rec1 matches rec2
}
AlertDatabase.java
// Methods to open, close, enumerateRecords and, cleanup
// AlertRecordStore. Very similar to StockDatabase methods
public synchronized String search( String symbol ) {
// Return the alert for a given symbol
}
public int getNumRecords() {
// Return the record we are looking for a given symbol
}
private class AlertFilter implements RecordFilter() {
public boolean matches( byte[] data ) {
return ( ( data.length < 5 ) ? : true ? False ); }
}
private class AlertComparator implements RecordComparator() {
public int compare ( byte[] rec1, byte[] rec2 ) {
// Check to see if rec1 matches rec2
}
96
Summary
l
Case study of an application that uses all
the MIDlet APIs such as
u MIDlet
UI components, events
u Networking (Open a URL for stock quotes)
u Use RMS APIS for storage
u Use Timer and TimerTask for scheduling
l
Sample in 13_Stock
Advanced Topics:
MIDP for PalmOS and
Motorola iDEN devices
97
MIDP for PalmTM OS
l Released On May 30, 2001
l Available from
http://developer.java.sun.com/developer/earlyA
ccess/midp_palm/
l Targets devices running PalmOS 3.5
l Includes the following functionality
u Binary
release of CLDC/MIDP for
Palm
u Desktop utility for converting MIDlets
to PRC
u MIDP User Preference
u Samples & documentation
Using MIDP for PalmTM OS
l You can create a .PRC file from a .jar or .jad
file
l From MIDP for Palm distribution, copy the
following files to where you have your MIDlet:
u makeMIDPApp.jar
u mkSample.bat
l Edit mkSample.bat to reflect your .jar file
l Run mkSample.bat
java -jar MakeMIDPApp.jar -version 1.0
-type Data -creator mJav -nobeam -v -o
Hello.prc -JARtoPRC HelloMIDlet.jar
HelloMIDlet
98
Using MIDP for PalmTM OS
l Install MIDP.PRC from the MIDP-Palm
directory on your Palm handheld or the Palm
OS Emulator
u This installs the JavaManager on your
Palm
u Use it set Preferences
l Install the HelloMIDlet.PRC you created
l Now you are ready to launch this application
Palm Java Manager
• MIDP.prc
– 560kb
– Contains KVM and application manager
• Runs automatically when MIDlet is
launched
– MIDlets are launched from their own icons
• Java Manager Preferences
– System wide
• Application Preferences
– Apply to a single MIDlet suite
• Supports beaming of MIDlets
99
Java Manager Preferences
• Java Manager Preferences
– System wide
– Networking
– Application memory
– “Advanced” - debugging, console output,
heap stats
• Application Preference
– Game controls
– Button and keypad location
– Colors and drawing speed
How to get MIDP for Palm
• http://developer.java.sun.com/develo
per/earlyAccess/midp_palm
– Binary release of CLDC and MIDP for Palm
OS
– Desktop utility for converting MIDlets to PRC
files
– Preference setting tool
– Sample MIDlets
– User documentation
• Java Developer Connection login required
• Currently at EA2
100
Demo: Using MIDP for Palm
MIDP Device Programming
Nextel/Motorola I85S
101
Nextel/Motorola i85s
• CLDC 1.0 MIDP 1.0
•
•
•
•
•
•
•
– No device specific APIs
Download apps over serial cable
– No OTA provisioning yet
Packet data TCP/IP
111x100 4-level grayscale display
256 KB heap
~380 KB program space
Supports HTTP, socket, and datagram
connections
HTTP bandwidth ~300-1500 bytes/sec
Nextel i85s Development
• Buy a Motorola i85s, service, and serial cable
– http://www.nextel.com/websales/index.shtml
• Register with Motorola iDEN Developer
Program
– http://www.motorola.com/idendev
• Download and install the iDEN Update Software
– http://www.nextel.com/idenupdate
– Requires Internet Explorer 4.0 or better
• Register with Nextel's Developer Program
– http://developer.nextel.com
•
Get the Developer and PacketStream rate plans
– http://developer.nextel.com/secured_site/index.ht
ml confirmation via email
102
Getting the Phone Ready
• Once the Nextel developer plan has
signed you up, you may need to reset
the phone
–
–
–
–
–
–
–
Push MENU
Scroll to SETTINGS and select
Scroll to SECURITY and select
Scroll to MASTER RESET and select
Passcode = 000000
At MASTER RESET? Hit Yes
At CAUTION SEE MANUAL push OK
Application Development
l
l
Use your favorite IDE or the J2ME
Wireless Toolkit
The i85s phone is picky about jar
and jad files
u Hard
to get them right by hand
u Let IDE/toolkit build them for you
l
Jar & jad files are loaded directly
onto the phone
103
Loading the App on the Phone : Using
JAL Lite for Standalone MIDlets
• Apps are loaded over serial cable
• Connect serial cable to PC/Phone
• Launch JAL Lite
– Click on Connect
– Click on Download
– Choose .jad file
– jad & jar transferred
Loading the App on the Phone: Using
iDEN Update for Networked MIDlets
• Apps are loaded over serial cable
• Connect serial cable to PC
• Launch the iDEN Update Software
– Set serial port settings
– Log in with iDEN userid and password
– Go to “J2ME Developers” tab
– Choose .jad file
– jad & jar transferred
104
Installing and Running MIDlets
• MENU -> JAVA APPS gives list of MIDlet
suites
• MIDlet suite must be installed before it’s
run
– Shows INSTALL instead of SELECT
command button
– Takes several seconds
– Can hose your system if the battery dies in
the middle
• MIDlet suite must be de-installed before
reinstalling
– Can hose your system if the battery dies in
the middle
i85s Limits
•
•
•
•
•
•
•
•
UDP packets limited to 1472 bytes outgoing, and 2944
bytes incoming
Maximum of 4 concurrently open RecordStores
Maximum of 2 simultaneous network connections
Recommendation of 50kb max jar file size
– “>50kb jar file may not install”
– (42kb jar becomes 106kb application)
Jad file pickiness
Maximum of 16 MIDlets per suite
Classes loaded with Class.forName() need jad entries
– e.g., iDEN-Install-Class-2:
midp.uidemo.LabelDemo
See i85s/i50sx developer’s guide for details
105
Debugging
l
Can use serial cable and terminal
emulator to see System.out.println
output
u Set
baudrate=19200, data bits=1,
parity=none, stop bits=1, flow
control=hardware
u Enable Java debug with the following
command:
AT+WS46=252;+WS45=0;+IAPPL=2;D
u System.out.println output turns up on
terminal screen
Resources
• http://www.idendev.com
- iDEN
developer site
u iDEN
update program
u iDEN sdklist mailing list
u developer’s guide:
https://commerce.motorola.com/ide
nonline/ideveloper/program/iDENJ2ME-i85s-i50sx-Guide.pdf
106
Summary
Objectives
l
l
l
l
l
l
Explain configurations and profiles of
J2ME
Explain the technical aspects of J2ME
CLDC and MIDP
Show how to setup MIDP run-time
environment.
Show the MIDP development Tools
Explain XML – MIDP integration
Use sample program code to illustrate
MIDP APIs
107
J2ME: Key points
l
l
Java 2 Micro Edition addresses the
need for an elegant High Level
language and common set of APIs for
resource constrained devices
Defines Configurations
u Configurations
define minimum Java™
technology libraries and virtual machine
capabilities available on a broad range of
devices in all areas
l
Defines Profiles
u Specification
that details the Java
technology APIs, built on top of and
utilizing the underlying Java [Platform]
Edition, necessary to provide a complete
runtime environment for a specific kind of
device
CLDC: Key points
l
l
CLDC is base technology that defines the core
virtual machine features and libraries for small
devices
KVM/JVM differences
u No floating point support
u No user-defined class loaders
u No JNI, weak references, finalization, reflection
u Limited error handling support
l
New security model in CLDC
u Low Level VM security (external/in-device verifier)
u Application security through sandbox model
l
l
New Generic Connection Framework
Profiles must implement specific features
108
MIDP: Key points
l
l
Designed to work on top of CLDC
MIDP defines the following set of class
libraries
javax.microedition.midlet
u javax.microedition.lcdui
u javax.microedition.rms
u javax.microedition.io
u java.lang and java.util
u
l
What is NOT in MIDP Scope
How an application actually gets on the device
u End-to-end security model
u System or OEM specific application needs
u Any particular implementation
u
Programming for small
devices: Key points
l
l
l
l
l
l
l
Every byte counts
Don’t string String concats. Use
StringBuffer instead
Less Hashtable/Vectors
Reuse Buttons, and other resources
Use Code packer/obfuscator
Recycle objects
Keep track of memory
u
l
Use Runtime.getRuntime.get…()
Use any utility you may have to optimize
the heap size
109
Whats next?
Download the CLDC specification, and
the Reference Implementation for
Solaris, Linux, or Win32
Download the MIDP specification and the
MIDP reference implementation
Download the J2ME Wireless Toolkit
Obtain the SDK/IDE from a device
manufacturer. They will provide steps to
transfer your MIDP application to their
respective device
A
A
A
A
Discuss the J2ME™ Platform
l
The kvm-interest mailing list is a free J2ME
development list hosted by Sun
u
u
u
l
To subscribe, send email to:
[email protected]
In the body of the message, type:
subscribe kvm-interest
For digest mode, include the following line:
set kvm-interest digest
The kvm-interest archive is searchable online at:
archives.java.sun.com/archives/kvm-interest.html
110
J2ME™ Platform Resources
l
l
l
l
l
J2ME:
java.sun.com/j2me
Connected, Limited Device Configuration
specification and SDK:
java.sun.com/products/cldc
Mobile Information Device Profile
specifications and implementations:
java.sun.com/products/midp
Download the Sun J2ME Wireless Toolkit:
java.sun.com/products/j2mewtoolkit
J2ME and Wireless Webcasts:
java.sun.com/jdc/onlineTraining/webcasts
Additional Resources
l
l
l
l
J2ME™ Archive:
www.billday.com/j2me
jGuru J2ME FAQ: www.jguru.com/faq/J2ME
J2ME tutorial articles:
java.sun.com/jdc/technicalArticles/wireless
J2ME tools CD, available now as part of
Java Jumpstart™ from Sun Developer
Connection (SDC)
111
Summary
l
l
l
There is tremendous opportunity for
markup and Java™ technology-based
wireless development.
Develop for 2G networks now, planning
and designing for 2.5G and 3G
possibilities as you go.
Get started today!
About the Instructor
Bill Day is a Technology Evangelist at Sun
Microsystems.
Bill created the J2ME Archive to help developers build
wireless applications and services using Java
technology. He manages jGuru’s J2ME FAQ. Bill
writes about software development for numerous
publications and speaks frequently on Java and
Wireless development at major industry conferences
including SIGGRAPH and JavaOne. He is also a Sun
Certified Programmer for Java 2 Platform.
More information is available from Bill’s web site:
www.billday.com
112
Copyright Statement
Copyright © 2001 by Bill Day. Permission to make hard
copies of part or all of this presentation for personal use is
granted without fee provided that copies are not made or
distributed for profit or commercial advantage and notice
is given that copying is by permission of Bill Day.
Copyrights and trademarks for components of this work
owned by others than Bill Day must be honored.
Portions © Copyright 2001 Sun Microsystems, Inc.,
All rights reserved.
Sun, Sun Microsystems, the Sun logo, Solaris, Java,
PersonalJava, Java TV, EmbeddedJava, Java Card,
Java Hotspot, JavaOne, JavaScript,
iPlanet, JDBC, JDK, JavaCheck, Enterprise
JavaBeans, Java Embedded Server, Java Community
Process, The Java Coffee Cup Logo, Java Virtual
Machine, Java Native Interface, JVM, J2ME, J2SE, and
The Network Is The Computer are trademarks or
registered trademarks of Sun Microsystems, Inc.
in the United States and other countries.
Thanks to Srikanth Raju of Sun for use of some of his
MIDP in depth materials. Thanks also to Keith Bigelow
of Lutris for his help with some of the WAP and i-mode
related material.
113