Documentation  |   Table of Contents   |  < Previous   |  Next >   |  Index

4    Object Exchange

High-Level Communications

Exploring Palm OS®

The simplest form of communication for a Palm OS® application to implement is the sending and receiving of typed data objects, such as MIME data, databases, or database records.

You use the Exchange Manager to send and receive typed data objects. The Exchange Manager interface is independent of the transport mechanism. You can use Bluetooth, email, IR, SMS, or any other protocol that has an Exchange Manager plug-in called an exchange library.

This chapter describes how applications use the Exchange Manager to send and receive typed data objects. It covers the following topics:

About the Exchange Manager ^TOP^

This section explains concepts you need to know before you can begin using the Exchange Manager. It discusses the following topics:

Exchange Libraries ^TOP^

The Exchange Manager works in conjunction with an exchange library. Each exchange library is transport-dependent and performs the actual communication with the remote device. When an application makes an Exchange Manager call, the Exchange Manager forwards the request to the appropriate exchange library. The Exchange Manager's main duty is to maintain a registry of which libraries implement each protocol and which applications receive each type of data. See Figure 4.1.

Figure 4.1  Object exchange using Exchange Manager

The list of available exchange libraries depends on the particular device hardware and on what other software the user has installed. Some typically available libraries include: IR Library (IrDA), Local Exchange Library, SMS (Short Messaging System) Library, Bluetooth Library, and HotSync® Exchange Library.

As other exchange libraries become available, users can install them on their Palm Powered handhelds and use the communications functionality they provide.

Typed Data Objects ^TOP^

The Exchange Manager sends and receives typed data objects. A typed data object (or object) is a stream of bytes plus some information about its contents. The content information includes any of: a creator ID, a MIME data type, or a filename.

The object itself can be in any format, but it's best to use a standardized data format rather than a proprietary one if you have a choice. Table 4.1 lists the standardized data formats that the built-in Palm OS applications can receive.

Table 4.1  Built-in applications and standard data types 

Application

Data Type

Address Book

