Java™-based development framework for PalmOS™ devices (PDAs) Copyright© 2000 by Bernd R. Fix. All Rights Reserved. |
|
Back to the section ... |
Porting DynaWorks to a J2ME implementation |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
If you want to use DynaWorks in an other environment than currently
provided, you can port the DynaWorks framework to that platform.
All you have to do is to implement the interfaces needed by the framework to run in an
environment - and you can compile and run your DynaWorks application
on the platform of your choice. It would be even possible (and not too complicated either) to write an emulator for DynaWork using J2SE that would run as a Java apllet from the web in any browser: you wouldn't even need a PalmOS™ ROM image to get that to work! Writing a port is straight forward: The functionality is very PalmOS™-oriented, so any J2ME™ implementation running on PalmOS™ is likely to support this (still) limited set of methods to make the port easy (This may change in the next versions as DynaWorks will support more PalmOS™ functionality over the time...). To demonstrate the things you have to do during a port, this section describes all steps that were neccessary to port DynaWorks to the KJava environment that comes with the KVM / CLDC from Sun.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Overview |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The image on the right (also found in the
Basic DynaWorks design section of
this manual) shows the basic components that are needed to run a
DynaWorks application in a PalmOS™/J2ME™
environment: The details of the underlaying implementation are hidden to the DynaWorks application (and developer); all 'communication' with implementation dependent features is routed through the singelton instance Environment that delegates the request to the actual Implementation running on the device. So the very first thing a DynaWorks application should do is to tell the environment, which Implementation to use. You can use wrapper classes to do so (see the documentation for further details) or the first statement in the main method of the start-up class should be Environment.setImpl (new J9Impl()) or something like that to initialize the environment. This must be done before anything else on the device can be done from the application! |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There are four processes/objects that are implementation-dependent:
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Involved interfaces |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There are four interfaces in the DynaWorks framework that
must be implemented if you want to use a certain PalmOS™/J2ME™ environment:
All these interfaces must be implemented for each environment you want to use. The next sections describe these interfaces in more detail. Each of these sections also include the source code for the KJava implementation. Of course each implementing class requires a constructor method. You are free to use any constructor arguments you need to perform the object creation in your environment. This comes in handy, since you can use complex initialization arguments if you need and the applications will never need to know: objects are never created via the new operator in a DynaWorks application, but thrught the class factory methods in the Implementation interface Although not explicitly defined by the interface, DynaWorks requires these constructors to confirm to certain rules; these rules are explained for each interface. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The `Audio´ interface |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Let's start with an easy one - the Audio interface:
The Audio interface allows the application to playback sound snippets defined by the system. There is no support for any kind of other sound snippets or MP3 files - all tones are predefined by the hardware platform. This is a limited approach, but sound is not a main issue in DynaWorks yet. The following sound constants are defined by the interface: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<<Constants>> | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The following methods need to be implemented: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Audio (String param) (<init>)> | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The constructor for the Audio class. The argument list and the implementation depend on the platform and runtime environment. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void playSound (int sound) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Use to play one sound from a list of predefined 'system sounds'. These sounds are defined as constants in the class (see above) and should sound different to each other when played (or the sound wouldn't carry an information ?!). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void dispose () | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Called by the framework when the implementation goes out of scope. This is the right point to release any system resources (audio) that were allocated in the constructor. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The `Graphics´ interface |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The Graphics interface is a bit more complex than the Audio, but I should
also be quite easy to implement on any PalmOS™ environment:
The Graphics object represents the 'canvas' where your application can draw bitmaps and primitives (like rectangles, lines, etc.), clear the screen, setting clipping areas and move raster areas around on the screen. A 'hidden' screen of the same size as the 'visible' screen is available for double-buffering or screen backup purposes. The coordinate system (x- and y-coordinates) has its origin (0,0) in the upper left corner of the screen. Positive x-coordinates run to the right and positive y-coordinates to the bottom. Currenly there is no support for color or fonts in DynaWorks. I hope this will change in one of the next versions. Since the Graphics interface is "derived" from the normal set of graphics routines in the PalmOS™, you find a lot more information about the single methods in the PalmOS™ documentation. The following constants are defined by the interface: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<<Constants>> | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The following methods must be implemented: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int getWidth() int getHeight() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Return the size of the screen in pixel. Although nothing limits this pixel range, it is still common to return 160 pixel in each direction as screen resolution. Whenever Palm makes PalmOS™ work with a different screen size and we have a layout manager in DynaWorks, these methods make much more sense - but they are here already. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void clearScreen() void setDrawRegion (int x, int p, int w, int h) void resetDrawRegion() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
clearScreen clears the complete canvas to the background color
(that is white). setDrawRegion(...) defines a clipping area on the screen at the defined position and dimension. Any draw operation that follows only leaves visible 'marks' within the defined clipping area. resetDrawRegion() removes any clipping area. Please make sure that you nest calls to setDrawRegion() and resetDrawRegion() correctly, since not all implementations may have a stack of clipping areas. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void drawBorder (int x, int y, int w, int h, int mode, int width, int round) void drawRectangle (int x, int y, int w, int h, int mode, int round) void drawBitmap (int x, int y, Bitmap icon) void drawLine (int x, int y, int xx, int yy, int mode); |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
These are the basic methods for the graphical primitives Border (a filled
rectangular area with rounded corners and shadow), Rectangle (a outline
of a rectangular area with rounded corners), Bitmap (a bloack/white raster image)
and Line (a line between two points in different thickness and color). The drawing mode can be set to different value from the constant table above. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int getStringWidth (String s) int getStringHeight (String s) |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
These methods return the length and height (in pixels) of the bounding
box of a string on the canvas. These methods are used by the application
to determine the size on the screen before painting a string. Note: Since there are no fonts in DynaWorks yet, the PalmOS™ built-in font is used! |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int drawString (String text, int x, int y, int mode) int drawString (String text, int x, int y) |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
These methods are used to print text strings on the screen. Texts are
not wrapped at the end of the screen, so it is up to the application
to ensure texts fit on the screen. The mode argument can be one of the draw style values (PLAIN, GRAY, ERASE, INVERT). The second method call has PLAIN preset as a mode argument. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void bitBlt (int sx, int sy, int w, int h, int tx, int ty, int mode) void bitBlt (int sx, int sy, ... , int ty, int mode, int from, int to) |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
These methods allow to copy an area of the screen (or of the background buffer) to
another area of the same size on the screen (or in the buffer). The mode of the
operation determines how the source and the target pixel behave. The first method is used to bitblt areas on the screen; the second method allows to specify a source ('from' = SCREEN|BUFFER) and a target ('to' = SCREEN|BUFFER), so you can bitblt between screen and background buffer. The pixel in each area is represented as by a bit; if it is 0 you see the background (white); if it is 1, the pixel is drawn as a black dot. So any 'boolean' operation between pixels can be expressed as bit logic. The bitblt mode decides, which boolean operation should be performed during the operation:
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void dispose () | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Called by the framework when the implementation goes out of scope. This is the right point to release any system resources (graphic) that were allocated in the constructor. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The `Database´ interface |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The following error codes are defined by the interface: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<<Error Codes>> | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The following methods have to be implemented: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int getErrorCode () | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Return the current error code from the database. The return value can be any of the defined error codes from the table above. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
boolean open () | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Open the database object: If the database does not exist, it
is created and then opened. All information required to address and to open the database were already passed to the object in the constructor call. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void close () | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Close the database. In an implementing class this is a good point to free any resources allocated during an open() call. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int numberOfRecords () | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Return the number of records in a database. In case the database can not be
accessed or there is an error of any kind, the method returns the value -1;
otherwise the number of (undeleted) records is returned. Please note: The KVM implementation of the PalmOS™ database is somewhat strange: It returns the overall number of records in the database, including deleted entries (that always show up at the end of the database). More... |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int addRecord (Dataset rec) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
This method adds a new record into the database. The argument passed in
referes to an implementing class of the interface Dataset (a
generic byte field container). This interface is implemented by the
Record class in the package brf.j2me.dynaworks.db.
The method returns the sequence index of the new record in the database. Please note: The KVM implementation of the PalmOS™ database does not allow access to the unique index of a record. Therefore all record indexing is based on the current sequence of records in the database (and that may change due to deletion operations). This is likely to change in next versions of DynaWorks. More... |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
boolean getRecord (int idx, Dataset rec) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Read a record from the database at a given sequence index. The record
is passed in as a Dataset instance. Please note: The KVM implementation of the PalmOS™ database does not allow access to the unique index of a record. Therefore all record indexing is based on the current sequence of records in the database (and that may change due to deletion operations). This is likely to change in next versions of DynaWorks. More... |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
boolean putRecord (int idx, Dataset rec) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Write a record to the database at a given sequence index. The record
is passed in as a Dataset instance. Please note: The KVM implementation of the PalmOS™ database does not allow access to the unique index of a record. Therefore all record indexing is based on the current sequence of records in the database (and that may change due to deletion operations). This is likely to change in next versions of DynaWorks. More... |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
boolean deleteRecord (int idx) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Delete a record from the database at a given sequence index. The behaviour of the method varies among different J2ME implementions. This is vary unsatisfying, so the next release of DynaWorks will have a overhaul of the Database interface... Please note: The KVM implementation of the PalmOS™ database does not allow access to the unique index of a record. Therefore all record indexing is based on the current sequence of records in the database (and that may change due to deletion operations). This is likely to change in next versions of DynaWorks. More... |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The `Implementation´ interface |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The following methods have to be implemented: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
EventQueue register (EventQueue queue) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
This method registers the argument EventQueue with the PalmOS™
event loop. All events are now passed to this event queue until another
event queue registers with the Environment. The method returns the event queue that was registered before (or 'null' in case there was no such queue) to the caller.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Graphics getGraphics () | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
This method returns an access object for drawing operations. This object is a singleton (e.g. there is only one instance of the implementing class in the framework). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Audio getAudio() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
This method returns an access object for audio playback. This object is a singleton (e.g. there is only one instance of the implementing class in the framework). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Database getDatabase (String name) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The string argument to the constructor contains all information neccessary
to access a database on the PalmOS™ platform. It must confirm to
the following notation: The string consists of three parts that are each
delimited by a colon character (:). The single parts are:
|