Showing posts with label J2ME. Show all posts
Showing posts with label J2ME. Show all posts

Friday, May 14, 2010

Mobile thick clients vs thin clients

For many application developers, the fastest, easiest way to introduce a mobile solution was to "chop down" an existing Web-based application. Users that had a device with a browser could then access the applications. However, because the resulting applications were not designed for the navigation capabilities of a mobile device or the smaller bandwidth, the user experience suffered. These problems can be solved by using a thick client instead of a thin client.

With a thin client, there is nothing running on the device except the presentation. All the content is on the host. The data, along with the rules to display it, are sent down and rendered on the local machine. Everything is done on the server; every request requires going back to the host. With a thick client, however, the presentation engine is on the local machine, which does the work.

The need for thick clients is driven by the complexity of the information and the presentation demanded by
mobile users. Mobile users, too, want robust applications and a good user experience. Years ago with the
PC, users went to a Web site and got straight HTML. PC users said, "That's not good enough." Then came
dynamic HTML, Java applets, Flash, and great plug-ins.

It depends on
  • what application you want to build
  • which audience you want to target
  • Operating cost
  • Billing and revenue models
Thin clients are good for:
  • Displaying regularly changing information eg. news.
  • Casual one-off browsing, where the user is unlikely to ever need to come back and benefit from having any sort of state remembered, and not being able to access any content is not a serious problem (due to lack of signal, etc).
  • Very changeable data with simple display requirements that change unpredictably over time, with minimal data entry requirements.
  • Situations where reliable network connections are guaranteed – either fast connections, or very small nuggets of content that can be found very quickly.
Thick clients are good for:
  • Repeated user experiences – local secure caching can reduce data entry, always a significant pain point on mobile.
  • Intelligent data delivery can reduce costly data overheads whilst providing faster responses for the user for known types of data set.
  • High interactivity and improved user experiences with many potential data visualisation models and on-client validation (minimising round trip requirements to the server, which cost money and time).
  • Improved branding around content, which only ever has to be downloaded once rather than at the start of ever session – handsets rarely dedicate persistent storage to browser caches so ever visit to a branded site reloads many Kbs of images, CSS etc.
  • Real security, guaranteed – there are known issues with Wap security which can even affect Wap2 browsers running through legacy APNs.
  • Offline access – content can be stored locally to browse even when there is no signal (eg. Tube maps), data entry can be performed when required and then submitted to a server asynchronously etc.
  • Data roaming can be incredibly expensive so for content like travel guides designed to be read abroad, or interactive services for which Java can choose to use SMS instead of GPRS, there are big cost savings to be had.
  • Precise optimal rendering of certain types of content, for example barcodes (used for ticketing etc) which would be useless if the handset decided to rescale them badly as can happen when displaying MMS messages or images in browsers.
First is the ability to do local processing and local data storage. With a thin client, modifying one item could require making several trips back to the host. And, because the bandwidth in the wireless world is so small, bringing pages down is a long, arduous task. A thick client, however, enables mobile users to work offline with the local data that is brought down; everything is done locally.

The advantage of a thick client's local processing ability can be seen when a user makes a mistake while entering data. With a thin client, the user would be prompted again, requiring another trip. With a thick client, you could use an "if" statement to determine if the information is correct before sending it to the host, which saves time.

Thursday, July 9, 2009

APIs in J2ME

General APIs
The core APIs are defined by the underlying Connected Limited Device Configuration.

javax.microedition.io

Contains the Java ME-specific classes used for I/O operations.

javax.microedition.lcdui

