July 26, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

"Beaming" Using The Palm OS Exchange Manager

  • October 8, 2003
  • By Alex Gusev
  • Send Email »
  • More Articles »

As a final part of our "inter-application communication triptych," let us discuss one more way of how to do it. As you may guess, I mean here the Exchange Manager API. This kind of communication differs from those ones we've spoke about in previous articles. When you hear 'beaming', yes—that's it. But, as you may discover, a request for exchange data is just one of the launch codes your application may receive (e.g. sysAppLaunchCmdExgReceiveData), so it may be useful to export data to other apps at the same device. So, let's go ahead and take a look at practical cases.

Case 1: Standard Beaming of a Whole Database or Specific Records

The Palm OS's user interface doesn't allow beaming of an abitrary database, only prc-files, i.e. applications. So, it'd be nice for your program to offer such functionality. Fortunately, it becomes a pretty simple task with Exchange Manager. The normal working flow is as follows:

  1. Define a variable of type ExgSocketType and initialize it to zeroes.
  2. Assign appropriate values to description, target, and optionally to the type and name fields.
  3. ExgSocketType is declared in ExgMgr.h as

    typedef struct ExgSocketType {
      UInt16      libraryRef;     // identifies the Exg library
                                  // in use
      UInt32      socketRef;      // used by Exg library to
                                  // identify this connection
      UInt32      target;         // Creator ID of application
                                  // this is sent to
      UInt32      count;          // # of objects in this
                                  // connection (usually 1)
      UInt32      length;         // # total byte count for all
                                  // objects being sent (optional)
      UInt32      time;           // last modified time of object
                                  // (optional)
      UInt32      appData;        // application specific info
      UInt32      goToCreator;    // creator ID of app to launch
                                  // with goto after receive
      ExgGoToType goToParams;     // If launchCreator then this
                                  // contains goto find info
      UInt16      localMode:1;    // Exchange with local machine
                                  // only mode
      UInt16      packetMode:1;   // Use connectionless packet
                                  // mode (Ultra)
      UInt16      noGoTo:1;       // Do not go to app (local mode
                                  // only)
      UInt16      noStatus:1;     // Do not display status dialogs
      UInt16      preview:1;      // Preview in progress: don't
                                  // throw away data as it's read
      UInt16      reserved:11;    // reserved system flags
      Char *description;          // text description of object
                                  // (for user)
      Char *type;                 // Mime type of object (optional)
      Char *name;                 // name of object, generally a
                                  // file name (optional)
    } ExgSocketType;
    typedef ExgSocketType *ExgSocketPtr;
    
  4. Note that the localMode field controls the operation mode, so you may want to set a 1 there to work locally.
  5. To establish a connection, call ExgPut.
  6. To send the whole database, call ExgDBWrite. An alternative way is to call ExgSend in a loop to send all desired data. Actually, these are the same methods because ExgDBWrite requires a callback function as a parameter, which uses ExgSend internally.
  7. After all jobs are finished, call ExgDisconnect to close the connection.

The following code chunk illustrates all that was said above:

void BeamWholeDB()
{
    ExgSocketType exgSocket;
    UInt16 cardNo;
    LocalID dbID;
    DmSearchStateType searchState;
    Err err;
    Char *appName = "TestDB";

    err = DmGetNextDatabaseByTypeCreator(true, &searchState,
                                         'data', 'test', true,
                                         &cardNo, &dbID);
    if (!err)
    {
        MemSet(&exgSocket,sizeof(exgSocket),0);
        exgSocket.description = appName;
        exgSocket.name = "TestDB.pdb";

        err = ExgPut(&exgSocket);
        if (err == 0)
        {
            ExgDBWrite(WriteProc, &exgSocket, appName, dbID,
                       cardNo);
            ExgDisconnect(&exgSocket,err);
        }
    }
}

As you can see, it's really not a big deal. Sure, we've left a lot of details behind the scene, such as sending multiple objects (refer to the count member of ExgSocketType), which application should be launched (if any) after receiving data, and so forth. Like any other Palm OS API, Exchange Manager API is rich, so you're welcome to investigate it more closely.

Okay, coming back to sending individual records, you may guess now that it differs from the previous example only in using ExgSend function in some loop instead of ExgDBWrite. Therefore, we'll consider the receiving part of flow; i.e. what the application should do when it is going to get some data via Exchange library.

