High portability has been one of LWUIT's main design principles. LWUIT is portable as a library and it also enables application porting in such a way that binary code or source can be compatible across different Java ME profiles. This philosophy has also been preserved while implementing Series 40 specific features into the LWUIT for Series 40 port.
To understand LWUIT's portability, you must first understand the original problems in Java ME and the solutions LWUIT provides for each problem. These are listed below.
Low power, low memory devices
With CLDC 1.1 devices this is not as much of a problem as it used to be, but this should still not be overlooked. Series 40 devices range from devices with very cost-optimised hardware to the Nokia Asha phones, especially the recent full touch devices with a smartphone-alike user experience. With intelligent design, developers can achieve good performance in each category — for example, by not using memory hungry operations such as transitions in the low-end devices. Performance considerations are discussed in detail, including some concrete tips in the section Performance considerations.
Varying screen resolutions
LWUIT ships with a very fast low memory overhead scaling algorithm that does not lose transparency information. For extreme cases where the algorithm is not enough, LWUIT supports pluggable themes, allowing the UI to be customised with images more fitting to the resolution of the phone. Read more on this topic under Scalability.
Varying input methods
LWUIT detects softkeys automatically, and navigation is already portable. LWUIT supports touch screens seamlessly out of the box. Text input works with the Nokia TextEditor or device's native TextBox, ensuring proper input. Virtual keyboard is also built-in in full touch devices. Read more on the input support in LWUIT under Input.
Over-The-Air (OTA) code size limitations
The limitation in the JAR file size is still valid in today's Series 40 phones. The limit is 2MB (1MB in older non-touch devices). Because of the limit and the fact that LWUIT library is included in every LWUIT application, it is strongly recommended that all LWUIT applications are obfuscated. LWUIT fully supports obfuscation and works properly with obfuscators that remove redundant code. If jar file size is critical, developers can use other approaches as well, in addition to obfuscation. They can, for example, create unique packages to different device types (typically categorised by the UI style: non-touch, touch and type, and full touch) so that each package would only contain one theme. For more information on how to take obfuscation into use in each IDE, follow the instructions in the Getting started section.
Non-UI related pitfalls (for example, networking issues and RMS incompatibility)
LWUIT currently focuses on UI related issues, so you must find your own solution for the many minor issues related to these problems. For most common use cases, failure occurs because the device expects the “right thing”. For example, networking is problematic on some devices due to a connection that was never closed, and so forth.
In today's Java ME phones, the virtual machine and the graphics chip usually work flawlessly, thus allowing developers to rely on proper exception handling and class loading behaviour, instead of using complicated preprocess statements. Adaptive design and development also brings a clear advantage in code maintenance (such as refactoring and compiler checks), simplicity in reusing object oriented paradigms, and easier deployment (one JAR file for all or most devices).
If a missing API is invoked in code, it throws an exception because it does not exist. You can catch that exception and activate a flag disabling the functionality related to the feature. For example, your application might offer a location based feature based on JSR 179. You can wrap the calls related to JSR 179 code in try/catch and disable the functionality if a Throwable is thrown by the code (for example, NoSuchMethodError or ClassNotFoundException).
An example of this approach exists in the M3G class from LWUIT which is designed to run on devices that do not support JSR 184. The Log class is also designed in a similar way. It can utilise the FileConnector when the API is available in order to log to the device file system rather than RMS.
In some cases a device may also throw an exception, even if the API is supported, under a certain condition when using the API. For example, this happens with several devices that fail in drawRGB. The solution is to catch the exception and activate a flag to invoke a different code path designed for that device class only.
If you know that many devices have a bug with a certain API or with a specific usage of it, avoid that API or usage if possible. For example, many devices have a problem with flushGraphics(int, int, int, int), but all devices tested worked perfectly with flushGraphics().
Limitations are often related to appearance, number of colours, device speed, device resolution, and so forth. These can be worked around using a multitude of themes and picking the right default theme upon startup or disabling transitions on low-end phones. Use the methods in Display to check general device capabilities, then enable or disable some features.
For example, some devices support only three alpha levels (0%, 50%, 100%). Anti-aliased fonts do not look good on those devices especially when using white over black color schemes. It is easy to detect such devices using method Display.numAlphaLevels() to disable non-compatible themes (or simply exclude them from the default state). Another example of such a property is numColors to detect the colour depth.
Speed and memory constraints are much harder to detect on the fly. TotalMemory is often incorrect on devices and speed is hard to detect. True memory heap can be detected by allocating byte arrays until an OutOfMemoryError is thrown. While the VM is not guaranteed to be stable after an OOM, it generally recovers nicely. Store the amount of memory in RMS to avoid the need to repeat this exercise.
Read more on available techniques from an article Adaptive design and development on Series 40 in the Java Developer's Library, available as an online library in Nokia Developer web site and in the Nokia SDK 2.0 for Java.
One of the biggest challenges in Java ME programming is to adapt the application UI to various device resolutions. This is especially difficult because of lack of scaling support and the small selection of devices with SVG support. Another problem is varying aspect ratios; aspect ratio can even change in runtime on the same device, for example, when changing the orientation.
LWUIT solves the lack of scaling support by including a fast low overhead scaling algorithm that keeps the image's alpha channel intact. Scaling on devices is far from ideal for some image types. It is recommended that designers avoid “fine details” in images that are destined for scaling.
Since images and themes can be stored in resource bundles, such bundles can be conditionally used to support different resolutions. This solution is not practical on a grand scale with a single JAR file strategy; however, for some basic resolution and important images this is a very practical solution, especially when dynamically downloading resources from a server.
This section describes how LWUIT deals with various input methods on non-touch and touch-based phones. LWUIT has a built-in support for touch and non-touch user interfaces, and this principle is also followed in the changes made in LWUIT for Series 40.
Softkeys
Softkeys for common devices in the market are detected automatically by LWUIT. If LWUIT fails to detect a specific device, a developer can still set the key code for the soft keys using setter methods in Display. However, this should not be needed in any Series 40 device.
In LWUIT for Series 40, the commands are placed following the rules of each Series 40 UI style, so that correct command types always show in correct places. In Series 40 touch and type and non-touch phones, the LWUIT MenuBar takes care of showing commands in the sotfkeys and options menu. In Series 40 full touch phones, the LWUIT commands are mapped to native commands shown in the Series 40 full touch platform chrome. This happens transparently to the application. Read more on softkeys and command handling in section Commands and menus.
Designing for the touch UI
Touch screens are supported out of the box; however, designing a UI for finger operation is very different from designing a UI for general use. Finger operations expect everything to be accessible via taps (not keys).
A touch interface expects widgets to be big enough to fit the size of a human finger. This is somewhat counter-intuitive, because normally you might want to cram as much UI detail as possible into a single screen to avoid scrolling.
Component sizes can be easily customised globally using the theme (this has been done in touch and type and full touch themes). Simply set the default padding attribute to a large enough value (e.g. 5, 5, 5, 5) and all widgets “grow” to suit finger navigation. It is also a good practice to use buttons for touch devices and avoid menus where possible.
Virtual keyboard
In Series 40 full touch devices, there is no hardware keypad to enter text with. When a TextArea or TextField is focused, a Series 40 virtual keyboard opens up to enable text input.
Gestures
On touch UI, also gestures can be used. Section Touch gestures describes how to use gestures supported in Series 40 touch phones.
Though LWUIT itself is highly portable, sometimes it may be better to create device type specific branches to application logic. For example, you can provide a completely different UI for non-touch and full touch versions of the application. Display.getDeviceType() is a static method that returns the type of the Series 40 device type the application is running in. The information can be used in runtime variation of the application.
Possible device types are:
NON_TOUCH_DEVICE
Devices with keypad input only.
TOUCH_AND_TYPE_DEVICE
Series 40 devices with touch and type UI, i.e.,devices with keypad and single touch input.
FULL_TOUCH_DEVICE
Devices based on Series 40 Developer Platform 2.0 that have multi touch input and no keypad.
The API changes in LWUIT for Series 40 port have been made so that compatibility would be preserved whenever possible. Developers should of course still avoid using any of the new interfaces or create fallback mechanisms if they want their application to work out-of-the-box on any other platform.
LWUIT for Series 40 library has an additional package com.nokia.lwuit that contains classes to access Nokia proprietary APIs and some utility classes. Most of the Nokia proprietary APIs are accessed via wrappers using indirect references to the classes, so the application does not crash when using the APIs on older Series 40 devices where the APIs might not exist. Note, however, that you should not rely on the existence of the com.nokia.lwuit package and its classes if you want to maintain API compatibility with original LWUIT.
LWUIT for Series 40 has also some added functionality in the classes under com.sun.lwuit package. If you need to maintain compatibility with original LWUIT, you should avoid directly using those methods.
In LWUIT for Series 40 port, some of the original LWUIT classes of the com.sun.lwuit package use Nokia proprietary APIs internally. That is, the implementations of some LWUIT UI components take advantage of the Nokia APIs when possible, but fall back to pure LWUIT solution if the APIs are not available. Examples of such classes are TextArea and TextField, which use the TextEditor from Nokia UI package. This affects also the virtual keyboard that is displayed on context of TextArea and TextField. The API compatibility is maintained and thus it should not affect porting between the original LWUIT and LWUIT for Series 40 port . Note, however, that the experience of running the application using LWUIT for Series 40 may differ from the original LWUIT application in these cases.
For a comprehensive list of all the additions, see section New classes and methods.