Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Mobile

Programming Mobile Phones


Sep01: Programming Mobile Phones

Panos is a fellow at WebMD Corp. He can be reached at [email protected].


Until recently, most mobile phones had a single input device — the keypad. This was fine until you got a new phone and had to reenter all your phone numbers. Worse yet was every time a number changed, you had to make changes in both your desktop contact manager and mobile phone. Fortunately, this is changing. Today's mobile phones come with everything from Infrared ports and serial cables, to Bluetooth wireless support. In addition, phone manufacturers are providing connectivity SDKs and standardizing on APIs.

In this article, I'll present one approach for updating contact information for my mobile phones. In this case, I download selected Outlook contacts from my PC running Outlook 2000 to my Nokia 8260 Series mobile phone. Although the solution is based on the Nokia PC Connectivity Kit 2.0, it should work with most 6xxx, 7xxx, and 8xxx Nokia Series phones. I implemented the solution using Microsoft's Visual J++.

The application uses the Infrared port of the PC to connect to a Nokia phone. If this fails, an error message pops up and the application exits. If the application successfully connects to the mobile phone, it displays a frame with two tabs. As Figure 1 illustrates, the first tab shows the capacity of the phone. The second tab lets users select an Outlook contacts folder, then download selected contacts from Outlook to the mobile phone. Since the phone's capacity is only a few hundred contacts and the Outlook folder's capacity many more, I had to devise a strategy to download only selected contacts.

One feature of the Outlook contact manager is that each contact can be assigned to several categories. Outlook comes with a number of built-in categories. In addition, users can create more. The Nokia phone contact manager supports "caller groups," a notion similar to categories. Each contact can only be in one caller group. The default caller groups are Family, Business, Friends, VIP, and Other. What's nice about caller groups is that each one is associated with a customizable logo and ringing tone. So when a friend calls, the phone behaves differently than when a family member does. The application only downloads the contacts that are assigned to a category that corresponds to a calling group. Each contact is assigned to the corresponding caller group. For instance, if you want to download the numbers of your friend "Bob Smith" to the phone, then assign his contact entry to the Outlook category "Friends."

Of course, the mobile phone's smaller screen shows only 14 characters without scrolling. Since most names are longer than that, the application truncates the last and first name to seven and four characters before downloading them to the phone. So while "Bob Smith" would not change at all, a longer name would; for instance, my name would appear as "Kougiou Pano," shorter than normal but still legible and easy to find. The remaining two characters are used to indicate if it is a home, mobile, or business number. For each contact, the business, home, and mobile phone numbers are downloaded. So the entry for my mobile phone number appears as "Kougiou Pano M" — 14 characters.

U.S. and Canadian phones are expected to be the 10-digit number (three-digit area code + seven-digit number). International numbers are expected to start with the "+" sign, followed by the country code, area code, and number. Besides these rules, the program strips all nondigit characters (parenthesis, spaces, dashes, and so on) to work accurately.

The Nokia PC Connectivity SDK

The Nokia PC connectivity kit, available at Nokia Developer's web site (http://forum.nokia.com/), is a collection of COM objects that let you connect to and program a Nokia mobile phone from a Windows application. The objects abstract you from the low-level details of the connection (Infrared versus serial line, and so on) and the idiosyncrasies of each phone.

The SDK supports a collection of object models, including those to support access to the settings of the phone, short messaging subsystem, phonebook, calendar, and WAP adapter. For my application, I only used the phonebook access object model. The phonebook object model provides access to the contacts, caller groups, and their associations. Again, a caller group (like Business or Friends) lets the phone recognize an incoming call and ring in a different way. It allows creating contacts, deleting contacts, and assigning them to memory locations. Each contact associates a name with a number and caller group. A timestamp associated with each contact is also kept. The timestamp could be used by sophisticated applications to synchronize the phone with a personal information manager (PIM).

The SDK supports COM, so you can write a program in languages such as Visual Basic, C++, and VJ++, Microsoft's version of Java. However, the object model does not support automation, so access from scripting languages such as Javascript, VBScript, and Perl is not possible. Listing One shows how to create a Phonebook object, then retrieve the versioning information.

The Outlook Object Model

One feature of every application in the Microsoft Office suite is that it provides an object model. The object model can be used to script or automate the application. Scripting the application is equivalent to driving an application through a program. For instance, instead of opening the application and using the GUI to add a new contact, you can write a program that performs the function.