A sequence of steps follows:

  1. First, you should handle the sysAppLaunchCmdExgReceiveData launch code in PilotMain.
  2. Call ExgAccept to accept the incoming request.
  3. Call ExgReceive in a loop until it returns zero.
  4. And finally, call ExgDisconnect to close the connection.

So, as we've just said:

// in PilotMain
DmOpenRef g_dbP;    // our database
...
if (cmd == sysAppLaunchCmdExgReceiveData)
{
    DmOpenRef dbP;
    if ((launchFlags & sysAppLaunchFlagSubCall) ==
       sysAppLaunchFlagSubCall)
    {
       dbP = g_dbP;
       FrmSaveAllForms();
       err = ReceiveData(dbP,(ExgSocketPtr)cmdBPB);
    }
    else
    {
       dbP = DmOpenDataByTypeCreator('data','test',
                                     dmModeReadWrite);
       if (dbP)
       {
           err = ReceiveData(dbP,(ExgSocketPtr)cmdBPB);
           DmClosedatabase(dbP);
       }
    }
}
...
Err ReceiveData(DmOpenRef dbP, ExgSocketPtr sockP)
{
    Err err = 0;
    UInt16 wIndex = -1;
    
    err = ExgAccept(sockP);
    if ( err == errNone )
    {
        char buffer[1024];
        ULong lBytesRecv = 0;
        
        while ((lBytesRecv = ExgReceive(sockP,buffer,
                sizeof(buffer)))
        {
            // process data
            ...
        }
        
        err = ExgDisconnect(sockP,err);
    }
}

Now, a few words about the name member the of ExgSocketType structure. Starting from Palm OS 4.0, this field may contain a URL to identify the exchange library to connect with. Using a local exchange library may become handy if you want to debug your application locally or to send/request data to/from another application at the same device. On Palm OS 4.0 and later, if the URL starts from the '?' character, the user may be prompted to choose which exchange library to use if more than one library is registered for the selected scheme.

Case 2: Exchanging Data with the Local PIM

There are at least several situations when you might want to use Local Exchange Manager. A good example is exporting data to some built-in application (e.g. to MemoPad as the simpliest case). Even if the user has decided to use some third-party program instead of a standard one, you'll be sure that this program will correctly receive exported data. A small example looks like this:

void SendToLocalMemopad()
{
    ExgSocketType exgSocket;
    Err err = 0;
    Char *textBuf = "test";
    UInt32 size = StrLen(textBuf) + 1;

    MemSet(&exgSocket,sizeof(exgSocket),0);
    exgSocket.description = "Test message";
    exgSocket.name = "?_local:Sample.txt";
    exgSocket.type = ".txt";
    err = ExgPut(&exgSocket);
    if (err == 0)
    {
          ExgSend(&exgSocket,textBuf,size,&err);
          ExgDisconnect(&exgSocket,err);
     }
}

Well, after we've discussed the basic terms of Exchange Manager stuff, you are ready to go ahead and study additional details. Here I don't intend to copy the Palm OS Reference guide, so it'll be our homework. In real applications, you may want to use much more than we've covered here. Games, responding to 'Get' requests from a remote application, two-ways communications etc., are just instant examples. Good luck!

Communication with Devices Running an OS other than Palm OS

One other task that becomes relevant today is to exchange data between different devices with different OSes. Here, I'm speaking mainly about a PalmOS/Symbian <=> WinCE exchange. The main point is that Exchange manager uses the OBEX protocol to do its job. Early Pocket PC 2000 handhelds did not utilize OBEX at all. If you are facing such a case, you need to implement some kind of OBEX simulation on the Pocket PC device (refer to the OBEX specification for exact details). Fortunately, on Pocket PC 2002 and later, OBEX is supported, so data may be freely sent back and forth either from the OS GUI or programmatically. The only thing you might need to take care of in your Palm OS application is to register an application to handle desired types of data, say '.doc', by calling ExgRegisterDatatype. That's all, folks.

About the Author

Alex Gusev started to play with mainframes at the end of the 1980s, using Pascal and REXX, but soon switched to C/C++ and Java on different platforms. When mobile PDAs seriously rose their heads in the IT market, Alex did it too. Now, he works at an international retail software company as a team leader of the Mobile R department, making programmers' lives in the mobile jungles a little bit simpler.

# # #






Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel