February 27, 2004 8:20 PM

Nokia 7650 fact list

Nokia 7650 I'll use this diary entry to collect known facts about Nokia 7650 mobile phone and corresponding technologies (and I will update it when new facts come to my attention).

Nokia 7650 is the member of so called Series 60 developer platform. Devices in this series are based on Symbian OS and support both C++ and Java applications. 7650 contains Symbian OS 6.1.

Band Functionality: GSM900/GSM1800
Browser Version: WAP 1.2.1
Java APIs: CLDC 1.0 (JSR 30), MIDP 1.0 (JSR 37), Nokia UI API
Data Bearers: HSCSD, GPRS
PC Connectivity: Bluetooth, Infrared
Display resolution: 176 x 208
Color Depth: 4096 Colors (12 bit)
Heap Size: free RAM (up to 1.4MB)
Shared Memory for Storage: free user memory, up to 4 MB
Maximal Jar File Size: up to 4MB, WAP GW restrictions applies
Messaging: SMS, MMS, Email
Music Support: MIDI tones (poly 24), AMR audio clips (NB-AMR)
Dimensions: 114 x 56 x 26 mm
Weight: 154 g
Navigation Key: Grid key mat, 2 labeled soft keys, 5 way scrolling
Extra Features: VGA camera (640x480), SMTP/POP3/IMAP4 email, Handsfree speaker
My testing phone Nokia 7650 is identified (*#0000#) as:
V 5.06
02-06-03
NHL-2NA
Nice introduction to Series 60 is the document Developer Platform 2.0 for Series 60: Introductory White Paper (Dev_Plat_WP_v_1_0.pdf, 2.88 MB). Although primary oriented to business customers, it also describes differences between Developer Platform 1.0 and 2.0.

Getting Started with Java(TM) Technology (Getting_Started_with_Java_Technology_v1_1.pdf, 387 kB) is a very good introductory document for people who never used GUI programming environments. It also contains step-by-step creation of HelloWorld project.

Introduction to Series 60 Applications for Java Developers (Introduction_to_Series_60_Appls_for_Java_Developers.pdf, 122 kB) is much better introduction for developers. It contains the description of Java implementation for Series 60 devices.

Java 2 Platform, Mobile Edition (J2ME) consists of two main components:

  • Configuration (Connected Limited Device Configuration) - virtual machine (VM) and a small set of classes for system-level programming.
  • Profile (Mobile Information Device profile) - additional classes for new APIs (UI, sound, ...)
MIDlet is an application written for MIDP profile. They are written to extend javax.microedition.midlet.MIDlet class. This class controls the life cycle of each MIDlet by those three methods: startApp(), pauseApp() and destroyApp().

MIDlet suite is a JAR (Java ARchive) file containing several MIDlets and other classes. MIDlet suite is described by small text file called Java Application Descriptor (JAD file) that contains e.g. the name of the provider of MIDlet suite, the name of MIDlet suite, its size and URL.

The following table shows the source code of HelloWorld midlet:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class HelloWorld extends MIDlet implements CommandListener
{
    private Command exitCommand;
    public HelloWorld() {}
    public void startApp()
    {
        Displayable current = Display.getDisplay(this).getCurrent();
        if(current == null)
        {
            TextBox helloScreen = new TextBox("Hello World!", "Hello World!", 256, 0);
	    exitCommand = new Command("Exit", Command.EXIT, 1);
	    helloScreen.addCommand(exitCommand);
	    helloScreen.setCommandListener(this);
            Display.getDisplay(this).setCurrent(helloScreen);
        }
    }
    public void pauseApp() {}
    public void destroyApp(boolean b) {}
    public void commandAction(Command c, Displayable d)
    {
	if (c == exitCommand) {
	    destroyApp(false);
	    notifyDestroyed();
	}
    }
}
The following table shows how HelloWorld MIDlet looks like when run in several emulators and also on real device:
Nokia Developers Suite for J2ME Sun J2ME Wireless Toolkit 2.1 Sun J2ME Wireless Toolkit 1.0.4 Real device
HelloWorld MIDlet in the emulator HelloWorld MIDlet in the different emulator HelloWorld MIDlet in the different emulator HelloWorld MIDlet on the real device
Corresponding JAD file looks like:
MIDlet-1: HelloWorld, HelloWorld.png, HelloWorld
MIDlet-Jar-Size: 1169
MIDlet-Jar-URL: HelloWorld.jar
MIDlet-Name: HelloWorld
MIDlet-Vendor: Pavel Janik
MIDlet-Version: 1.0
How to deploy the MIDlet JAR file to the device? There are several ways to do that.

Sun J2ME Wireless Toolkit 2.1 provides the capability to run MIDlet via OTA. You will enter the URL of the HTML page containing link to JAD file and J2ME WTK simulates the phone fetching the file from the network, asking the user if he really wants to install the application and will finally install it. By default J2ME WTK uses webserver on the localhost so you can test it even without connection to the network. This is good for testing, but it is useless for deployment to real device.

How it works?

Over-the-Air deployment Over-the-Air deployment
1. Intro screen of Sun J2ME WTK 2.1 when running via OTA (Over-the-Air). 2. The Application Management System (AMS) page allows you to run the installed applications (none is installed by default) or to install new applications.
Over-the-Air deployment Over-the-Air deployment
3. When installing the application, you must enter the URL to the page containing the link to JAD file. Sun J2ME WTK 2.1 automaticall creates HTML page for you in the bin/ directory. 4. When the page is displayed, you can chose which JAD file to open.
Over-the-Air deployment Over-the-Air deployment
5. JAD file is displayed. The name of the application, its size, version, vendor and the full location of it JAR file are displayed. You can choose to cancel the installation or to install it. 6. Application was successfully installed and is now listed on the main AMS page.
On the other hand, real device works in the same way - you point its WAP browser directly to JAD file and the device lets you choose if you wish to install the package. If you wish to, it will download the JAR file and install it.

The MIME type for JAD files is text/vnd.sun.j2me.app-descriptor, the MIME type for JAR files is application/java-archive.

There are also other ways to deploy the MIDlet to the real device: via infrared (look at the OpenOBEX project), via Bluetooth, via e-mail and via MMS.

Going the systematic way of learning new things, I started to read CLDC specification. Here are my notes.

Connected, Limited Device Configuration, specification version 1.0a, Java 2 Platform Micro Edition

This specification defines Java platform for small devices (from only 160 kB to 512 kB of memory for Java virtual machine, configuration libraries, profile libraries and applications). CLDC is the core definition of Java platform and is the basis for profiles. Profiles are more focused definitions of Java platform for particular devices.

CLDC specification addresses the following areas:

  • Java language and virtual machine features
  • Core Java libraries (java.lang.*, java.util.*)
  • I/O and networking
  • security
  • i18n
Additional features are to be addressed by profiles.

So the architecture of CLDC devices is layered. The lowest level is host operating system (Symbian OS 6.1 in case of Nokia 7650), Java virtual machine, CLDC libraries (Java libraries), profiles (Java libraries, MIDP profile).

Java application is run by JVM by calling one single main function declared as

  public static void main (String[] args)
CLDC specification does not support floating point numbers, finalization of class instances.

There are two types of class libraries in CLDC:

  • classes that are subsets of standard Java 2 SE
  • classes specific to CLDC
The first group consists of java.lang.* (Object, Class, Runtime, System, Thread, interface Runnable, String, StringBuffer, Throwable, Boolean, Byte, Short, Integer, Long, Character, Math), java.util.* (Vector, Stack, Hashtable, interface Enumeration, small subset of Calendar, Date and TimeZone, Random) and java.io.* (InputStream, OutputStream, ByteArrayInputStream, ByteArrayOutputStream, interface DataInput, interface DataOutput, DataInputStream, DataOutputStream, Reader, Writer, InputStreamReader, OutputStreamWriter, PrintStream). CLDC specific classes are contained in the package javax.microedition.* (io).

Properties in CLDC: java.util.Properties is not implemented, but several properties are defined:

  • microedition.platform - name of the host platform or device (default null)
  • microedition.encoding - default character encoding (default ISO8859_1)
  • microedition.configuration - name and version of the supported configuration (default CLDC-1.0)
  • microedition.profiles - names of supported profiles separated by blanks (default null)
Those properties are available for reading by method System.getProperty(String property). Profiles may define additional properties.

Properties in NDS for the Java 2 Platform, Micro Edition's emulator (Series 60 MIDP Concept SDK Beta 0.3.1, Nokia Edition):

microedition.platform = j2me
microedition.encoding = ISO-8859-1
microedition.configuration = CLDC-1.0
microedition.profiles = MIDP-1.0 MIDP-2.0
Properties in Sun's Java 2 Platform, Micro Edition Wireless Toolkit's emulator (DefaultColorPhone):
microedition.platform = j2me
microedition.encoding = ISO8859_1
microedition.configuration = CLDC-1.1
microedition.profiles = MIDP-2.0
Properties in real Nokia 7650:
microedition.platform = Nokia7650
microedition.encoding = ISO8859_1
microedition.configuration = CLDC-1.0
microedition.profiles = MIDP-1.0
Generic Connection framework defined in CLDL allows network/serial connections. CLDC spec doesn't define protocols, only the framework. It is profile's task to define supported protocols.

The second basic specs is J2ME Mobile Information Device Profile (MIDP), specification version 1.0a, Java 2 Platform Micro Edition. Profile of Java 2 Micro Edition is a device-type specific set of APIs.

The MIDP specification defined minimal hardware characteristics as: screen resolution at least 96x54, 1bit display depth, pixel shape approximately 1:1, at least one input device (ITU-T phone keypad, QWERTY keyboard or touchscreen). Minimal memory requirements are: 128 kB non-volatile memory for MIDP components, 8 kB non-volatile memory for persistent data storage and at least 32 kB volatile memory for Java runtime (heap). And of course: two-way networking with limited bandwidth.

MIDP defines additional properties:

  • microedition.locale - current locale of the device (default null)
  • microedition.profiles - defined in CLDC, must contain at least MIDP-1.0
The specification requires locale to contain both language and country (like cs-CZ), but Nokia 7650 returns only en or de according to the selected language of the GUI.

Reading resources You can use java.lang.Class.getResourceAsStream for access to resource files bundled in MIDlet's JAR file. This code reads the contents of the resource file resourcefile.txt and displays it in the TextBox.

import java.io.*;
import java.lang.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class ApplicationResources extends MIDlet implements CommandListener
{
    public ApplicationResources() {}
    public void startApp()
    {
        Displayable current = Display.getDisplay(this).getCurrent();
	String resValue;
        if(current == null)
        {
	    InputStream resFile = getClass().getResourceAsStream("resourcefile.txt");
	    byte[] resByteArray = new byte[100];
	    int resLength = 0;
	    try {
		resLength=resFile.read(resByteArray, 0, 100);
	    } catch (java.io.IOException ex) {
		notifyDestroyed();
	    }
	    resValue = new String(resByteArray, 0, resLength);
            TextBox resourcesScreen =
		new TextBox("Resource contained in JAR file", resValue, resLength, 0);
            Display.getDisplay(this).setCurrent(resourcesScreen);
        }
    }
    public void pauseApp() {}
    public void destroyApp(boolean b) {}
    public void commandAction(Command c, Displayable d) {}
}
Call of java.lang.System.exit must throw java.lang.SecurityException (MIDlets should exit only by MIDlet.notifyDestroyed). The same applies to java.lang.Runtime.exit. When you call System.exit in the emulator, you get:
startApp threw an Exception
java.lang.SecurityException: MIDP lifecycle does not support system exit.
	at java.lang.Runtime.exit(+9)
	at java.lang.System.exit(+7)
	at Exit.startApp(+4)
	at javax.microedition.midlet.MIDletProxy.startApp(+7)
	at com.sun.midp.midlet.Scheduler.schedule(+266)
	at com.sun.midp.main.Main.runLocalClass(+28)
	at com.sun.midp.main.Main.main(+116)
Real device will produce alert "Application Error. Exiting...".

Timer and TimerTask classes. This part of MIDP specification allows applications to set alarms and be notified when they expire. Timers can be set to expiry once and also expire repeatedly. It is implemented by two classes:

  • java.util.TimerTask - this class implements interface Runnable and represents task that could be attached to Timer expiry for execution. Typical usage is:
    TimerTask myTask = new TimerTask() {
       public void run()
       {
       ... the code to run ...
       }
    };
  • java.util.Timer - this class is the actual timer that is scheduled for expiry with its schedule method:
       timer.schedule(myTask, 1000*seconds);
    
The Timer can be scheduled for one-time execution by those methods:
public void schedule(TimerTask task, long delay)
This schedules the timer to expire after delay milliseconds, or
public void schedule(TimerTask task, Date time)
which schedules the timer to specified time in the future. If the time is in the past, the task is called immediately.

The Timer can also be scheduled for repeated execution by:

public void schedule(TimerTask task, long delay, long period)
public void schedule(TimerTask task, Date firstTime, long period)
where delay (firstTime respectively) is the delay before the first execution (resp. the exact time of the first execution) and period is the time (in period ) before the next (and additional) executions. Scheduling using plain schedule can be very inaccurate because n+1th call of the function is scheduled according to time of nth call. This is called fixed-delay execution. It is inaccurate because of garbage collection in VM etc.

The second method to schedule tasks is fixed-rate execution. In this method, tasks are scheduled according the real time approximately. n+1th call of the function is scheduled according to nth scheduled call. If something slows down, several close runs of the task can happen in the period less than period. This can't happen in fixed-delay execution.

The Timer can be canceled by calling cancel method:

public void cancel()
The following is a small example of fixed-delay execution:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTaskDemo extends MIDlet implements CommandListener
{
    private Command exitCommand;
    private Timer timer = new Timer();
    private TextBox myScreen;
    private int seconds = 10;
    public void startApp ()
    {
        Displayable current = Display.getDisplay(this).getCurrent();
        if(current == null)
        {
            myScreen = new TextBox("TimerTask demo!", "You have 10 seconds to Exit...", 256, 0);
	    exitCommand = new Command("Exit", Command.EXIT, 1);
	    myScreen.addCommand(exitCommand);
	    myScreen.setCommandListener(this);
            Display.getDisplay(this).setCurrent(myScreen);
	    TimerTask counterTask = new TimerTask() {
		    public void run()
		    {
			myScreen.setString("Seconds left: " + Integer.toString(--seconds));
		    }
		};
	    TimerTask dismissTask = new TimerTask() {
		    public void run()
		    {
			notifyDestroyed();
		    }
		};
	    timer.schedule(counterTask, 1000, 1000);
	    timer.schedule(dismissTask, seconds*1000);
        }
    }
    public void pauseApp() {}
    public void destroyApp(boolean b) {}
    public void commandAction(Command c, Displayable d)
    {
	notifyDestroyed();
    }
}
This MIDlet displays the following screen first:
Initial screen of TimerTask MIDlet.
and schedules task counterTask to execute in a second and execute repeatedly after 1 second. It also defines second task dismisstask which is scheduled to destroy the MIDlet in 10 seconds. The counterTask changes the text of the TextBox to count down to 0:
Count down in TimerTask MIDlet.
When 0 is reached, the MIDlet is destroyed. You can also destroy it manually by pressing the Exit button (the Series 60 MIDP Concept SDK Beta 0.3.1 Nokia edition emulator has Close button instead and Exit is hidden in Options menu).

CLDC specification defines only the generic framework for connections, but no actual protocols. This is the role of profiles. MIDP profile v1.0 defines subset of the HTTP 1.1 protocol (interface HttpConnection) with GET, POST and HEAD methods.

Example of HttpConnection javax.microedition.io.HttpConnection interface is used for HTTP connection. The following example shows the sample usage of it.

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;
import java.io.*;
import javax.microedition.io.*;
public class HttpConnectionExample extends MIDlet {
    private Display display;
    String url = "http://www.janik.cz/";
    public HttpConnectionExample() {
	display = Display.getDisplay(this);
    }
    public void startApp() {
	try {
            getViaStreamConnection(url);
	} catch (IOException e) {
	}
    }
    public void pauseApp() {}
    public void destroyApp(boolean b) {}
    void getViaStreamConnection(String url) throws IOException {
        HttpConnection c = null;
        InputStream s = null;
        StringBuffer b = new StringBuffer();
        TextBox t = null;
        try {
	    c = (HttpConnection)Connector.open(url);
	    c.setRequestProperty("User-Agent", "UnknownAgentUsingNokia7650");
	    s = c.openInputStream();
	    int ch;
	    while((ch = s.read()) != -1) {
		b.append((char) ch);
	    }
	    t = new TextBox("Web page", b.toString(), 1024, 0);
        } finally {
	    if(s != null) {
		s.close();
	    }
	    if(c != null) {
		c.close();
	    }
        }
        display.setCurrent(t);
    }
}
This example shows the usage of HttpConnection interface and using its setRequestProperty property. We set the User-Agent HTTP header to the string "UnknownAgentUsingNokia7650" and it is shown as such to the server itself:
160.218.160.213 - - [...time...] \
    "GET /www.janik.cz/ HTTP/1.1" 200 689 "" "UnknownAgentUsingNokia7650"


Persistent storage is the only mechanism to permanently store data on the MIDP device. The implementation on MIDp devices is called Record Management System (RMS). RMS is not relational database. Records are byte arrays and it is the responsibility of the application (MIDlet) to understand the data stored there. Developers can pack anything they want to into the record using DataInputStream, DataOutputStream and ByteArrayInputStream, ByteArrayOutputStream. You can even store images in records.

Every record is identified by record IDs. Record IDs are unique in one record store (see below). First record's ID is 1, second's 2, ... If you delete record with ID 2, and add new one, record ID 2 is NOT reused.

What is it record store? It is a collection of records (with their IDs running up from 1). Each record belongs to exactly one record store and are accessed through their record store. Record store is named. The name is case sensitive and may contains up to 32 Unicode characters. Only the MIDlet who created the record store and other MIDlets from the same MIDlet suite can access record store. This means that each and every MIDlet suite in the device can create record store with the same name and they will be distinct. MIDP version 1.0 does not allow sharing record stores between MIDlet suites, but version 2.0 allows that. When the MIDlet suite is removed/uninstalled from the device, all record stores created by it must be removed too.

There is no locking in the record store API, but the implementation must ensure that all operations are atomic, synchronous and serialized. After each change, the record store is marked with timestamp (in the form of System.currentTimeMillis()) and version. If you want to track changes in the record store, you can also register listener and be notified after each change.

Actual implementation of record management system is inside javax.microedition.rms. MIDP devices provide limited data storage, but the specification requires at least 8k of non-volatile memory for persistent data. Applications can specify the minimal required persistent data storage in their JAD file in the MIDlet-Data-Size property. Devices may refuse to install the application if there is not enough space.

Really nice introductory article about RMS were written by Eric Giguere at Sun's website. Similar article was written by Qusay Mahmoud.

MIDlet Life Cycle Now, it is the good time to explore the life cycle of a MIDlet. MIDlets are executes in a virtual entity referred to as Application Management Software (AMS). As our picture describes, MIDlet can be in several phases (when already installed on the device):

  • Paused
  • Active
  • Destroyed
While creating the MIDlet, AMS calls its constructor. MIDlet constructor can't access the Display. When the application receives focus from the AMS (at the start or when returning from Paused state), startApp() is called. Application then should call appropriate startup page by Display.getDisplay(this).setCurrent() function (when starting up) or restore the page displayed before going to Paused state. When the application loose the focus, pauseApp() is called. No screen is displayed then, but all timers and tasks are still running. The application can setCurrent() the screen that should be presented when returning from Paused state. The function destroyApp(boolean unconditionally) is called when application is being destroyed. No access to Display, but the application can/should save its state to persistent storage. The application can request to not enter the Destroyed state by throwing MIDletStateChangeException but only if the unconditional flag is set to false.

MIDP specification contains the chapter about User Interface, using so called MIDP UI API. There are two APIs for two distinct ways of programming applications:

  • high-level API - it is designed to be as portable between devices as possible. Should your goal be portable application, prefer high-level API. While using this API, application doesn't have a way to control fonts, colors etc. This is controlled directly by the implementation. The application also can not use all events like in the low-level API.
  • low-level API - is provide for applications that need direct control of both displaying and user interaction (like keys, ...). Device specific API is also part of low-level API (like Nokia UI API). Applications using low-level API (should they be portable) should not use device specific APIs and when working with screen, should be independent of the screen size.
The Central object for UI API is Displayable. It is abstract class extending Object. Displayable can be placed on the Display thus shown to the user. It may have a title string, a ticker and zero or more commands and listener attached to it. The actual visual presentation is defined by its subclasses.

MIDP 1.0 defines two subclasses of Displayable:

  • Screen - is the parent of all high-level UI widgets: Alert, TextBox, List and generic Form.
  • Canvas is the direct screen representation used in low-level API.
The TextBox is UI widget (Screen in fact) that allows the user to enter and edit text in the widget. This UI widget has the following constructor:
  TextBox(String title, String text, int maxSize, int constraints)
where title is the title of the TextBox, text is its initial contents, maxSize identify the maximal number of character programmer wants it to contains (see below) and constraints allows the programmer to modify its behavior.

The maximal size of the text inside TextBox is device dependent so application should check getMaxSize() for valid sizes. It is not the size of the displayed text though. The displayed text may be shorter and it is device's responsibility to allow scrolling in it.

Constraints allow programmer to specify which value is to be entered. They are constants defined in the class TextField:

  • ANY
  • EMAILADDR
  • NUMERIC
  • PHONENUMBER
  • URL
  • DECIMAL
TextBox in the emulator The following table shows the sample TextBox code for the TextBox on this image. The title is displayed twice on the screen, but the real device displays title only once (at the top of the screen). Ticker is running from the right to the left side of the screen just below the title. The application can't set its direction nor speed, it is decided by the implementation. If there are linebreaks in the ticker text, emulator removes them, but the real device uses empty boxes - so do not use them. Several screens can reuse the same ticker (see setTicker() method of Screen). The modifier TextField.ANY allows any text to be typed. If you change it to TextField.PASSWORD, only starts will be displayed instead of the actual text.
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class UITextBox extends MIDlet implements CommandListener
{
    private Command exitCommand, showCommand;
    private TextBox uiTextBox;
    public UITextBox() {}
    public void startApp()
    {
        Displayable current = Display.getDisplay(this).getCurrent();
        if(current == null)
        {
            uiTextBox =
		new TextBox("UITextBox title",
			    "The initial contents of the uiTextBox", 256, TextField.ANY);
	    exitCommand = new Command("Exit", Command.EXIT, 1);
	    showCommand = new Command("Show the text", Command.SCREEN, 1);
	    uiTextBox.addCommand(exitCommand);
	    uiTextBox.addCommand(showCommand);
	    uiTextBox.setCommandListener(this);
	    Ticker uiTicker = new Ticker ("This is a ticker!");
	    uiTextBox.setTicker(uiTicker);
            Display.getDisplay(this).setCurrent(uiTextBox);
        }
    }
    public void pauseApp() {}
    public void destroyApp(boolean b) {}
    public void commandAction(Command c, Displayable d)
    {
	if (c == exitCommand) {
	    destroyApp(false);
	    notifyDestroyed();
	} else if (c == showCommand) {
	    // This is only useful for the emulator.
	    System.out.println(uiTextBox.getString());
	}
    }
}

-----


Posted by Pavel | Permanent link | File under: Mobile technologies