Being an Office application, Outlook could not be an exception to the automation rule. In fact, security experts have criticized the automation of Outlook's contact list because malicious viruses have used it to find the e-mails of a user's contacts, then spread the virus. The documentation of Outlook's object model is part of the Office and MSDN documentation (http://msdn.microsoft.com/). The run time is installed along with the installation of Outlook.

The main object is the Application object. It can be created through the Outlook.Application progid. Through the Application object, the Outlook folders can be accessed by name. A folder can be a contacts folder, calendar folder, or a folder with e-mail messages. Contacts folders contain ContactItem's objects. A ContactItem object has numerous properties, similar to those that appear in the GUI of Outlook. Java code that opens a Contacts folder and copies certain contacts into a Java hash table is available electronically; see Resource Center, page 5.

Using Visual J++

Visual J++, part of Microsoft's Visual Studio family of IDEs, brings the rapid application development concepts of Visual Basic and PowerBuilder to Java. Furthermore, it enhances the definition of the relationships among controls in a form. For instance, you can dock a control to the top of the form. As the form resizes, the control stays glued to the top of the form. Also, there is no more hidden code. Any manipulation of the form at design time generates Java code. This is great for debugging and troubleshooting. In addition, if you work in a team environment where multiple developers might edit the same form, merging the changes is much more straightforward than it is in VB.

On the downside, the next version of Visual Studio will not include the Visual J++ IDE. However, Visual J++ IDE features will likely make it to Visual Stdio.Net and its support for C#.

Accessing COM objects from Visual J++ requires importing the type libraries into the environment. When you do this, the IDE generates Java classes that bridge between the COM objects and your Java code in a type-safe manner. A class is generated for every object in the library, and an interface is generated for each interface or enum.

The Application Design

The GUI of the application is based on two forms: The main form (see Figure 1) and a dialog box that appears when communication with the device takes place. The main form has two tabs. The first tab demonstrates the memory capabilities of the device and is implemented using a Data Grid control. A recordset is used to set the values of the grid from the responses of the device. Recordsets are part of Microsoft's data access APIs; they represent an array with named columns, where each column might have a different data type. Listing Two is Java code that initializes the columns of the recordset, fills the recordset with information from the device, and associates the device with the data grid.

The functionality of the application is implemented in the form of Command objects. All Command objects inherit from an object called Command and implement the interface ICommand. As part of the contract of the ICommand interface, all Command objects implement a method called executeInner() that performs the operation. For instance, take a closer look at the ContactGroupsCommand in Listing Three. The command retrieves the names of the caller groups that the device knows about. Users instantiate the object passing a Nokia PhoneBook object as a parameter. They then call the execute() method. The execute() method is implemented by the Command object. It retries in case of failure for a few times and sets certain flags that indicate if the command is completed, if it was successful, or whatever. It then calls the executeInner() method implemented by the ContactGroupsCommand object. If the method does not throw any exceptions, the results can be collected through the getGroups() method.

A lot of GUI applications suffer from interactivity problems. For certain periods, while a command is executed, users cannot interact with the application. To avoid this, my application executes commands in a separate thread. The thread runs the code in the CommandsQueue object. When users request an action through the GUI, the appropriate Command object is created and added to the queue. The thread then asynchronously executes the command.

A number of flags that are passed through the addCommand() method dictate the behavior of the execution. The flag SYNCHRONOUS dictates that the method will return only when the operation completes. The flag DIALOGBOX dictates that a dialog box informing the user what is going on should be shown while the operation is executing. When the method returns, the caller should check for the status of the command (completed(), failed(), and so on) before it proceeds with the collection of the results. To customize the appearance of the dialog box for each command, the framework calls the method getName() on the Command object. Each Command object returns a different String that is displayed in the dialog box. For instance, Listing Four shows what is happening when users click the Download button. As you can see, two commands are executed. The first command erases all the contacts from the mobile device. The second command downloads the appropriate contacts to the phone.

The DownloadContactsCommand is the only part of the code that knows how to communicate with the PIM, application. So if you were to change the program to work with some other PIM, you would only need to add a similar class for your own favorite PIM. The class creates a Contacts object, passing the name of the Outlook Contacts folder and the name of the caller groups as input. The Contacts object uses this information to find all the appropriate contacts, format names and numbers, and add them to a table. The DownloadContactsCommand then iterates over the contents of the table and adds the entries to the mobile device as shown in Listing Five.

Conclusion