Contains the Java ME-specific classes used for the GUI. LCDUI has a simple screen based approach where a single Displayable is always active at a time in the application user interface. LCDUI API provides a small set of displayables common in mobile device user interfaces: List, Alert, TextBox, Form and Canvas. For all displayables the device MIDP implementation has control over the presentation and layout of the displayable. Canvas is a low-level graphics surface for which an application has full control over what is rendered to it, although normally some space is reserved for system areas like screen title and indicators common in mobile device UIs. Since MIDP 2.0, Canvas also supports a full-screen mode that allows to make full screen graphics, which is especially useful for games.
LCDUI also has quite unique approach of abstract operations, called Commands. The placement of commands added to a displayable is completely up to the device implementation of this toolkit. The application programmer uses API specified command types to indicate the usage or purpose of the command in application user interface. Common types are BACK, EXIT, ITEM, SCREEN. The idea of the command abstraction is to make applications more portable between various different mobile device. Application developers should use the command types properly to indicate the purpose of an operation, and device implementation then places the operation to the common location for a given type in device's specific user interface style. This may be e.g. a specific key, like "a back navigation key" for BACK commands or button on screen.
The term LCDUI was actually a joke in JCP Expert Group that created it. It has not been opened up in the MIDP specifications but stands for Limited Capability Device User Interface. The joke was that no-one else really knows what it stands for. Then later the Programming Wireless Devices with the Java 2 Platform, Micro Edition book gave this term out.
Other common definitions have appeared. "Liquid Crystal Display User Interface" would reflect the fact that mobile phones normally use LCD displays; however, the API is not specifically tailored to this particular display technology. It is also said that "LCD UI" stands for "lowest common denominator" due to the fact the specific UI has simplest possible design.

javax.microedition.rms