vCards (vcf file extension, text/x-vCard MIME type). Palm OS supports vCard version 2.1 and most features of version 3.0 (except for the '\' 'n' sequence in properties).

Datebook

vCalendars (vcs file extension, text/x-vCalendar MIME type). Palm OS supports vCalendar version 1.0.

Launcher

Palm OS databases (prc, pdb, oprc, and pqa file extensions, application/x-pilot and application/vnd.palm MIME types)

Memo

Plain text (txt file extension, text/plain MIME type)

ToDo

Not explicitly registered, but receives vCalendar objects from Datebook as appropriate


NOTE: The MIME type application/vnd.palm has been registered with the IANA and is preferred over the application/x-pilot MIME type.

More information on the vCard and vCalendar formats is available at http://www.imc.org/pdi/. For text, the basic MIME text format is described in RFC 822 (http://www.ietf.org/rfc/rfc822.txt). Palm OS builds on that with support for the quoted printable format (for international character sets) in RFC 2045 (http://www.ietf.org/rfc/rfc2045.txt) and multipart MIME (for categories) in RFC 2046 (http://www.ietf.org/rfc/rfc2046.txt). Palm OS doesn't implement everything in these RFCs, but it does generate and read content that is compliant with these standards.

If you want your application to receive objects, you must first register with the Exchange Manager for the type of data you want to receive. See "Registering for Data" for instructions on how to do so. You can override the built-in applications by registering for any data type listed in Table 4.1 and becoming the default application for that type (but only with the user's permission). See "Setting the Default Application" for more information.

If you only want to send data, you do not have to register. Your application can send data of the types listed in Table 4.1, and the Exchange Manager ensures that the appropriate application receives it.

Initializing the Exchange Socket Structure ^TOP^

The Exchange Manager, exchange library, and application use an exchange socket structure (ExgSocketType) to communicate with each other. This structure is passed from the application to the Exchange Manager to the exchange library and vice versa. (The use of the term "socket" in the Exchange Manager API is not related to the term "socket" as used in sockets communication programming.) When your application sends data, you must create this structure and initialize it with the appropriate information. When you receive data, this structure provides information about the connection and the incoming data.

The ExgSocketType structure you use must identify two important pieces of information:

The socket structure defines other fields that you may use to provide other information if you want. See the description of the ExgSocketType structure for complete details.


IMPORTANT: When initializing the ExgSocketType structure, set all unused fields to 0.

Identifying the Exchange Library ^TOP^

The ExgSocketType structure identifies the library to be used via a Uniform Resource Locator (URL) in the name field.

When your application sends data, it should always identify which exchange library to use. (If you do not specify an exchange library, the IR Library is used to maintain backward compatibility.)

The URL scheme specifies which exchange library to use. The scheme is the part of the URL that appears before the colon (:). For example, the scheme in the following URL is "http"

http://www.palmos.com 

When you pass the preceding URL to a web browser, the scheme tells the browser to connect to the server using the HTTP protocol. Similarly, when you pass the Exchange Manager a URL, the scheme tells the Exchange Manager which exchange library to use. For example, the following URL tells the Exchange Manager to connect to a remote Palm Powered device using the IR Library:

_beam:BusinessCard.vcf

Multiple exchange libraries can register for the same scheme.

On Palm OS, a URL has the following format (in BNF notation):

[?][scheme{;scheme}:]filename

where:

?
If more than one exchange library is registered for the provided schemes, the Exchange Manager has the user select the exchange library by displaying the Send With dialog.
scheme{;scheme}
The URL schemes that identify which exchange library should be used. If more than one exchange library is registered for the scheme, the default exchange library is selected unless the URL begins with a question mark.
As shown, multiple schemes may be provided, separated by semicolons. Multiple schemes are only supported in conjunction with the question mark. For example, the string "?_send;_beam:" has the Exchange Manager display a Send With dialog that lists all exchange libraries that support either the _send scheme or the _beam scheme.
filename
The name of the file to send. Typically, this file also has an extension that is used, if necessary, to determine which application should receive the data. See "Identifying the Type of Data" for more information about the file extension.

Palm OS URL schemes all begin with the underscore (_) character. Standard schemes, such as mailto, are supported without the underscore.

Palm OS defines some URL prefixes that any application can use to connect with the installed exchange libraries. A URL prefix is everything up to and including the colon character. Table 4.2 describes the prefix constants. Note that you generally only need to use exgBeamPrefix or exgSendPrefix unless a specific transport is required.

Table 4.2  Exchange Library URL Prefixes 

Exchange Library

URL Prefix

IR Library

exgBeamPrefix

Local Exchange Library

exgLocalPrefix

SMS Library

kSmsScheme:

Bluetooth Library

_btobex:

Mobile Mail Exchange Library

exgMobileMailPrefix

and exgMailtoScheme:

HotSync Exchange Library

exgDesktopPrefix

Any library that supports the _send scheme (user's choice)

exgSendPrefix

Any library that supports the _send or _beam scheme (user's choice)

exgSendBeamPrefix

Any library that supports the _get scheme (user's choice)

exgGetPrefix

The section "Implementing the Send Command" provides more information on using exgSendPrefix or exgSendBeamPrefix.

The section "HotSync Exchange" provides more information on using exgDesktopPrefix.

The section "Attachment Support Guidelines" provides more information on using exgGetPrefix.

For more information on the SMS exchange library, refer to Chapter 5, "SMS Exchange Library Reference," in Exploring Palm OS: Telephony and SMS.

For more information on the Bluetooth exchange library, refer to Chapter 12, "Bluetooth Exchange Library Support," in Exploring Palm OS: Low-Level Communications.

Identifying the Type of Data ^TOP^

When your application sends data, the exchange socket structure (ExgSocketType) identifies the type of data being sent. It can do so with one of the following values:

  • A MIME type in the type field.
  • A file extension for the file in the name field. That is, you might supply MyDB.pdb as the value of the name field. The part after the last period (.) is the extension.

In most cases, the data type determines which application receives the data on the remote side. (If the target field is specified, it determines which application receives the data instead of the data type as described below.) The Exchange Manager maintains a registry of applications and the types of data each application can receive. When the Exchange Manager receives an object, it checks the exchange socket for the data type. It checks the type field first, and if it is not defined or if no application is registered to receive that MIME type, it checks the name field for a file extension. This is discussed in more detail in the "Registering for Data" section.

Note that you may also directly specify which application should receive the data. To do so, place the creator ID in the target field. You do not have to specify a MIME type or file extension in this instance. If the target field is nonzero, the Exchange Manager checks to see if an application is registered for that creator ID and, if so, delivers the data directly to that application.

If the target application does not exist, the Exchange Manager searches the registry as usual. Use the target field only if you know that you are communicating with a Palm Powered device and want to explicitly specify which application should receive the data.

An application can register for another application's creator ID and receive all objects targeted to that creator ID, but only with the user's permission. See "Setting the Default Application" for more details.

Registering for Data ^TOP^

In most cases, applications that want to receive data from the Exchange Manager must register for the MIME type and/or file extension that they want to receive.

To do so, call ExgRegisterDatatype() and pass it five parameters:

  • Your application's creator ID.
  • A constant that identifies the type of data you want to register to receive: exgRegExtensionID for file extensions, exgRegTypeID for MIME types, exgRegCreatorID for creator IDs (see "Setting the Default Application"), or exgRegSchemeID for URL schemes (see "Requesting a URL"). Alternatively, you can register for direct delivery of data (bypassing an email application) by specifying one of these constants: exgRegDirectExtensionID, exgRegDirectCreatorID, or exgRegDirectTypeID. Or, you can indicate that the application supports data viewing by specifying one of these constants: exgRegViewExtensionID, exgRegViewCreatorID, or exgRegViewTypeID.
  • A string that lists the MIME types or file extensions.
  • A string containing descriptions of the data you are registering to receive; these are displayed to preview the data in the exchange dialog under certain circumstances.
  • A flag value of zero.

For example:

ExgRegisterDatatype(beamerCreator,
  exgRegExtensionID, BitmapExt, "bitmap", 0);

General Registration Guidelines ^TOP^

Follow these guidelines when registering for data:

  • Register as early as possible.

    To ensure that your application can receive data at any time after it is installed, call ExgRegisterDatatype() in response to the sysAppLaunchCmdSyncNotify and sysAppLaunchCmdSystemReset launch codes. The sysAppLaunchCmdSyncNotify launch code is sent to your application upon its first installation and any time the HotSync® operation modifies the application's database. The sysAppLaunchCmdSystemReset is sent to your application when the system is reset.

  • It's best to use a standardized data format rather than a proprietary one if you have a choice.
  • Provide user-friendly descriptive information for the descriptionsP parameter of ExgRegisterDatatype(). The descriptions are used in dialogs displayed by Exchange Manager to identify applications or libraries. Use information that describes the type of information handled, such as pictures, sounds, contact information, etc. Don't use MIME types or file extensions because they are not meaningful to the average user.
  • Multiple applications can register to receive the same data type, however, an application must not automatically register itself as the default application without prompting the user for permission. The section "Setting the Default Application" describes this further. An application might check when it is launched if it is still the default application (with ExgGetDefaultApplication()). However, it must honor the user's choices for handling a particular data type by saving this information in its database and by providing a "Don't ask me again" option regarding changing the default.
  • When registering for file extensions, do not include the period (.) as part of the extension. Register for "TXT", for example, not ".TXT".
  • Do not make multiple calls if you want to register for more than one MIME type or more than one file extension.

    Instead, make one call for all file extensions and one call for all MIME types. Pass a single string containing file extensions or MIME types separated by a tab (\t) character. For example, the following call registers the application for two file extensions, TXT and DOC:

ExgRegisterDatatype(myCreator,
exgRegExtensionID,"TXT\tDOC", "plain text", 0);
  • Applications that want to serve as display applications for specific kinds of data should register to receive data in view mode by using one of the view mode constants: exgRegViewExtensionID, exgRegViewCreatorID, or exgRegViewTypeID. For more details on supporting view mode, see "Viewing Attachments."

Setting the Default Application ^TOP^

Because multiple applications can register for the same data type, the Exchange Manager supports the concept of a default application that receives all objects of a particular data type. To set the default application, call the function ExgSetDefaultApplication(). There is one default application per data type in the registry.

Suppose a device receives a vCard object, and it has three applications registered to receive vCards. The Exchange Manager checks the registry to see if any of these applications is assigned as the default. If so, the default application receives all vCards (unless the exchange socket structure's target field is set). If none of the three applications is the default, the Exchange Manager chooses one, and that application receives all vCards.

Do not automatically register as the default application without the user's permission. It's imperative that you allow users to choose which application is the default. To do so, you could display a panel via a menu option that shows users the applications that can receive the same type of data as your application, show them which is the default, and allow them to select a different default. Use ExgGetRegisteredApplications() to get a list of all applications registered to receive the same data type as yours, and use ExgGetDefaultApplication() to retrieve the current default, if any. See Listing 4.2 to see how an application performs this task for the mailto URL scheme.

Listing 4.1  Initializing a List of Registered Applications


void PrvSetMailAppsList(int32_t listSelection) 
{ 
   ControlPtr ctl; 
   ListPtr lst; 
   uint32_t defaultID; 
  
   ctl = GetObjectPtr(PrefDefaultMailTrigger); 
   lst = GetObjectPtr(PrefDefaultMailList); 
  
   // crIDs, appCnt, appNames are all global variables.  
   // Get the list of creator IDs if we don't have it already.  
   if(!crIDs) { 
      ExgGetRegisteredApplications(&crIDs, &appCnt, &appNames, NULL,  
         exgRegSchemeID, "mailto"); 
      if(appCnt) { 
         MemHandle tmpH = SysFormPointerArrayToStrings(appNames, appCnt); 
         if(tmpH) 
            appNamesArray = MemHandleLock(tmpH); 
         else 
            return; 
      } 
      else 
         return; 
   } 
  
   if(appNamesArray) 
      LstSetListChoices(lst, appNamesArray, appCnt); 
   LstSetHeight(lst, appCnt < 6 ? appCnt : 6); 
  
   if(listSelection == -1) 
   { 
      uint16_t i; 
      ExgGetDefaultApplication(&defaultID, exgRegSchemeID, "mailto"); 
  
      for(i=0;i<appCnt;i++) { 
         if(crIDs[i] == defaultID) 
            LstSetSelection(lst, i); 
      } 
   } 
   else 
      LstSetSelection(lst, listSelection); 
  
   CtlSetLabel(ctl, appNamesArray[LstGetSelection(lst)]); 
} 

To become the default application for a data type that a built-in Palm OS application is registered to receive (see Table 4.1), you must perform some extra steps to ensure that you can receive that type of object when it is beamed from a device running Palm OS 3.X. You must register for the built-in application's creator ID and become the default application for that creator ID.

On Palm OS 3.X, the built-in applications always set their creator IDs in the target field when sending data, causing the data to always be sent to that application. On Palm OS 4.0 and higher, the built-in applications still register to receive the same type of data, but they do not set the target field when sending. This means that if your application is registered for the same data type and is the default application, it receives the data from devices running Palm OS 4.0 and higher as expected, but if the data is sent from a device running Palm OS 3.X, you still won't receive that data because it is specifically targeted for the built-in application.

To solve this problem, the ExgRegisterDatatype() function supports registering for another application's creator ID. Listing 4.2 shows how an application that receives vCards might set the default application after allowing the user to select the default from a list, assuming the list is initialized with code similar to that in Listing 4.1.

Note that, as with all data types, your application won't receive the data targeted for the other application unless yours is the default application for that creator ID.

Listing 4.2  Setting the default application for vCards


uint32_t PilotMain (uint16_t cmd, void *cmdPBP, uint16_t launchFlags) 
{ 
   ... 
   // Register for vCard MIME type, extension, and Address Book's creator ID.  
   // At this point, we are not the default application so we do not receive 
   // vCards. We still must register upon install so that our application  
   // appears in the preferences list when the user chooses the default  
   // application for vCards.  
   case sysAppLaunchCmdSyncNotify: 
   case sysAppLaunchCmdSystemReset: 
      char addressCreatorStr[5]; 
       
      // Create a string from Address Book's creator ID.  
      MemMove(addressCreatorStr, sysFileCAddress, 4); 
      addressCreatorStr[4] = chrNull; 
  
      ExgRegisterDatatype(crID, exgRegTypeID, "text/x-vCard", "vCard", 0); 
      ExgRegisterDatatype(crID, exgRegExtensionID, "vcf", "vCard", 0); 
      ExgRegisterDatatype(crID, exgRegCreatorID, addressCreatorStr, NULL, 0); 
      ... 
} 
  
static void PrefApply (void) 
{ 
   MemHandle h; 
   FieldType *fld; 
   ControlType *ctl; 
   uint16_t listItem; 
  
   // Set the default vCard app 
vif(appCnt && crIDs) 
   { 
      uint32_t crID; 
      char addressCreatorStr[5]; 
       
      // Create a string from Address Book's creator ID.  
      MemMove(addressCreatorStr, sysFileCAddress, 4); 
      addressCreatorStr[4] = chrNull; 
       
      listItem = LstGetSelection(GetObjectPtr(PrefDefaultAppList)); 
      crID = crIDs[listItem]; 
      ExgSetDefaultApplication(crID, exgRegTypeID, "text/x-vCard"); 
      ExgSetDefaultApplication(crID, exgRegExtensionID, "vcf"); 
      ExgSetDefaultApplication(crID, exgRegCreatorID, addressCreatorStr); 
   } 
} 

Registering to Receive Unwrapped Data ^TOP^

In rare circumstances, you can register to receive data that is sent enclosed in another object.

For example, suppose you have a stock quote application that wants to receive vStock objects. If the device is sent an email message that has the vStock object attached, your application may want to register to receive the vStock object directly rather than having the email application receive it. To do so, call ExgRegisterDatatype() and pass one of the direct delivery constants (exgRegDirectCreatorID, exgRegDirectExtensionID, or exgRegDirectTypeID) as the second parameter.

If you want to register to receive an object when it is sent as part of another object, you probably also want to receive it when it is sent by itself. This requires two calls to ExgRegisterDatatype(): one with one of the direct delivery constants, and one without.


ExgRegisterDatatype(myCreator, exgRegDirectExtensionID, "TXT\tDOC",  
  "plain text", 0); 
ExgRegisterDatatype(myCreator, exgRegExtensionID, "TXT\tDOC", "plain text", 0); 

Thus, you might make four calls to ExgRegisterDatatype():

  • one call to register for the file extensions
  • one call to register for file extensions that are sent as part of another object
  • one call to register for MIME types
  • one call to register for MIME types that are sent as part of another object

As mentioned previously, it's rare for an application to register to receive unwrapped data directly. It's more common for one application (such as an email application) to receive the entire compound object and then unwrap and disperse the enclosed objects using the Local Exchange Library. See "Sending and Receiving Locally" and "Attachment Support Guidelines" for more information.

Sending Data ^TOP^

This section describes how to send data using the Exchange Manager. It discusses the following topics:

For information about sending data as an attachment from a messaging application such as email or SMS, see "Attachment Support Guidelines."

Sending a Single Object ^TOP^

The most common use of the Exchange Manager is to send or receive a single object. To send an object, do the following:

  1. Create and initialize an ExgSocketType data structure with information about which library to use and the data to be sent. See "Initializing the Exchange Socket Structure" for more information.
  2. Call ExgPut() to establish the connection with the exchange library.
  3. Call ExgSend() one or more times to send the data.

    In this function, you specify the number of bytes to send. You may need to call it multiple times if you don't send all the data in the first call.

  4. Call ExgDisconnect() to end the connection.

    A zero (0) return value indicates a successful transmission. However, this doesn't necessarily mean that the receiver kept the data. If the target application for an object doesn't exist on the receiving device, the data is discarded; or the user can decide to discard any received objects.

Note that the ExgSend() function blocks until it returns. However, most libraries provide a user interface dialog that keeps the user informed of transmission progress and allows them to cancel the operation.

The Exchange Manager automatically displays error dialogs as well, if errors occur. You must check for error codes from Exchange Manager routines, but you don't need to display an error dialog if you get one because the Exchange Manager handles this for you.

For example, Listing 4.3 shows how to send the current draw window from one Palm Powered handheld to another Palm Powered handheld.

Listing 4.3  Sending data using Exchange Manager


status_t SendData(void) 
{ 
   ExgSocketType exgSocket; 
   uint32_t size = 0; 
   uint32_t sizeSent = 0; 
   status_t err = 0; 
   BitmapType *bmpP; 
  
   // copy draw area into the bitmap 
   SaveWindow(); 
   bmpP = PrvGetBitmap(canvasWinH, &size, &err); 
   // Is there data in the field? 
   if (!err && size) { 
      // important to init structure to zeros... 
      MemSet(&exgSocket,sizeof(exgSocket),0); 
      exgSocket.description = "Beamer picture"; 
      exgSocket.name = "Beamer.pbm"; 
      exgSocket.length = size; 
      err = ExgPut(&exgSocket);  
      if (!err) { 
         sizeSent = ExgSend(&exgSocket,bmpP,size,&err); 
         ExgDisconnect(&exgSocket,err); 
      } 
   } 
   if (bmpP) MemPtrFree(bmpP);	 
   return err; 
} 

Sending Multiple Objects ^TOP^

If the exchange library supports it, you can send multiple objects in a single connection. To send multiple objects, do the following:

  1. Create and initialize an ExgSocketType data structure with information about which library to use and the data to be sent. See "Initializing the Exchange Socket Structure" for more information. You might also supply a value for the count field to specify how many objects are to be sent.
  2. Call ExgConnect() to establish the connection with the exchange library.
  3. For each object, do the following:
    1. Call ExgPut() to signal the start of a new object.
    2. Call ExgSend() one or more times to send the data.

      You may need to call it multiple times if you don't send all the data in the first call.

  4. Call ExgDisconnect() to end the connection.

    A zero (0) return value indicates a successful transmission. However, this doesn't necessarily mean that the receiver kept the data. If the target application for an object doesn't exist on the receiving device, the data is discarded; or the user can decide to discard any beamed objects.

The ExgConnect() call is optional. Some exchange libraries, such as the IR Library, support the sending of multiple objects but do not support ExgConnect(). If ExgConnect() returns an error, the first call to ExgPut() initiates the connection. You should only continue to send objects if the first ExgPut() call succeeds. See Listing 4.4. Libraries that support the ExgConnect() call also support sending multiple objects without using ExgConnect().

Listing 4.4  Sending multiple objects


Boolean isConnected = false; 
err = ExgConnect(&exgSocket);      //optional 
if (!err) 
   isConnected = true; 
if (!err || err == exgErrNotSupported) { 
   while (/* we have objects to send */) { 
      err = ExgPut(&exgSocket); 
      if (!isConnected && !err) 
         isConnected = true; //auto-connected on first put. 
      sizeSent = ExgSend(&exgSocket,dataP,size,&err); 
      if (err) 
         break; 
   } 
} 
if (isConnected)  
   ExgDisconnect(&exgSocket, err); 

Implementing the Send Command ^TOP^

The built-in applications support a Send menu command. The purpose of this command is to allow the user to send data using any available transport mechanism.

The Exchange Manager defines a _send URL scheme. The intent is that any exchange library that supports sending is registered for the _send scheme. Currently, the Bluetooth, HotSync, SMS, and Mobile Mail libraries are registered for this scheme on release ROMs. The IR Library is not registered for the _send scheme.

To implement the Send command in your application, construct a URL that has the prefix exgSendPrefix, and send the data in the normal manner. You can also use the exgSendBeamPrefix instead so that the user can select from all exchange libraries registered for either sending or beaming (which includes the IR Library). Both of these prefixes begin with a question mark, causing the Exchange Manager to display a dialog if it finds more than one exchange library registered for the specified schemes.

For an example of how to implement the Send command, see the Memo application example code distributed with the Palm OS SDK.

Receiving Data ^TOP^

To have your application receive data from the Exchange Manager, do the following:

  1. Register for the type of data you want to receive. See "Registering for Data" for more information.
  2. Handle the launch code sysAppLaunchCmdExgAskUser if you want to control the user confirmation dialog that is displayed. See "Controlling the Exchange Dialog" for more information.
  3. Handle the launch code sysAppLaunchCmdExgReceiveData to view and/or receive the data. See "Receiving the Data" for more information on receiving the data, and see "Viewing Attachments" for more information about viewing the data; it's best to follow the guidelines in "Put with View Mode."
  4. If you want, handle sysAppLaunchCmdGoTo to display the record.

Controlling the Exchange Dialog ^TOP^

When the Exchange Manager receives an object and decides that your application is the target for that object, it sends your application a series of launch codes. The first launch code your application receives, in most cases, is sysAppLaunchCmdExgAskUser.


NOTE: The Exchange Manager allows the exchange library to turn off the user confirmation dialog. In this case, your application does not receive the sysAppLaunchCmdExgAskUser launch code.

The Exchange Manger sends this launch code because it is about to display the exchange dialog, which asks the user to confirm the receipt of data. The launch code is your opportunity to accept the data without confirmation, reject the data without confirmation, or replace the exchange dialog.

Responding to this launch code is optional. If you don't respond, the Exchange Manager calls ExgDoDialog() to display the exchange dialog.

The ExgDoDialog() function allows you to specify that the dialog display a category pop-up list. This pop-up list allows the user to receive the data into a certain category in the database, but the pop-up list is not shown by default. If you want the exchange dialog to display the pop-up list, you must respond to sysAppLaunchCmdExgAskUser and call ExgDoDialog() yourself. Pass a pointer to an ExgDialogInfoType structure. The ExgDialogInfoType structure is defined as follows:


typedef struct { 
  uint16_t     version; 
  DmOpenRef  db; 
  uint16_t     categoryIndex; 
} ExgDialogInfoType; 
 

version
Set this field to 0 to specify version 0 of this structure.
db
A pointer to an open database that defines the categories the dialog should display.
categoryIndex
The index of the category in which the user wants to file the incoming data.

If db is valid, the function extracts the category information from the specified database and displays it in a pop-up list. Upon return, the categoryIndex field contains the index of the category the user selected, or dmUnfiledCategory if the user did not select a category.

If the call to ExgDoDialog() is successful, your application is responsible for retaining the value returned in categoryIndex and using it to file the incoming data as a record in that category. One way to do this is to store the categoryIndex in the socket's appData field (see ExgSocketType) and then extract it from the socket in your response to the launch code sysAppLaunchCmdExgReceiveData. See Listing 4.5 for an example.

Listing 4.5  Extracting the category from the exchange socket


uint16_t categoryID = (ExgSocketType *)cmdPBP->appData; 
  
/* Receive the data, and create a new record using the 
   received data. indexNew is the index of this record. */ 
if (category != dmUnfiledCategory){ 
   uint16_t attr; 
   status_t err; 
   err = DmRecordInfo(dbP, indexNew, &attr, NULL, NULL); 
  
   // Set the category to the one the user specified, and  
   // mark the record dirty.  
   if ((attr & dmRecAttrCategoryMask) != category) { 
     attr &= ~dmRecAttrCategoryMask; 
     attr |= category | dmRecAttrDirty; 
     err = DmSetRecordInfo(dbP, indexNew, &attr, NULL); 
   } 
} 

Some of the Palm OS built-in applications (Address Book, Memo, and ToDo) use this method of setting the category on data received through beaming. Refer to the example code provided in the Palm OS SDK for these applications for a more complete example of how to use ExgDoDialog().

When you explicitly call ExgDoDialog(), you must set the result field of the sysAppLaunchCmdExgAskUser launch code's parameter block to either exgAskOk (upon success) or exgAskCancel (upon failure) to prevent the system from displaying the dialog a second time.

Getting the Object Description ^TOP^

The user might need more information about the object being received, so the Exchange Manager displays information about the object in the exchange dialog. Some exchange libraries do not transmit information for the exchange socket's description field, so the Exchange Manager must provide another means of supplying the user with information about the data being received.

The Exchange Manager displays the first item that it locates in the following list:

  • The data's description from the exchange socket's description field
  • The filename in the socket's name field
  • The receiving application's description as stored in the exchange registry (you pass this description to ExgRegisterDatatype() when registering)
  • The MIME type in the socket's type field
  • The file extension in the socket's name field

If you want to support viewing the data in an application, the Exchange Manager can launch a display application with the launch code sysAppLaunchCmdExgReceiveData. Display applications should register both file extension(s) and MIME type(s) of data that they can handle. Ideally, display applications should register for receiving data in view mode by registering with one or more of the view mode data type constants: exgRegViewExtensionID, exgRegViewCreatorID, or exgRegViewTypeID. Refer to "General Registration Guidelines."

For detailed information about supporting data viewing, see "Viewing Attachments"; particularly, you should follow the guidelines in "Put with View Mode." This information applies not only to email attachments, but to any incoming data.

Receiving the Data ^TOP^

If the Exchange Manager receives exgAskOk in response to the exchange dialog or the sysAppLaunchCmdExgAskUser launch code, the next step is to launch the application with sysAppLaunchCmdExgReceiveData. This launch code tells the application to actually receive the data.

To respond to this launch code, do the following:

  1. Call ExgAccept() to accept the connection.
  2. Call ExgReceive() one or more times to receive the data.

    In this function you specify the number of bytes to receive, and ExgReceive() returns the number of bytes that were received. You may need to call it multiple times if data is remaining to be received after the first and subsequent calls.

    Note that in the socket structure, the length field may not be accurate, so in your receive loop you should be flexible in handling more or less data than length specifies.

  3. If you want your application launched again with the sysAppLaunchCmdGoTo launch code, place your application's creator ID in the ExgSocketType's goToCreator field and supply the information that should be passed to the launch code in the gotoParams field. (The ExgSocketType structure is the parameter block for the sysAppLaunchCmdExgReceiveData launch code.)
  4. Call ExgDisconnect() to end the connection.

    A zero (0) return value indicates a successful transmission.

After your application returns from sysAppLaunchCmdExgReceiveData, if the goToCreator specifies your application's creator ID and if the exchange library supports it, your application is launched with sysAppLaunchCmdGoto. In response to this launch code, your application should launch, open its database, and display the record identified by the recordNum field (or matchCustom field) in the parameter block. The Exchange Manager always does a full application launch with sysAppLaunchCmdGoto, so your application has access to global variables; however, if you also use this launch code to implement the global find facility, you may not have access to global variables in that instance. The example code in Listing 4.6 checks to see if globals are available, and if so, calls StartApplication to initialize them.

Listing 4.6  Responding to sysAppLaunchCmdGoto


case sysAppLaunchCmdGoto: 
  if (launchFlags & sysAppLaunchFlagNewGlobals) {
     err = StartApplication(); 
     if (err) return err; 
     GoTo(cmdPBP, true); 
     EventLoop(); 
     StopApplication(); 
  } else { 
     GoTo(cmdPBP, false); 
} 

Not all exchange libraries support using the sysAppLaunchCmdGoto launch code after the receipt of data.

Because Palm OS supports multiple object exchange, there is no guarantee that your application is the one that is launched at the end of a receipt of data. If multiple objects are being received, it is possible for another application to receive data after yours and to set the goToCreator field to its own creator ID. In this case, the last application to set the field is the one that is launched.

Listing 4.7 shows a function that receives a data object and sets the goToCreator and goToParams.

Listing 4.7  Receiving a data object


status_t ReceiveData(ExgSocketPtr exgSocketP) 
{ 
   status_t err; 
   MemHandle dataH; 
   uint16_t size; 
   uint8_t *dataP; 
   int16_t len; 
   uint16_t dataLen = 0; 
    
   if (exgSocketP->length) 
      size = exgSocketP->length; 
   else 
      size = ChunkSize;  
   dataH = MemHandleNew(size);   
   if (!dataH) return -1;  //  
   // accept will open a progress dialog and wait for your receive commands 
   err = ExgAccept(exgSocketP); 
   if (!err){ 
      dataP = MemHandleLock(dataH); 
      do { 
         len = ExgReceive(exgSocketP,&dataP[dataLen], size-dataLen,&err); 
         if (len && !err) { 
            dataLen+=len; 
            // resize block when we reach the limit of this one... 
            if (dataLen >= size) { 
               MemHandleUnlock(dataH); 
               err = MemHandleResize(dataH,size+ChunkSize); 
               dataP = MemHandleLock(dataH); 
               if (!err) size += ChunkSize; 
            } 
         } 
      } 
      while (len && !err); 
  
      MemHandleUnlock(dataH); 
       
      ExgDisconnect(exgSocketP,err); // closes transfer dialog 
       
      if (!err) { 
         exgSocketP->goToCreator = beamerCreator; 
         exgSocketP->goToParams.matchCustom = (uint32_t)dataH; 
      } 
   } 
   // release memory if an error occured 
   if (err) MemHandleFree(dataH); 
   return err; 
} 

Sending and Receiving Databases ^TOP^

It's common to want to send and receive an entire database using the Exchange Manager. For example, you might want to allow your application's users to share their versions of the PDB file associated with your application by beaming that file to each other.

Sending and receiving a database involves the extra steps of flattening the database into a byte stream when sending and un-flattening it upon return.

In addition to the process documented in this section, you can now also use the Data Manager function DmBackupUpdate() to flatten a database into a bye stream, and DmRestoreUpdate() to restore a database from a byte stream. These functions are more flexible than the Exchange Manager functions.

Sending a Database ^TOP^

To send a database, do the following:

  1. Create and initialize an ExgSocketType data structure with information about which library to use and the data to be sent. See "Initializing the Exchange Socket Structure" for more information.
  2. Call ExgPut() to establish the connection with the exchange library.
  3. Call ExgDBWrite() and pass it a pointer to a callback function in your application that it can use to send the database. You make the call to ExgSend() in that function.
  4. Call ExgDisconnect() to end the connection.

The ExgDBWrite() function takes as parameters the local ID of the database to be sent and a pointer to a callback function. You may also pass in the name of the database as it should appear in a file list and any application-specific data you want passed to the callback function. In this case, you would pass the pointer to the exchange socket structure as the application-specific data. If you need any other data, create a structure that contains the exchange socket and pass a pointer to that structure instead.

The write callback function is called as many times as is necessary to send the data. It takes three arguments: a pointer to the data to be sent, the size of the data, and the application-specific data passed as the second argument to ExgDBWrite().

Listing 4.8 shows an example of how to send a database. The SendMe() function looks up the database creator ID and passes it to the SendDatabase() function. The SendDatabase() function creates and initializes the exchange socket structure and then passes all that information along to the ExgDBWrite() function. The ExgDBWrite() function locates the database in the storage heap, translates it into a stream of bytes and passes that byte stream as the first argument to the write callback function WriteDBData(). WriteDBData() forwards the exchange socket and the data stream to the ExgSend() call, sets its size parameter to the number of bytes sent (the return value of ExgSend()), and returns any error returned by ExgSend().

Listing 4.8  Sending a database


// Callback for ExgDBWrite to send data with Exchange Manager  
status_t WriteDBData(const void* dataP, uint32_t* sizeP, void* userDataP)  
{ 
   status_t err; 
  
   *sizeP = ExgSend((ExgSocketPtr)userDataP, (void*)dataP, *sizeP, &err); 
   return err; 
} 
  
status_t SendDatabase (LocalID dbID, CharPtr nameP, CharPtr descriptionP)  
{ 
   ExgSocketType exgSocket; 
   status_t err; 
  
   // Create exgSocket structure 
   MemSet(&exgSocket, sizeof(exgSocket), 0); 
   exgSocket.description = descriptionP; 
   exgSocket.name = nameP; 
  
   // Start an exchange put operation 
   err = ExgPut(&exgSocket); 
   if (!err) { 
      err = ExgDBWrite(WriteDBData, &exgSocket, NULL, dbID); 
      err = ExgDisconnect(&exgSocket, err); 
   } 
   return err; 
} 
  
// Sends this application 
status_t SendMe(void) 
{ 
   status_t err; 
   // Find our app using its internal name 
   LocalID dbID = DmFindDatabase(0, "Beamer"); 
   if (dbID) 
      err = SendDatabase(dbID, "Beamer.prc", "Beamer application"); 
   else 
      err = DmGetLastErr(); 
   return err; 
} 

Note that there is nothing about ExgDBWrite() that is tied to the Exchange Manager, so it may be used to send a database using other transport mechanisms as well. For example, if you wanted to transfer a database from your Palm Powered handheld to your desktop PC using the serial port, you could use ExgDBWrite() to do so.

Receiving a Database ^TOP^

The Launcher application receives databases with the .prc or .pdb file extension. If you want your application to be launched when the database is received, you can use a different extension and handle receiving the database within your application. For example, a book reader application might want to be launched when the user is beamed a book. In this case, the book reader application might use an extension such as .bk for the book databases.

You receive a database by responding to the same launch codes that you do for receiving any other data object (see "Receiving Data"); however, your response to the sysAppLaunchCmdExgReceiveData launch code is a little different:

  1. Call ExgAccept() to accept the connection.
  2. Call ExgDBRead() and pass it a pointer to a callback function in your application that it can use to read the database. You make the call to ExgReceive() in that function.
  3. Call ExgDisconnect() to end the connection.

The ExgDBRead() function takes as parameters two pointers to callback functions. The first callback function is a function that is called multiple times to read the data. The second function is used if the database to be received already exists on the device.

Requesting Data ^TOP^

This section describes how to use the Exchange Manager to request data. It covers:

Some exchange libraries may allow you to request data from a remote device through a call to ExgGet(). If supported, you can use ExgGet() to implement two-way communications between two Palm Powered devices.


NOTE: The only standard exchange library that supports ExgGet() is the Local Exchange Library; currently there are no transports that support remote get requests.

For information on using ExgGet() to attach a document to a message from a messaging application, see "Sending an Attachment from a Messaging Application."

Sending a Get Request for a Single Object ^TOP^

To request data from a remote device, do the following:

  1. Create and initialize an exchange socket structure (ExgSocketType) as described in "Initializing the Exchange Socket Structure"section. The data structure should identify the exchange library and the type of data that your application wants to receive.
  2. Call ExgGet() to establish the connection and request the data.

    In response, the exchange library establishes a connection with the remote device, and upon return has data that your application should receive. If the remote device is a Palm Powered device, the exchange library obtains this data from an application on the remote side using the process described in the "Responding to a Get Request" section.

  3. Call ExgReceive() one or more times to receive the data.
  4. Call ExgDisconnect() to end the connection.

Responding to a Get Request ^TOP^

When the Exchange Manager receives a get request, it launches the appropriate application with the launch code sysAppLaunchCmdExgGetData. Applications can register their support for the Get mechanism by registering to handle the _get scheme.


NOTE: Since no standard transports support remote get requests, this section describes how to support a local get request.

Your response to the sysAppLaunchCmdExgGetData launch code should be to send the requested data:

  1. Present a document selection screen so that the user can choose an object to send.
  2. Set the name, type, and description fields in the socket.
  3. Call ExgAccept(). (Do not call ExgPut().)
  4. Call ExgSend() one or more times.
  5. Call ExgDisconnect() when finished.

For more information on supporting the Get mechanism, see "Sending an Attachment from a Messaging Application."

See the "Sending a Single Object" section for more information on sending objects.

Two-Way Communications ^TOP^

You can use ExgGet() and ExgPut() in combination with the ExgConnect() call to have your application perform two-way communication. For example, you may want to implement two-way communication in a multiuser game.

In such a situation, one device acts as a client and the other acts as a server. The client calls ExgConnect(), which tells the exchange library that a connection is established to perform multiple operations, such as the sending of multiple objects. The client then calls ExgGet() or ExgPut() repeatedly and calls ExgDisconnect() when finished. On the server device, the appropriate application is launched for each of these requests. The server also calls ExgDisconnect() when it is done sending or receiving each object. The swapping of client and server roles is not supported.

Remember that not all exchange libraries support ExgConnect() and ExgGet(). If either one of these returns an error, your application should assume that this feature is not available.

Getting the Sender's URL ^TOP^

For some applications, you might need to know the URL that addresses the remote device from which you are receiving data. This is especially useful for games and other two-way communications. You can get the URL after calling ExgAccept() by calling ExgControl() and passing the exgLibCtlGetURL operation code.

Not all exchange libraries support this operation. The Bluetooth exchange library does support it, and you can find more information in Chapter 12, "Bluetooth Exchange Library Support," in Exploring Palm OS: Low-Level Communications.

Requesting a URL ^TOP^

In addition to requesting data with an ExgGet() call, you can request a URL with a ExgRequest() call. The idea behind the ExgRequest() call is to follow the model of pull technology. You could, for example, implement a web browser if you had an exchange library that supported the HTTP protocol. You could then send an ExgRequest() call with an exchange socket containing a URL such as http://www.palmos.com and receive the web page in response.

The fundamental differences between ExgRequest() and ExgGet() are:

  • ExgRequest() does not automatically send the data back to the application that requested it. With ExgRequest(), when the exchange library receives the requested data, it has the Exchange Manager send it to the default application for that data type.
  • Applications can register for URLs sent using ExgRequest(). ExgRequest() first looks for an exchange library that handles the URL scheme. If it cannot find one, it looks for an application instead. If it finds an application, it launches it with the sysAppLaunchCmdGoToURL launch code.

    For example, suppose an application that handles email registers for the mailto URL scheme. If another application wants to implement an email command, it could do so by calling ExgRequest() and passing an exchange socket with a URL that begins with mailto. In response to this command, the Exchange Manager launches the application that handles email, allowing the user to compose the email.

For information on another method of implemented email and attaching a document to a message, see "Sending an Attachment from a Display Application."

Sending and Receiving Locally ^TOP^

Most of this chapter has described how to use the Exchange Manager to send data to a remote device and receive data from a remote device.

You may also use the Exchange Manager to exchange data with other applications on the local device. To do so, use the Local Exchange Library. You might want to do so in the following circumstances:

  • You might have an application that creates some sort of event in the Datebook application. Your users might have an application that they use in place of the built-in Datebook. To ensure that the appointment is sent to the user's chosen application, you can send that data as a vCalendar object using the Local Exchange Manager. This way, whichever application is the default in the Exchange Manager registry is the one that receives your vCalendar.
  • Your application receives compound data objects, such as email messages that contain attachments intended for other applications. As described in the "Registering to Receive Unwrapped Data" section, exchange libraries can "unwrap" a compound object and deliver the objects it contains directly; however, doing so is the exception the rule.

    It's much more common for the email message to be sent to the email application and have the attachments delivered to the appropriate applications only when the user requests it. In response to a user request, the email application extracts the attached object and uses the Local Exchange Library to send it to the application that should receive it, for viewing and/or storage. For detailed guidelines on handling attachments, see "Attachment Support Guidelines."

  • Your application exchanges data with a remote device, and you want to debug the code that interacts with the Exchange Manager. In this case, using the Local Exchange Library causes your application to send data in loopback mode, where it is also the recipient of the data.

To use the Local Exchange Library, do the following:

  1. Use a URL in the name field of the ExgSocketType structure to identify the Local Exchange Library. Begin the URL with the constant string exgLocalPrefix.
  2. If you want to suppress the exchange dialog, create and initialize an ExgLocalSocketInfoType structure and assign it to the socket's socketRef field.

    typedef struct { 
      Boolean freeOnDisconnect; 
      Boolean noAsk; 
      ExgPreviewInfoType *previewInfoP; 
      ExgLocalOpType op; 
      FileHand tempFileH; 
    } ExgLocalSocketInfoType; 
    

    where the following are parameters you might want to set:

freeOnDisconnect

Determines whether the structure is freed when the ExgDisconnect() call is made. The default is true. In general, code that allocates a structure should be responsible for freeing that structure. Therefore, if you have allocated ExgLocalSocketInfoType, you should set this field to false and explicitly free the structure when you are finished with it.

noAsk

Set to true to disable the display of the exchange dialog. For example, if you want to create a vCalendar object and send it to the datebook application in response to a user command, you probably want to set noAsk to true so that the user does not have to confirm the receipt of the data they just requested you to send.

previewInfoP

A pointer to an ExgPreviewInfoType structure, used to display a preview of the data. The preview feature is deprecated and is maintained only for backward compatibility.

All other fields are set by the Local Exchange Library. If you don't create this structure, the library does it for you; therefore, you only need to create this structure if you want to supply non-default values for the noAsk or previewInfoP fields.

  1. You can suppress the display of the progress dialogs that the exchange libraries typically display by setting the noStatus field of the ExgSocketType structure to true.
  2. Send and receive data in the normal manner. See "Sending Data" and "Receiving Data" for details.

Interacting with the Launcher ^TOP^

When you beam an application from the Launcher, other databases can be automatically beamed with it. If the application has an associated overlay database, the overlay is beamed along with the application. You do not have to perform any extra work to allow this to happen. This bundling behavior is available only when beaming from the launcher, not if an application manually beams an application.

In addition to beaming overlays, you can set up a record database so that the Launcher beams it along with the application database and the overlay. For example, a dictionary application might have its dictionary data in an associated database. When a user beams the dictionary application to another user, the dictionary data should be beamed along with the application itself. To allow this to happen, you set the bit dmHdrAttrBundle in the database's attributes.

If you beam an application plus databases to a device running Palm OS 4.0 or higher, the user sees a single confirmation message. If you beam the application to a device running Palm OS 3.X, the device receives only the application database and displays an alert saying that it cannot receive the other databases.

HotSync Exchange ^TOP^

HotSync Exchange allows a Palm OS Cobalt device and a desktop computer running the Palm Desktop to exchange files in their native formats. For example, HotSync Exchange enables installation of JPEG (.JPG) files to a handheld image viewer via the standard HotSync desktop install tool and the HotSync exchange library, provided the viewer application has registered with the Exchange Manager for the .JPG extension. This feature eliminates the need for the viewer application developer to write a custom conduit to pack JPEG data into the Palm OS database format.

Similarly, the viewer application can send JPEG files via the Exchange Manager directly to the desktop where HotSync stores them in standard .JPG format.

HotSync Exchange also supports bundled install, which is the installation of an application and its data files in a single HotSync session. Bundled install requires the newly installed application to register for its data types with the Exchange Manager when it receives the sysAppLaunchCmdSyncNotify launch code. This allows the HotSync exchange library to deliver the data files when it receives the subsequent sysNotifySyncFinishEvent.

For more information about the desktop side of HotSync Exchange, refer to the book Introduction to Conduit Development.

Note that HotSync Exchange is supported only by Palm OS devices running Palm OS Cobalt.

Sending Files with HotSync Exchange ^TOP^

Applications use the HotSync exchange library to send files to a HotSync desktop. The HotSync exchange library supports the following Exchange Manager schemes:

  • The desktop scheme (_desktop). This scheme supports direct exchange of a file to a HotSync desktop.
  • The _send scheme. This scheme allows users to send data using any transport that supports this scheme, such as the HotSync exchange library.

These schemes support the exchange of files during a HotSync operation to a directly connected desktop.

Neither scheme supports the specification of a target desktop in the Exchange URL, so the file will, by default, be sent during the next HotSync operation to any desktop. However, the user may select a specific target desktop for each file pending HotSync Exchange via the HotSync client user interface, if desired (see below). This will cause the file to be sent during the next HotSync operation with the selected desktop.

Example ^TOP^

The following example illustrates the data flow involving the HotSync exchange library and the desktop. Say that a device application wants to transfer palmuser.id to the desktop. The user also wants to install the picture mountain.jpg to the handheld to view on a registered JPEG picture viewer.

Figure 4.2  HotSync Exchange example

Prior to the HotSync Operation

Before the HotSync operation the following operations are performed:

The user queues the file mountain.jpg for install to the handheld during a subsequent HotSync. The file is queued in a user-specific download folder on the desktop.

The device application uses the Exchange Manager API to do the following (represented by red lines in the figure):

  1. Initialize the ExgSocketType structure with the file name palmuser.id.
  2. Call ExgPut(). This causes the HotSync exchange library to allocate a temporary cache to store the data. It also stores information about the pending transaction in a catalog of pending desktop exchanges.
  3. Call ExgSend() to fill the database with the data.
  4. Call ExgDisconnect() to close the cache. The data is then queued until it can be successfully sent during a HotSync operation.
During the HotSync Operation

During the HotSync Exchange operation, the conduit performs several actions, represented by the black lines in the figure.

The HotSync Exchange conduit first checks if there are any pending handheld-to-desktop transfer requests for the local desktop by examining the handheld exchange catalog mentioned above. Since the conduit finds an entry, it proceeds to create a desktop file with the associated file name (palmuser.id) in the user's directory on the desktop that contains the contents of the associated temporary cache. Afterwards, the conduit deletes the catalog entry and the temporary cache from the handheld.

The conduit then checks to see if there are any files to be installed to the device. It finds mountains.jpg and creates a cache named mountains.jpg on the handheld.

After the HotSync Operation

After the HotSync operation the following operations are performed (represented by blue lines in the figure):

The system launches newly installed applications and applications whose data has been modified by the HotSync operation. At this point newly installed applications can register supported file types with the Exchange Manager. (So, if the HotSync operation had installed a JPEG viewer, it would now register for .JPG files). When the HotSync exchange library receives the sysNotifySyncFinishEvent notification, it searches for temporary HotSync caches. On finding mountains.jpg, it opens the cache and calls ExgNotifyReceive(). This causes the Exchange Manager to launch the viewer for JPEG files and transfer the file mountains.jpg to it. The application may choose to convert and store it in a Palm OS database. When the application calls ExgDisconnect(), the HotSync exchange library deletes the temporary cache created by the conduit.

The HotSync exchange library disables the confirm receipt dialog that is normally displayed when data is sent via the Exchange Manager. Thus there is no user interface on the handheld device during a successful desktop to handheld exchange.

Attachment Support Guidelines ^TOP^

This section outlines how Palm OS applications should interoperate to exchange email attachments. On other platforms attachments are stored intermediately on a file system for the handover between a messaging application (email, instant messaging, etc.) and a display application (word processor, image viewer, etc.). On Palm OS, which doesn't provide a file system, the Exchange Manager enables data exchange between applications.

The following sections describe how applications should use the Exchange Manager to handle attachments. These guidelines were designed with the following goals:

  • Leveraging existing capabilities of today's applications.
  • Ensuring backwards compatibility with Palm OS 4 by using existing standard mechanisms.
  • Providing a good user experience.

Application providers are strongly encouraged to follow these guidelines to enable a consistent user experience on Palm OS.

The following topics are covered:

The Attachment Support sample code shows how to implement the guidelines covered in this section. It is available in the Developer Knowledge Base at http://kb.palmsource.com/

Viewing Attachments ^TOP^

Messaging applications should leverage dedicated display applications already available on the device rather than implementing their own content viewers. Passing data from the messaging application to a display application is facilitated by the Exchange Manager.


NOTE: The data viewing mechanism described here can be used for more than just viewing email attachments. It can be used as a general purpose mechanism to view any data incoming via the Exchange Manager. Follow the guidelines for display applications to support data viewing in a display application.

There are two methods of exchanging attachments:

  • Regular Put: This is the standard put mechanism (using ExgNotifyReceive() or ExgPut()). It is backwards compatible with older applications that don't know about attachment support.
  • Put with View Mode: This method defines an enhanced view mode. It enables display applications to distinguish between data sent for temporary viewing versus data sent to be accepted into the database.

    Additionally, this method defines a return mechanism to the messaging application. This allows display applications to execute a full launch of one or more other applications before returning control to the messaging application.

Regular Put

This method, which has been around for several years, enables an application to send data to another application. Older display applications, which are not attachment aware, will simply accept the data into their database and not return to the messaging application. (The user needs to return via the launcher). Although this behavior doesn't present an optimal user experience, it provides a way to take advantage of older applications.

Newer applications, which follow the guidelines outlined in this section, provide the user with the option to return to the messaging application (for example, via a Done button). The recommended method is that the display application simply exits. The system will automatically launch the previous application (implicit launch of the messaging application).

The interaction between the messaging application, Exchange Manager, and the display application for a regular Put operation is shown in Figure 4.3. Specific guidelines for messaging applications and display applications follow the figure.

Figure 4.3  Regular Put operation

Guidelines for Messaging Applications

To handle attachment viewing with the regular Put method, messaging applications should follow these guidelines:

  • Messaging applications are strongly encouraged to implement their own exchange library to support the Put mechanism (minimal implementation of accept/receive/disconnect).

    Although Put can be implemented without an exchange library (by using ExgPut(), ExgSend(), and ExgDisconnect()), this implementation is slow, especially for large attachments, because the Exchange Manager first reads and copies all the data before handing it over to the display application.

  • Messaging applications can query the Exchange Manager registry to determine if a dedicated application is available to handle a specific content type (use ExgGetRegisteredTypes()). If no application can handle the attachment, the messaging application may convert the content into a different format that can be displayed on the device. The conversion might take place either on the client side or, in the case of a distributed email solution, on a server or desktop computer. For example, if no application has registered with the Exchange Manager to handle HTML content, the email application could convert it to text and display it itself.
  • Whenever possible, messaging applications should include the MIME type information (besides the file extension) when sending data to the Exchange Manager. File extensions do not uniquely identify the content of a document. In some cases, the same file extension has been used for different file formats (for example, ".doc"). Refer to IANA (http://www.iana.org/assignments/media-types/) for the official list of registered MIME types.

    Some notes on MIME types: MIME type information in the Content-Type field of email messages isn't always reliable. Some email programs use non-registered MIME types (for example, application/powerpoint instead of application/vnd.ms-powerpoint) or use a generic MIME type (for example, application/octet) when attaching documents. It is recommended that email applications analyze the Content-Type field carefully (including file extensions), and map it to the correct MIME type before passing this information to the Exchange Manager. Developers of messaging applications are encouraged to present a list of applications that can handle the attachment, instead of simply using the default application. (The ExgGetRegisteredApplications() function allows messaging applications to query for applications that have registered for a specific MIME type or file extension).

  • Messaging applications should send only one data object (document) at a time to a document application in a single connection. Although the exchange library is capable of handling multiple objects in a single connection, the assumption is that a display application can display only one document at a time.
  • For regular Put, the default Exchange Manager dialog ("Do you want to accept...") should not be disabled. (Use ExgNotifyReceive()(...,0) in the exchange library).
  • Messaging applications are responsible for transport-related encoding and decoding of the content. All content exchanged with a display application happens in binary format.

Guidelines for Display Applications

To handle attachment viewing with the regular Put method, display applications should follow these guidelines:

  • Display applications should register both file extension(s) and MIME type(s) of data that they can handle. Refer to "General Registration Guidelines."
  • Applications should be prepared to receive invalid data and deal with this situation gracefully.
  • Applications that accept data or documents into their databases should avoid unnecessary duplication. For instance, if a user views an attachment several times, the data should not be duplicated.
  • Applications should provide the user with an option to return to the messaging application (for example, a Done button).
  • Display applications and messaging applications exchange data in its normal binary format. Messaging applications will encode/decode the data according to their transport requirements.

Put with View Mode

This method defines an extension to the standard Put mechanism. It allows display applications to implement a special view mode where data is displayed, but not automatically added to the application's database. During view mode, the default Exchange Manager "Accept..." dialog can be disabled, which saves the user an extra step.

Moreover, view mode defines a mechanism to return to the messaging application across an arbitrary number of nested launches of other applications. This is useful, for instance, when a messaging application hands a .zip or .tar file to a decompression utility application that, after the user chooses a specific document, sends the content to the appropriate display application.

Implementation of the view mode requires collaboration of both the messaging and display applications. Display applications indicate support for view mode by using the following exchange registry IDs during registration:


// New Exchange registry IDs for View registry. Don't change values!  
#define exgRegViewExtensionID 0xff8d // filename ext. registry for View  
#define exgRegViewTypeID 0xff8e // MIME type registry for View  
 
ExgRegisterDatatype(...,exgRegViewExtensionID,...,...,...); 
ExgRegisterDatatype(...,exgRegViewTypeID,...,...,...); 

These two exchange registry IDs, one for file extensions and the other for MIME types, allow display applications to support view mode only for a subset of the content they usually accept.

Before a messaging application calls ExgNotifyReceive(), it must first check if the receiving application supports view mode for the content that is to be sent. If the display application supports view mode, the messaging application must add its own GoTo information to the ExgSocketType structure. Figure 4.4 shows the interaction between the applications and the Exchange Manager in more detail.

Figure 4.4  Put with view mode

Guidelines for Messaging Applications

Messaging applications are strongly encouraged to support view mode.

In addition to the guidelines defined in "Regular Put," messaging applications that want to take advantage of display applications with view mode support must follow these guidelines:

  • Messaging applications must check if the receiving application supports view mode, before adding their own GoTo information. The default "Accept" dialog can be disabled only if the target application supports view mode, resides on the same device, and if GoTo information is added.

    ExgGetRegisteredApplications(..., ..., ..., 
    exgRegViewExtensionID,...) 
    ExgGetRegisteredApplications(..., ..., ..., exgRegViewTypeID,...) 
    ... 
    if (supportsView) { 
      add_my_GoTo_info(); 
      ask = exgNoAsk; 
    } 
    ExgNotifyReceive(..., ask); 
    

  • If the receiving application does not support view mode, the gotoCreator field and the goToParams structure fields in the ExgSocketType structure passed to ExgNotifyReceive() (or ExgPut()) must be set to zero and the "Accept" dialog must not be disabled. The reason for this is that some applications (for example, certain built-in PIM applications) that don't support view mode, use some goToParams fields to determine certain states. Supplying wrong information could lead to unwanted behavior.
  • When a messaging application is relaunched after view mode, it should return to the same state it was in when the display application was launched. Especially, the same message should be displayed and any splash screens should be skipped.

Guidelines for Display Applications

In addition to the guidelines defined in "Regular Put," display applications that want to implement view mode support must follow these guidelines:

  • Support for view mode must be indicated by registering with the Exchange Manager like this:

    // New Exchange registry IDs for View registry. Don't change values! 
    #define exgRegViewExtensionID 0xff8d // filename extension ID 
    #define exgRegViewTypeID 0xff8e // MIME type registry  
     
    ExgRegisterDatatype(...,exgRegViewExtensionID,...,...,...); 
    ExgRegisterDatatype(...,exgRegViewTypeID,...,...,...); 
    

  • Always check if your application is called in view mode by checking if goToCreator information is available (in the ExgSocketType structure).
  • When applications receive data in view mode, the data should be stored temporarily and not automatically accepted into the application database. Instead, the user should be given the option to save the data. To save memory space, temporary data should be removed before the application exists.
  • Applications that support view mode must provide an option to return to the messaging application (for example, a Done button). Returning to the messaging application must be implemented by actively launching the messaging application (with SysUIAppSwitch() or the AppLaunchWithCommand() macro), using the GoTo information provided by the messaging application.

Sending an Attachment from a Messaging Application ^TOP^

Traditionally, when the user composes a message, messaging applications provide an option to select a document and attach it to the outgoing message. This has not been straightforward on Palm Powered devices in the past, since the Palm OS doesn't provide a file system. These guidelines define a standard way to implement this feature using the Exchange Manager's Get mechanism. This mechanism isn't limited to attachment support, but rather defines a general import mechanism.

The process of selecting an attachment includes two steps:

  1. Let the user select the application where the data is stored.
  2. Launch this application and let the user pick from a list of data objects.

The idea is to enable users to perform a data lookup by application (in contrast to a path lookup on other platforms). This fits the Palm OS model where data is associated with one particular application. The application that stores the data is responsible for providing the user interface in step 2. This makes it possible to present a user interface that is optimized for that particular data type. For instance, a calendar application can present information in an appropriate calendar context rather then as a simple list, allowing for a better user experience.

The Get mechanism requires implementation for both the messaging application as well as the display application. Although the Get mechanism has been available since Palm OS 4, it hasn't been widely used yet by applications, due to lack of guidelines and usage scenarios. However, with more and more applications supporting the exchange of native file formats across different platforms, this situation will change rapidly.

To leverage the existing Get mechanism for the purpose of supporting attachments, a new _get exchange scheme has been defined (similar to _local or _send). Display applications must register this scheme with the Exchange Manager to let other applications know that they support the Get mechanism.

Figure 4.5 shows the interaction between the applications and the Exchange Manager.

Figure 4.5  Sending attachment from messaging application


NOTE: There are bugs in some versions of Palm OS that prevent using the Get mechanism as documented here. The Attachment Support sample code shows how to work around these problems. It is available in the Developer Knowledge Base at http://kb.palmsource.com/

Guidelines for Messaging Applications

To handle attachment sending, messaging applications should follow these guidelines:

  • Messaging Applications must use the _get scheme to identify the available display applications that implement attachment support.
  • Messaging applications should offer a way to add multiple attachments to a message by repeating the attachment selection process.
  • Messaging application should never try to read/write directly from/to the databases of other applications. Database formats might change or databases might be encrypted. Using the Exchange Manager not only prevents database corruption by other applications but also ensures interoperability between 68K and ARM applications.
  • Before calling ExgGet(), messaging applications must:
    • allocate buffers for the exgSocket.name, exgSocket.type, and exgSocket.description fields. The size of these buffers are:

      description: exgMaxDescriptionLength + 1

      type: exgMaxTypeLength + 1

      name: exgMaxTypeLength + 1 (same as for type)

    • initialize all buffers with zeros
    • set exgSocket.name to "_local:"

Guidelines for Display Applications

To handle attachment sending from a messaging application, display applications should follow these guidelines:

  • Applications must register the _get scheme with the Exchange Manager if they implement attachment support. Refer to "General Registration Guidelines."
  • Applications must not send more then one data object for every ExgGet() request.
  • When responding to a sysAppLaunchCmdExgGetData launch code, an application should copy the file name, type, and description information of the content into the supplied exgSocket.name, exgSocket.type, and exgSocket.description fields. Memory for these fields has been allocated by the calling application. The usable size of these fields is:
    • name: exgMaxTypeLength (same as type)
    • type: exgMaxTypeLength
    • description: exgMaxDescriptionLength

      Applications should first check if memory was allocated (check for NULL pointers) before writing to the buffers. An application should never allocate or reallocate memory for these fields itself.

      If the exgSocket.name field contains a scheme (for example, "_local:"), this scheme information should not be overwritten. Rather, name information should be appended to the scheme (for example, "_local:myname.txt").

  • Display applications should provide a familiar document selection screen, similar to the document list users might see when they usually launch the display application.
  • When responding to a sysAppLaunchCmdExgGetData launch code, applications may support requests for a specific record (for example, via an application-specific URL scheme passed in the name field of the ExgSocketType structure). Such a request should be handled without a user interface.

A display application may be launched with a full launch in response to a get request. This implementation is shown in detail in the Attachment Support sample code. It is available in the Developer Knowledge Base at http://kb.palmsource.com/

Sending an Attachment from a Display Application ^TOP^

Any display application should be able to send data to another device using any messaging application as a transport. For instance, a user could send a JPEG image from an image viewer to another person via email. This feature is implemented via the Exchange Manager using the _send URL scheme. Because the send capability is has been available since Palm OS 4, many existing display applications already support it.

Guidelines for Messaging Applications

To handle attachment sending from a display application, messaging applications should follow these guidelines:

  • Messaging applications must provide an exchange library that supports the _send URL scheme and register the scheme with the Exchange Manager (see "General Registration Guidelines."). Email applications will prompt the user for additional information (recipient information, subject line, etc.) and add the received data as an attachment to the message.
  • Messaging applications should be able to accept any content type to act as a transport mechanism.

Guidelines for Display Applications

To handle attachment sending, display applications should follow these guidelines:

  • Display applications must use the _send URL scheme to send data to the Exchange Manager. The Send mechanism is a general mechanism that provides the user with a choice of all the transport mechanisms available on the device that support the _send scheme (for example, Bluetooth, email, etc.).

    The sample code below shows how to send or beam data. The question mark in the name field means that on OS 4.0 and higher, it'll display a dialog to let the user choose which transport to use (for example, IR, Bluetooth, SMS, etc.).


    status_t err; 
    ExgSocketType exgSocket; 
     
    // Fill out exgSocket with the description of the data and the 
    // package's "address" 
    MemSet(&exgSocket, sizeof(exgSocket), 0); 
    exgSocket.description = "SuperApp data"; 
    exgSocket.name = "?_send;_beam:SuperAppData.sad"; 
    exgSocket.type = "application/x-superappdata"; 
     
    err = ExgPut(&exgSocket); // open the connection 
    ExgSend(&exgSocket, theData, theDataSize, &err); // send the data 
    err = ExgDisconnect(&exgSocket, err); // that's all! 
    

  • Display applications must set at least the type information (exgSocket.type). Name information (exgSocket.name), including file extension and description information (exgSocket.description), should also be provided. This allows messaging applications to format outgoing messages correctly, with the proper MIME content-type fields.

Email Application Guidelines ^TOP^

Email applications should follow these guidelines to support the mailto scheme and the helper APIs.

Support for Mailto URL Scheme

Applications like a web browser must be able to launch an email application to start composing a new message. In contrast to the _send scheme, the mailto URL automatically implies email as a transport medium and allows applications to provide additional information, like recipients, subject line, etc.

Therefore:

  • Email applications must implement the mailto URL scheme and register the scheme with the Exchange Manager. For more information on the mailto scheme, see RFC 2368 at http://www.ietf.org/rfc/rfc2368.txt
  • The application must display the message content before a message is sent. This prevents malicious applications from sending uncontrolled spam without the user's knowledge.

Support for Helper API

Messaging applications should register their services with the helper API as described in "Helper Notifications" in Exploring Palm OS: Programming Basics. In particular, email applications should support the mail service class.

Summary of Exchange Manager ^TOP^