Mobile phones will soon be shipping with software to synchronize contact lists and other personal information with popular PIMs. This article gives you an idea of what technologies such tools might employ. High-end phones already come with powerful operating systems — Palm OS, Pocket PC, Epoc, and the like — and you can expect that connectivity kits will evolve to wrappers on top of other open protocols. You can also expect to see connectivity standards emerging so that the same program can download and upload information from any mobile device.

Acknowledgment

The opinions expressed herein are those of the author and not necessarily of WebMD Corp.

DDJ

Listing One

import scm3as.*;
 ...
// Arrays because they are passed by reference (i.e. [out] parameters)
public String[] sIMEI = new String[1], sType = new String[1], 
                             verSW = new String[1], verHW = new String[1];
 ...
IphoneBook2 m_pb = new PhonebookSuite3();
m_pb.GetDevIdentificationInfo(sIMEI, sType, verSW, verHW);

Back to Article

Listing Two

Variant vtEmpty = new Variant(""); vtEmpty.noParam();
    _Recordset rs = new Recordset();
    rs.getFields()._Append("Memory", DataTypeEnum.adBSTR, 100, 0);
    rs.getFields()._Append("Free", DataTypeEnum.adInteger, 4, 0);
    rs.getFields()._Append("Used", DataTypeEnum.adInteger, 4, 0);
    rs.getFields()._Append("Total", DataTypeEnum.adInteger, 4, 0);
    rs.getFields()._Append("NameLength", DataTypeEnum.adInteger, 4, 0);
    rs.getFields()._Append("PhoneLength", DataTypeEnum.adInteger, 4, 0);
    rs.setCursorLocation(CursorLocationEnum.adUseClient);
    rs.Open(vtEmpty, vtEmpty, CursorTypeEnum.adOpenStatic, 
            LockTypeEnum.adLockBatchOptimistic,-1);
    m_cmdQueue.addCommand(new MemoryCommand(rs, m_pb), this, 
            CommandsQueue.SYNCHRONOUS|CommandsQueue.DIALOGBOX);
    m_memDataGrid.setDataSource(new com.ms.wfc.data.Recordset(rs));

Back to Article

Listing Three

import scm3as.*;
import java.util.*;

public class ContactGroupsCommand extends Command {
    private IPhonebook2 m_pb;
    private String[] m_DefaultGroups = {"Family", "VIP", "Friends", 
                                                     "Business", "Other"};
    public ContactGroupsCommand(IPhonebook2 pb){m_pb = pb;}
    public String getGroups()
    {
        String str = "";
        for (int i = 0; i < m_DefaultGroups.length; i++) {
            if (i != 0) str += ", ";
            str += (String)m_DefaultGroups[i];
        }
        return str;
    }
    public void executeInner() throws Throwable
    {
        for(int i = 0; i < 5; i++) {
            try {
                ICallerGroup grp = m_pb.GetCallerGroup(i);
                String name = grp.getName();
                if (name.length() != 0) 
                    m_DefaultGroups[i] = name;
            } catch (Throwable thr) {
                int err = m_pb.GetLastError(); 
                if (err == NmpAdapterError.errPnInvalidMemory) continue;
                if (err == NmpAdapterError.errInvalidParameter) continue;
                throw thr;
            }
        }
    }
    public String getName()
    {
        return "Getting Groups...";
    }
}

Back to Article

Listing Four

private void m_btnDownload_click(Object source, Event e)
{
  m_cmdQueue.addCommand(new EraseAllCommand(m_pb), this,
        CommandsQueue.SYNCHRONOUS|CommandsQueue.DIALOGBOX);
  m_cmdQueue.addCommand(new DownloadContactsCommand(m_txtCategories.getText(),
        m_txtOutlookFolder.getText(), m_pb),
        this, CommandsQueue.SYNCHRONOUS|CommandsQueue.DIALOGBOX);
}

Back to Article

Listing Five

public void executeInner() throws Throwable
{
    Contacts m_contacts = new Contacts(m_groups, m_folderPath);
    Hashtable m_table = m_contacts.m_table;
    int j = 1;
    for (Enumeration e = m_table.keys(); e.hasMoreElements();) {
        String key = (String)e.nextElement();
        ContactInfo val = (ContactInfo)m_table.get(key);
        
        IContact contact = m_pb.CreateContact();
        contact.setName(key);
        contact.setNumber(val.m_number);
        contact.setMemory(PhonebookMemory.MEMORY_DEFAULT);
        contact.setGroupID(val.m_groupId);
        m_pb.SetContact(j, contact);
        j++;
    }
}

Back to Article


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.