Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
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