Provides a form of persistent storage for Java ME. It's like a database for the mobile device.
"Record Store"(class) is used to store the Data: RecordEnumeration(Interface) , RecordComparator(Interface), RecordFilter(Interface), are used to apply user queries for sorting,filtering the data of all the data present; and comparison of contents of two or more RecordStores is done by these Interfaces.Data is stored and must be retrieved from the RecordStore using a ByteArray.(i.e; data is stored in Bytes(string.getBytes() and stored in ByteArray Byte a[])

javax.microedition.midlet

Contains the base classes for Java ME applications.

Specialized APIs added in MIDP 2.0

MIDP 2.0 saw the introduction of gaming and multimedia APIs and some optional packages.

javax.microedition.media

Contains the base classes of the multimedia playback. These are approximately a subset of the JSR 135 Java Mobile Media API.

javax.microedition.lcdui.game

A gaming API aimed at simple 2D sprite based games.

javax.microedition.pki

Authenticate APIs for secure connections.

Optional JSRs

The following JSRs are not part of MIDP (1.0 or 2.0) but provide extra functionalities on some handsets. However, there is no guarantee that a MIDP2.0 handset implement such APIs

javax.microedition.messaging

Wireless messaging API (optional), for sending SMS and MMS messages.

javax.microedition.pim

Personal information management API (optional), access the device's Address Book , to-do List, Calendar.

javax.microedition.io.file

The File Connection Optional Package (FCOP) is one of two optional packages defined by JSR 75 through the Java Community Process. The FileConnection API specified in JSR 75 gives access to the local file systems on devices like PDA. In order to overcome security issues MIDlet needs to include requested file permission in its JAD file under MIDLet-Permission property.

Development Tools

There are several different ways to create MIDP applications: Code can be written in a plain text editor, or you can use a more advanced IDE such as NetBeans, IntelliJ (with bundled Java ME plugin), or Eclipse (with plugins such as EclipseME) which has a user interface for graphically laying out any forms you create, as well as providing many other advanced features not available in a simple text editor.

Noteworthy Limitations of MIDP 1.0

  • MIDP 1.0 has no active rendering APIs
  • MIDP 1.0 has no support for direct access to image pixels (RGB data)
  • MIDP 1.0 has no support for full screen mode
  • MIDP 1.0 has no support for audio
  • MIDP 1.0 requires only HTTP support
  • MIDP 1.0 cannot query key status (although key events are supported)
  • The specifications are not always clear, leading to differences in implementations
  • Some limitations may be avoided by using a vendor-specific API or MIDP 2.0, which obviously reduces the portability of the application

Monday, April 27, 2009

General Coding Tips

Avoid the Object.getClass() Method

Avoid using the Object.getClass() method, because it is not efficient and it produces garbage (the Class object) that is never collected. Also avoid using the example.class literal. Behind the scenes, this generates Class.forName(“Example”).

Writing Efficient Loops

You should always factor loop invariant code out of a loop, as in the following example:

    for(int i = 0; i < >
...

}

This code results in vector.size() getting called each time through the loop, which is inefficient. If your container is likely to have more than one element, it is much faster to assign the size to a local variable. In addition, this example using pre-increment (++i) results in smaller code than post-increment (i++). The optimized code appears below:

     int size = vector.size();
for(int i = 0; i < style=""> ...
}

Alternatively, if the order in which you iterate over items is not important, you can iterate backward. Iterating backward avoids the extra local on the stack, and the comparison is also faster, as the following example illustrates:

for(int i = vector.size() - 1; i >= 0; --i) {

...

}



Optimizing Subexpressions

If you ever use the same expression twice, do not rely on the compiler to optimize it for you. Use a local variable, as in the following example:

one(i + 1); two(i + 1); // Avoid
int tmp = i + 1; 
one(tmp); 
two(tmp); // Prefer

Avoid java.util.Enumeration
Avoid using java.util.Enumeration unless you are using it to hide data (in other words, returning an Enumeration of data rather than the data itself). The following example shows a typical use of an Enumeration:

for (Enumeration e = v.elements(); e.hasMoreElements();) {
   o = e.nextElement();
   ...
}

Asking a vector or hash table for an Enumeration object creates unnecessary garbage and is slow. Instead, you can iterate over the elements yourself, as in this example:

for(int i = v.size() - 1; i >=0; --i) {
   o = v.elementAt(i);
   ...
}

If the vector might be modified by another thread, you must synchronize the iteration:

synchronized(v) {
   for(int i = v.size() - 1; i >=0; --i) {
      o = v.elementAt(i);
      ...
   }
}

In Java 2 Platform, Standard Edition (J2SE), you would use an Iterator for this, but Iterators are not available in Java 2 Platform, Micro Edition (J2ME).

Returning null
If you are writing a public method that returns an object, it should never return null unless the following occurs:

  • a null is expected during normal program operation.
  • the javadoc @return parameter states that null is a possible return value.

If a null is not normally expected, then the method should throw an appropriate exception, which forces the caller to deal with the problem explicitly. The caller is not expected to check for a null return value, unless the documentation specifies otherwise.

Passing null into Methods
Do not pass null parameters into an API method unless the API Reference documentation explicitly states that the method supports them.

Passing null into a Constructor
To avoid ambiguity when passing a null into a constructor, you should use this form:

new someObject ((Object)null);

A class can have two or more constructors, such as SomeObject(String) and SomeObject(Object), where passing in a null does not identify which constructor to use. As a result, the compiler reports an error. Not all supported constructors necessarily appear in the API Reference documentation, because some constructors are for internal use only. By casting the null to the appropriate object, you indicate precisely which constructor the compiler should use. This practice also ensures forward compatibility if later releases of the API add new constructors.

Optimizing Division Operations
Division operations are slow on the BlackBerry Wireless Handheld because its processor does not have a hardware divide instruction. When you write code that divides a positive number by two, you should use “shift right by one” instead. The following example illustrates this:

midpoint = width / 2; //avoid this
int = width >> 1; //prefer this

This does not work for negative values. Only use “shift right” (>>) when you know you are dealing with a positive value. It does not work for negative values.

Managing Garbage Collection
Avoid calling System.gc() to perform garbage collection. On a full handheld, this could take two seconds. Let the virtual machine (VM) collect garbage automatically.


Casting Using instanceof
It is more efficient to use instanceof instead of classCastException to evaluate whether a cast succeeds. Here is an example of using a try/catch block to catch the classCastException:

try {
   (String)x.whatever();
} catch(ClassCastException e) {
   // something else
}

Alternatively, you can use instanceof operator:

if(x instanceof String) {
   (String)x.whatever();
} else {
   // something else
}

Using instanceof is faster. The only time you should use the try/catch block is when the failure of the cast is an exceptional circumstance. The BlackBerry Java Development Environment (JDE) compiler and the VM are optimized to perform only one class check in the first block of code. This is true of any code in which the cast is run immediately following a branch determined by an instanceof check. Always perform the cast immediately after the branch so that the optimization can be performed.

Using Longs for Unique Identifiers
You should use longs rather than strings for unique constants, such as globally unique identifiers (GUIDs), hash table keys, and state/context identifiers. So that unique identifiers remain unique across all third-party application developers, you should use randomly generated keys based on a hash of some string. In the input string, you should include enough information to make it unique.

Wednesday, April 9, 2008

Getting the IMSI number from mobile devices

An International Mobile Subscriber Identity, or IMSI [im-zee], is a unique number associated with all GSM and Universal Mobile Telecommunications System (UMTS) network mobile phone users. It is stored in the Subscriber Identity Module (SIM) inside the phone and is sent by the phone to the network. It is also used to acquire other details of the mobile in the Home Location Register (HLR) or as locally copied in the Visitor Location Register. In order to avoid the subscriber being identified and tracked by eavesdroppers on the radio interface, the IMSI is sent as rarely as possible and a randomly generated TMSI is sent instead.

The IMSI is used in any mobile network that interconnects with other networks, in particular CDMA and EVDO networks as well as GSM nets. This number is provisioned in the phone directly or in the R-UIM card (a CDMA analogue equivalent to a SIM card in GSM)

An IMSI is usually 15 digits long, but can be shorter (for example MTN South Africa's IMSIs are 14 digits). The first 3 digits are the Mobile Country Code, and is followed by the Mobile Network Code (MNC), either 2 digits (European standard) or 3 digits (North American standard). The remaining digits are the mobile subscriber identification number (MSIN) within the network's customer base.

The IMSI conforms to the International Telecommunication Union (ITU) E.212 numbering standard.

Example

IMSI:404400021281732

MCC 404 India
MNC 40 Airtel
MSIN 0021281732


Code:

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public class MobileProperties extends MIDlet implements CommandListener {
Form f = null;
Display dis = null;
Command ok = null;
Command exit = null;

public MobileProperties () {
dis=Display.getDisplay(this);
f = new Form(" Mobile Details ");
ok =new Command(" Ok",Command.OK,1);
exit =new Command(" Exit",Command.EXIT,2);
f.addCommand(ok);
f.addCommand(exit);
f.setCommandListener(this);
}

public void startApp(){
try {
f.append(" Nokia IMSI : " + System.getProperty("com.nokia.mid.imsi")+"\n");
f.append(" IMSI : " + System.getProperty("IMSI")+"\n");

} catch(Exception e) {
f.append("Exception :"+e);
}
dis.setCurrent(f);
}

public void pauseApp() {
}

public void destroyApp(boolean unconditional) {
}

public void commandAction(Command c, Displayable s) {
if (c == ok) {
destroyApp(true);
notifyDestroyed();
} else if (c==exit) {
destroyApp(true);
notifyDestroyed();
}
}
}

Getting the IMEI number from mobile devices of different manufacturers

International Mobile Equipment Identity (IMEI) is used to identify valid devices connected to GSM and UMTS network. This number can be accessed from a mobile phone by dialing *#06# on the keypad. IMEI is commonly use by software developers as part of software protection scheme to prevent it from being pirated.

JavaME developers however suffers from a drawback because MIDP/CLDC specification does not include an API to obtain IMEI from mobile devices. However there are few phone manufacturers included this functionality through System.getPropery() calls. Here's how to get IMEI number from mobile devices of different manufacturers

Manufacturer Argument
Nokia Mobiles System.getProperty("com.nokia.mid.imei”);
Sony-Ericsson Mobiles System.getProperty("com.sonyericsson.imei");
Motorola Mobile System.getProperty("IMEI");
Motorola Mobile System.getProperty("com.motorola.IMEI");
Samsung Mobiles System.getProperty("com.samsung.imei");
Siemens Mobiles System.getProperty("com.siemens.imei");


Code:

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public class MobileProperties extends MIDlet implements CommandListener {
Form f = null;
Display dis = null;
Command ok = null;
Command exit = null;
String s1= null;

public MobileProperties () {
dis=Display.getDisplay(this);
f = new Form(" Mobile Details ");
ok =new Command(" Ok",Command.OK,1);
exit =new Command(" Exit",Command.EXIT,2);
f.addCommand(ok);
f.addCommand(exit);
f.setCommandListener(this);
}

public void startApp(){
try {
if ((s1 = System.getProperty("phone.imei")) == null || s1.equals("")) {
s1 = System.getProperty("com.nokia.mid.imei");
}
if (s1 == null || s1.equals("")) {
s1 = System.getProperty("com.sonyericsson.imei");
}
} catch(Exception e) {
f.append("Exception :"+e);
}
dis.setCurrent(f);
}

public void pauseApp() {
}

public void destroyApp(boolean unconditional) {
}

public void commandAction(Command c, Displayable s) {
if (c == ok) {
destroyApp(true);
notifyDestroyed();
} else if (c==exit) {
destroyApp(true);
notifyDestroyed();
}
}
}

Getting a random number from range


If you need to get a random number between X and Y, you should use some mathematical pattern using the Math Class and some calculus.

You can use this quick method to get the random number:

public int getRandomNumber(int min, int max) {
Random rnd;
rnd = new Random();
return min + Math.abs(rnd.nextInt()) % (max - min);
}


Another Method

Using the below code you can generate a 4 digit random integer.
int random4Digit = (int) (9 * Math.random())
+ (int) (9 * Math.random())
+ (int) (9 * Math.random())
+ (int) (9 * Math.random());

You can generate a 5 digit random int, by adding one more '(int) (9 * Math.random())'

Installing an application on the Phone's Game menu

By default in Nokia mobiles, when a user install a Java ME application, it is installed in the default folder on in "Applications" folder. If you want to suggest a Nokia device to install the JAR file in the Game menu of the mobile device, you have to insert this property in the JAD file of your game:
Nokia-MIDlet-Category: Game

Detecting if a Class/Package is available on the phone

You know Java ME has many optional packages that phones must have preinstalled over MIDP and CLDC. So, how can you compile one only code that detects on the fly if some class or API is available?

We can use the dynamic instantiation method, like this:

Code:
boolean MMAPIAvailable;
try {
// Try to instantiate a class using a string as the Class name
// so, the SDK without the API can compile the application
Class.forName("javax.microedition.media.Player").newInstance();
// If the next code is executed, then the API is available
MMAPIAvailable = true;
} catch ( ClassNotFoundException e) {
MMAPIAvailable = false;
}

Blocking the screen saver using J2Me

If your application doesn't demand constant key presses, after a while the screen saver on a J2ME phone will start automatically.

To make sure that the display light is turned on, the setLights method should be called before the screen saver is started and this must be done in a loop since the screen saver is not disabled just interrupted.

BacklightWorkaround.java
import com.nokia.mid.ui.DeviceControl;
import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

public class BacklightWorkaround extends MIDlet {

private SimpleCanvas canvas;

/**
* Keeps the backlight on by repeatedly setting
*/

class LightThread extends Thread {
public void run() {
while(true){

DeviceControl.setLights(0, 100);
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}

private class SimpleCanvas extends Canvas implements CommandListener{
private Command exitCmd;
private MIDlet midlet;

public SimpleCanvas(MIDlet midlet) {
this.midlet = midlet;
exitCmd = new Command("Exit",Command.EXIT, 1);
addCommand(exitCmd);
setCommandListener(this);
}
public void paint(Graphics g) {
g.drawString("Let there be light.", 0, 0, Graphics.LEFT|Graphics.TOP);
}

public void commandAction(Command command, Displayable displayable) {
if(command == exitCmd){
midlet.notifyDestroyed();
}
}
}

public void startApp() {
if(canvas == null){
canvas = new SimpleCanvas(this);
new LightThread().start();
}

Display.getDisplay(this).setCurrent(canvas);
}

public void pauseApp() { }

public void destroyApp(boolean unconditional) { }
}

Adding contacts using JSR 75

Following code snippets show how to add contacts using JSR 75.

PIMWrite class
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import java.util.*;

public class PIMWrite extends MIDlet implements CommandListener
{
private Command PIMWriteCmd,exitCommand,generateName;
PIMImpl pimImpl;
private static Random random = new Random();
static String[] names;

public static Display display;
public static Form result;
private String sp,si,s1;
private String[] strJSR = new String[12];
private long l;
int noOfContacts;

TextField textfield = new TextField("Enter No of Contacts: ","",3,TextField.NUMERIC);


/*Constructs an Object
*/

public PIMWrite() {

display = Display.getDisplay(this);

PIMWriteCmd = new Command("PIMWrite", Command.SCREEN, 0);


exitCommand = new Command("Exit", Command.SCREEN, 0);

result=new Form("Write Contacts To PIM");
result.append(textfield);
System.out.println(" noOfContacts: "+noOfContacts);

result.addCommand(PIMWriteCmd);
result.addCommand(exitCommand);
result.setCommandListener(this);

}

public void startApp() throws MIDletStateChangeException {
display.setCurrent(result);

}

public void pauseApp() {
}

public void destroyApp(boolean unconditional) {
}

public void commandAction(Command c, Displayable s)
{
if (c == exitCommand)
{
destroyApp(false);
notifyDestroyed();
}

else if(c == PIMWriteCmd)
{
noOfContacts = Integer.parseInt(textfield.getString());
createConatactName();
System.out.println(" noOfContacts: "+noOfContacts);
//Start the PIM thread and write contacts .
pimImpl = new PIMImpl();
pimImpl.start();


}
}

public void createConatactName()
{
names = new String[noOfContacts];
for (int i = 0; i < style="color: rgb(102, 204, 102);">){
names[i] = PIMWrite.generateName()+" "+PIMWrite.generateName();
System.out.println(" Names :"+ names[i]+ " i "+i);
}
}


public static String generateName()
{
return generateName(4, 7, true);
}


/** This method generates the random names
*
* @param minLength Minimum length of name
* @param maxLength Max length of name
* @param capitalize Captilize
* @return name
*/

public static String generateName(int minLength, int maxLength, boolean capitalize)
{

int limit = (random.nextInt(maxLength - minLength + 1)) + minLength;
StringBuffer s = new StringBuffer(limit);
for (int i = 0; i < style="color: rgb(102, 204, 102);">)
{
char c = (char)((random.nextInt(26)) + 'a');
s.append(c);
}
if (capitalize && (s.length() > 0)) s.setCharAt(0, Character.toUpperCase(s.charAt(0)));
return s.toString();
}
}
PIM Implementation class

/**
* PIM Implementation class
*/

import javax.microedition.pim.*;
import java.util.*;
import javax.microedition.lcdui.*;
import javax.microedition.lcdui.Command;

public class PIMImpl extends Thread
{
static Alert check;

StringItem si;
//----------------------------------------Phone Book---------------------------------

int noOfRecords;
public static boolean pimTemp = false;
Random randPh = new Random();


public PIMImpl()
{

}

public void run()
{
writeData();
}



public synchronized void writeData()
{

String ph[] = new String[PIMWrite.names.length];
for (int i=0;inames.length ;i++ )
{

String r = Long.toString(randPh.nextLong());
if(r.startsWith("-"))
{
r = r.replace('-','9');
}
ph[i] =(r.length()>10)?(r.substring(0,10)):(r);



// System.out.println(" PH :"+ph[i] +"i:"+i);
}


int tc = 0;
PIM pim;
try{

ContactList contacts = null;
ContactList conT = null;
pim = PIM.getInstance();
try {

contacts = (ContactList) pim.openPIMList(PIM.CONTACT_LIST, PIM.READ_WRITE);
} catch (PIMException e) {
// An error occurred
return;
}
for(int i=0;inames.length;i++)
{

Contact contact = contacts.createContact();
String[] name = new String[contacts.stringArraySize(Contact.NAME)];

// System.out.println("i = "+i);
if (contacts.isSupportedField(Contact.TEL))
{
contact.addString(Contact.TEL, Contact.ATTR_MOBILE, ph[i]);
}

if (contacts.isSupportedArrayElement(Contact.NAME, Contact.NAME_GIVEN))
name[Contact.NAME_GIVEN] = PIMWrite.names[i];
contact.addStringArray(Contact.NAME, PIMItem.ATTR_NONE, name);


try {
contact.commit();
} catch (PIMException e) {
// An error occured
}
PIMWrite.result.deleteAll();
String msg=" Contacts Adding :"+i;
si = new StringItem("",msg);
PIMWrite.result.append(si);

}
check = new Alert("Added","Added ",null,AlertType.CONFIRMATION);
check.setTimeout(Alert.FOREVER);
PIMWrite.display.setCurrent(check);

try {
contacts.close();
} catch (PIMException e) {
}

}catch(Exception e){
String er = e+" ; tc="+tc;
check = new Alert( "Response",er,null,AlertType.CONFIRMATION );
check.setTimeout(Alert.FOREVER);

PIMWrite.display.setCurrent(check);
}
// return true;

}

}

Tuesday, April 8, 2008

Reading contacts from Mobile using JSR 75

The below Midlet explains how to read the contact names and numbers from the Phonebook using JSR 75
PIMMidelt.java
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class PIMMidelt extends MIDlet
{
ReadPIM readPim;
Display display;

public void startApp()
{
display = Display.getDisplay(this);
readPim = new ReadPIM(this);
display.setCurrent(readPim);
}
public void pauseApp()
{
}
public void destroyApp(boolean uc)
{
}
}
ReadPIM.java
import javax.microedition.lcdui.*;
import javax.microedition.pim.*;
import java.util.*;
import java.io.*;
public class ReadPIM extends Form implements Runnable,CommandListener
{
PIM pim;
PIMList pimlist;
Contact contact=null;
Enumeration enumeration;
PIMMidelt midlet;

String contactName="";
String contactNo="";


StringItem name;
StringItem telno;
Thread thread=null;
Command exitCmd = new Command("Exit",Command.EXIT,1);

public ReadPIM(PIMMidelt midlet)
{
super("Reading contacts");
this.midlet = midlet;

pim = PIM.getInstance();

thread = new Thread(this);
thread.start();
addCommand(exitCmd);
setCommandListener(this);

}

public void run()
{
readContacts();
}

public void readContacts()
{
String[] lists = pim.listPIMLists(pim.CONTACT_LIST);
for (int i = 0; i < style="color: rgb(0, 102, 0);">length; i++)
{
try{
pimlist = pim.openPIMList(pim.CONTACT_LIST,pim.READ_WRITE);
}catch(Exception e){}


try{
enumeration = pimlist.items();
}catch(Exception e){}

while (enumeration.hasMoreElements())
{
contact = (Contact)enumeration.nextElement();

try{
if(pimlist.isSupportedField(Contact.FORMATTED_NAME)&& (contact.countValues(Contact.FORMATTED_NAME) >0))
{
contactName += contact.getString(Contact.FORMATTED_NAME,0) +"\r\n";;
System.out.println("COntact name:"+contactName);
}
}catch( Exception e){}

int phoneNos = contact.countValues(Contact.TEL);
try{
if(pimlist.isSupportedField(Contact.TEL) &&(contact.countValues(Contact.TEL) >0))
contactNo += contact.getString(contact.TEL,0) +"\r\n";
System.out.println("contact No :"+contactNo);
}catch( Exception e){}

}

name = new StringItem("Name",contactName);
telno = new StringItem("No",contactNo);
append(name);
append(telno);

}
}

public void commandAction(Command c , Displayable d) {
if(c == exitCmd) {
midlet.destroyApp(true);
midlet.notifyDestroyed();
}
}
}