USERNAME PASSWORD LOST PASSWORD? REGISTER
"A Complete Mobile Application Development Environment"
Advertisement

Downloads
Documentation
Forums
Blog
Press
Bug Tracking
Creator IDs
Contact Us




Activity Model PDF Print E-mail

In most cases applications are designed to be standalone components. In addition, developers often write applications to assume primary responsibility for maintaining a well-defined set of data. For example, the Contacts application handles information like names and phone numbers, the Calendar application handles the user's agenda, and the Browser deals with Internet navigation. However, the user's primary purpose when using an ACCESS Linux Platform device isn't to run a particular application. Instead, they want to perform tasks that require them to run one or more applications. For instance, they might want to look up a person's phone number, or add an appointment to their calendar, or retrieve the current weather report from the web.

While some tasks can be performed entirely within a single application, many span data sets and therefore applications. For instance, when creating an appointment in the calendar you might need to consult the Contacts application. Or, while perusing an email message, you might need to use the Media Player application to play the contents of an attachment.

Activities and the Activity Model ^TOP^

Any action that takes the user from an application to a view or a form that belongs to a different application, with the intent of performing a specific action, is what is known as an activity. Applications providing such services together with applications employing those services make up the activity model that is supported by the ACCESS Linux Platform.

Note that activities are discrete tasks: a given application is likely to support a number of activities. For instance, the Contacts application allows you to create, delete, and look up contacts; each of these discrete tasks can be exposed as an activity. Table 7.1 shows some typical activities:

Table 7.1  Typical activities

Application

Activity

Description

Phone

dial

Dial a phone number or a string.

accepted

Launch the phone application to display the call list.

SMS+

send

According to parameters, send a vObject, and MMS.

Contacts

store

Create a new contact.

get

According to parameters, get specific contact information.

display

Display a contact.

Audio Player

display

Plays the specified audio file.

Calendar

store

Add a new event to the calendar.

display

Show a specified calendar event.

Camera

record

Capture a picture.

Email

sendemail

Open a compose window with the "to" address filled in or with the specified attachments added.

Browser

open

Open a URL.

Memo

display

Display a memo.

get

Obtain a memo selected by the user.

store

Create a new memo

Programs for ACCESS Linux Platform can, and often are, written both as stand-alone applications and as activity service providers. Applications can employ the services of others, whether those be general-purpose services of the type provided by many of the "core" ACCESS Linux Platform applications (such as are listed in Table 7.1, above) or "custom" services meant only to be used between a small number of specialized applications.

The Platform contains two mechanisms that support the activity model: the ability to launch an application in transient execution mode, and the Exchange Manager, which allows applications to publish the activities that they provide and which allows applications to employ those activities.

Application Execution Modes ^TOP^

On ACCESS Linux Platform, each application runs in its own process and manages its own user interface. Multiple applications can be executed simultaneously, each displaying information on the screen. However, in order to provide a better user experience across applications and typical use cases, the system ensures that only one application is granted full access to the screen at a time. This application is called the "main UI" or "primary" application (sometimes also referred to as the "foreground" application).

Although only one application can be primary, other applications and components can be running, and they can be granted partial or even full access to the screen for a limited time. These other applications fall into two classifications: "background" applications, and "transient" applications. Along with "primary," these three modes work as follows:

Primary
The primary application runs in the foreground and has full access to the screen. When an application is launched as primary, the application that had been running in foreground is requested to quit or move itself to the background. Primary applications are usually launched by the end user. For instance, applications started from the Launcher are launched as primary.
Background
Background applications can be thought of as running "behind" the main UI. They can display dialogs on top of the main UI application, although to minimize confusion they should do so sparingly.
Transient
An application launched as transient is displayed on top of the primary application's UI. Applications launched as transient usually run only for a short time, and usually to provide some service at the behest of the foreground application.

Foreground and background applications are discussed elsewhere in this document (most of this book discusses primary applications; background processing is discussed in Chapter 14, "Background Processing,"). Transient mode applications, however, are key to the "application model" supported by ACCESS Linux Platform and so are discussed further here.

Transient Mode ^TOP^

An application can be launched as "transient" to another application, appearing to the user as part of the original, primary application. For instance, suppose the user is in the Phone application, adding a new "favorites" entry. If the data for the "favorite" already exists in the Contacts application, the user should be able to invoke the Contacts application, select an entry, and then return to the Phone application with the relevant data filled in. Throughout the task, they should feel that they are still in the Phone application. For instance, they would not expect to see the Phone application close when the Contacts application is brought up. Instead, they should see something like what is illustrated in Figure 7.1.

Figure 7.1  Invoking the Contacts application as an activity

One way to implement this scenario would be to duplicate the part of the Contacts application that displays and allows the user to select a particular contact. However, this approach is inefficient and error-prone: each application that wanted to provide this service would have to include the same code, and any changes to the way that contact data is stored or accessed would require all of those applications to be rewritten. Another approach would be to launch the Contacts application as primary. However, this exposes the entire Contacts application to the user, rather than focusing them in on the single task they need to perform: selecting a contact from the list of existing contacts.

A better approach is to let the Contacts application perform just this simple activity—displaying contacts to the user and letting them select one—and to invoke it without shutting down the Phone application. In an instance such as this, the Contacts application is launched as transient.

There are three key differences between a primary application and a transient one:

  • When a transient application is launched, the current primary application remains primary and continues to run. However, the transient application's UI is rendered on top of the primary application's UI. Compare this with the launching of a primary application, which forces the previous primary application to be shut down or moved to the background.
  • A transient application is logically connected to the primary application in that if the user switches to an altogether different application (typically, by pressing the "Home" key to bring up the Launcher), both the transient application and the primary application are shut down. This makes sense, since from the user's viewpoint the service provided by the transient application appears to be part of the primary application; they don't necessarily know that the service is being provided by an altogether different application.
  • When the user has completed the activity provided by the transient application (for instance, in our example above when the user has selected a contact), the transient application exits and the user once again sees the UI presented by the primary application. This differs from the usage model that a primary application normally employs: when the user is done with the primary application, they either switch to another primary application, or they shut off the device. The concept of "exiting" a primary application isn't part of the ACCESS Linux Platform's application model.

Note that the user doesn't directly launch an application as transient. Instead, the transient application is launched on their behalf either by the current application or by the Exchange Manager (or by the current application through the Exchange Manager). If your application launches another with the ALP_APP_TRANSIENT launch code rather than the ALP_APP_PRIMARY launch code, that application will be launched as transient to yours. Of course, simply launching the application as transient is probably not enough: you'll also want to have that application focus on just the desired task. Thus, you'd want to supply one or more additional launch codes and parameters that specify the task to be performed.

While the launch code mechanism can be used for this purpose, more commonly you'll use the Exchange Manager to request a service from another application.

Exchange Manager ^TOP^

The Exchange Manager is a central system broker in charge of the communication between different applications or servers. It facilitates data exchange between client applications, which are applications requesting services, and handlers, which are the applications, libraries, and servers that perform the requested services. While originally designed simply to pass data back and forth, in ACCESS Linux Platform the Exchange Manager has been extended to become a general purpose mechanism for announcing and utilizing services provided by applications, libraries, and servers. This makes it an ideal mechanism to support the ACCESS Linux Platform activity model.

Applications use the Exchange Manager to inform the system of the kind of actions they can handle, such as dialing a phone number or storing a vCard as a contact. In order for a client application to use a service that has been registered with the Exchange Manager, the application need only send a request with the proper information—a verb and a set of data—to the Exchange Manager. The Exchange Manager determines which handlers can deal with requests of that type and invokes the appropriate application (passing in the verb and any data) in transient mode. Depending upon how the handler is designed, and depending upon the verb and data supplied, the application providing the service can provide a subset of its services or, if necessary, can act as if it had been launched normally.

When the handler application has completed the requested task, it exits and the primary application is once again revealed. All of this is handled automatically by the operating system and the Exchange Manager; a client application simply requests the service and then proceeds to act upon the results.


NOTE: Because the handler application is transient to the primary application, if the user switches to yet another application—by pressing the Home key, for instance—both the handler application and the client application will be shut down, at which point the new application is launched.

The Role of the Exchange Manager ^TOP^

The Exchange Manager provides all of its mechanisms via a daemon and a set of APIs to:

  • register services
  • enable a client application to request a given service
  • dispatch the service request to the appropriate handler in charge of "executing" the request.

It is important to note that a client application does not specify which application should provide the service: it requests a service without actually knowing which application will process it. The client application only needs to know what action the provider performs, and upon what kind of data. It is up to the Exchange Manager to take care of the request and pass back any results to the client. By not specifying a specific application to handle the request, one handler can easily be replaced by another without requiring changes to the client application. In addition, multiple applications can register to handle a given request. This makes the activity mechanism supported by the Exchange Manager extremely flexible and powerful: as the user adds new applications to their device, existing applications can gain new or improved capabilities.

The term "Exchange" is inherited from the Garnet OS and may be somewhat confusing. Indeed, in ACCESS Linux Platform this component is extended to exchanging to any kind of service (display an image, dial a phone number, etc.) and is not limited to exchanging data (for example, sending over Bluetooth).

Services ^TOP^

Each service is described by a verb (action) and a subject upon which the verb acts (usually, a MIME type). The combination of verb and subject defines a specific service to the Exchange Manager. To customize the service's behavior, parameters can be associated with the service. For instance, a service could be "store" (the verb) and "vObject" (the subject), with the actual object to be stored attached to the service request. Another service could be "display" (the verb) and "jpeg" (the subject). Or, a somewhat more complex service might be "get contact": if parameters are supplied they specify the contact to be returned, and if no parameters are supplied, the list of contacts is displayed and the user is allowed to select one. Either way, information about the contact (perhaps the entire vCard) is returned.

The standard applications, libraries and servers that make up ACCESS Linux Platform provide (and themselves employ) a great many Exchange Manager services. For a detailed list of those services that are supplied by most devices running ACCESS Linux Platform, see Appendix B, "Exchange Verbs." Note that depending upon the manufacturer some devices may omit certain components, and thus on those devices some services may not be available. Also, some devices may provide additional services.

Both verbs and data types are encoded as strings. The strings themselves have little meaning to the Exchange Manager; primarily, they are an agreed-upon protocol between the service provider (in the form of an exchange handler) and the client applications. Many of the verbs and data types supported by the handlers that make up ACCESS Linux Platform have constants defined that can and should be used in place of the actual strings. Not all do, however; when employing some services you need to provide the actual strings. When developing your own services, you can either define your own strings, or, if the service is similar to an existing one, use the same verb and/or data type strings employed by other applications. Note, however, that there cannot be more than one active handler application registered for a given combination of verb and subject that has already been registered for by another handler; for more information, see the section titled "Registering a Handler."

Basic Procedures ^TOP^

The following sections walk through the basic procedures you use when working with the Exchange Manager: requesting a service, and serving a handler.

Requesting a Service

The application that wants to request a service via the Exchange Manager should:

  1. Create an exchange request (an AlpExg2Request) with alp_exg2_request_create().
  2. Set relevant parameters defining the request: verb and subject. Do this by calling alp_exg2_request_set_verb() and alp_exg2_request_set_subject() if you have not already set them in alp_exg2_request_create().
  3. Set additional parameters as needed by the handler. For this you'll need to know the required and optional parameters that are needed by the handler for the verb/subject combination; see Appendix B, "Exchange Verbs," for a list of the command services provided by the standard ACCESS Linux Platform handlers. Use the following functions to specify parameters:
    • alp_exg2_request_int_parameter_set()
    • alp_exg2_request_string_parameter_set()
    • alp_exg2_request_blob_parameter_set()

      Parameters are identified by name; a given request can take any number of parameters of any of the above types. Also note that parameters can be designated as optional, depending upon the service being provided.

  4. If needed, specify data objects to be attached to the request. For instance, when storing a vCal (a calendar entry) you would specify the vCal object to be stored. You can specify a data object by using alp_exg2_request_object_add_by_fd(), alp_exg2_request_object_add_by_file(), or alp_exg2_request_object_add_by_ptr()).
  5. Once the request has been constructed with the needed parameters, call alp_exg2_request_execute_sync() to ask for the service to be performed.
  6. Examine the return code from the alp_exg2_request_execute_sync() call to ensure that the request was processed as desired. The request handler can pass back any value it deems appropriate, so this return code can indicate more than just whether or not the function call succeeded.
  7. Obtain any values returned through parameters. Note that just as when making a function call, parameters can be used either to pass data to the handler, to return data from the handler, or both.

    The functions you use to obtain parameter values neatly mirror those used to set parameter values. Again, note that parameters are identified by name, and there can be multiple parameters of a given type.

    • alp_exg2_request_int_parameter_get()
    • alp_exg2_request_string_parameter_get()
    • alp_exg2_request_string_parameter_const_get()
    • alp_exg2_request_blob_parameter_get()

      If the handler returns a data object, you can get them using the following functions:

    • alp_exg2_request_object_rcv_info()
    • alp_exg2_request_object_rcv_by_file()
    • alp_exg2_request_object_rcv_by_fd()
    • alp_exg2_request_object_rcv_by_ptr()

The code in Listing 7.1 shows how to construct and execute a simple exchange request. This particular request is handled by the Contacts application; it displays the list of contacts in the contacts database and allows the user to select one (the user can decline to choose one by clicking the Cancel button). The locally unique ID of the selected contact within the contacts database is returned.

Listing 7.1  Sample exchange request


alp_status_t GetContact(AlpLuid *contactLuid) { 
AlpExg2Request exgReq; 
int32_t tmpContLuid; 
alp_status_t err; 
// Default return value 
*contactLuid = 0; 
// Create the exchange request 
err = alp_exg2_request_create(&exgReq, ALP_EXGMGR_GET_VERB, 
ALP_EXGMGR_CONTACTS_MIME_TYPE);
<- the two defines here are not defined by exgmgr. 
// Fill in the exchange request 
err = alp_exg2_request_string_parameter_set() (exgReq, 
"contactType",ALP_EXG2_PHONESTRING_SUBJECT); 
// Execute it 
err = alp_exg2_request_execute_sync(exgReq); 
if(err == (alp_status_t)ALP_EXG2_USERCANCEL_ERR){ 
// the user clicked "cancel" 
goto Exit; 
} 
if(err != ALP_STATUS_OK){ 
// there was some problem with the request 
goto Exit; 
} 
// Get back the contact luid 
err = alp_exg2_request_int_parameter_get(exgReq, 
"contactLuid", &tmpContLuid); 
if(contactLuid != NULL){ 
*contactLuid = (AlpLuid)tmpContLuid; 
} 
Exit: 
// Deallocate the request 
alp_exg2_request_delete(exgReq); 
return err; 
} 

Providing a Service

A handler application that provides a service for a given verb and subject must declare it to the Exchange Manager with alp_exg2_handler_register_launch(). Once this is done, the Exchange Manager will invoke the handler whenever a request with that verb and subject is made.

Registering a Handler

A given application can register for many different verb and subject combinations. For instance, the Audio Player registers the verb ALP_EXGMGR_DISPLAY_VERB (which plays an audio file) multiple times, with a number of different data types including "audio/mpeg", "audio/x-ms-wma", "audio/x-wav", and "audio/mid", among others. When specifying a data type, certain wildcards are allowed. As an example, the File Manager application registers the ALP_EXGMGR_STORE_VERB verb (store) with the data type "*", allowing it to store and register with the Media Cataloger files of any type.

Before the service your application provides can be used, your application must have registered itself as a handler. While you could register as a handler when your application is run, that means that it won't be registered as a service provider until it has been run for the first time. As well, there is no need to reregister as a handler each time the application is run; exchange handler registrations are persistent and survive soft resets. The best time to register most exchange handlers is when the handler application is installed. As documented under "Application Installation Notifications," you do this by indicating in your application's manifest file that you wish to receive installation notifications. Then, in response to an ALP_NOTIFY_EVENT_NOTIFY_REGISTER notification, you register your application as an exchange handler.

The call to register yourself as an exchange handler is relatively simple. For example, a hypothetical application that provides a service to add two integers and return the result might register itself like this:


status = alp_exg2_handler_register_launch("plus", NULL, 
"integer","bar:com.example.apps.handlertest", 
ALP_EXG2_HANDLER_LOCAL_ONLY, 
ALP_EXG2_HANDLER_IS_NOT_REENTRANT); 

The first and third parameters to the alp_exg2_handler_register_launch() call are the verb and subject, respectively. The fourth parameter identifies the bundle that should be invoked when a request is made with the named verb and subject. And the last two parameters indicate the following:

iLocalOnly
Specifies that this handler will only execute requests originating from the local device.
iReentrant
Specifies whether or not this handler may be reentered. If set to ALP_EXG2_HANDLER_IS_NOT_REENTRANT, simultaneous incoming requests for this handler are dispatched one at a time.

See the reference documentation for the alp_exg2_handler_register_launch() function for complete details on all of its parameters.

Implementing the Handler

When the Exchange Manager gets a service request, it dispatches it to the appropriate handler. A registered handler is either launched, relaunched, or called back, depending upon whether or not the service is provided by an application or a server, and, if by an application, whether or not the application is running. It must then:

  1. Call alp_exg2_request_receive_start() to get the request.
  2. Extract all needed data from the request with alp_exg2_request get functions such as alp_exg2_request_get_verb() and alp_exg2_request_string_parameter_get(). Note that these are the same functions you use in a client application to extract returned parameters after a service has been performed.
  3. Perform the requested service.
  4. Set any return parameter values using alp_exg2_request set functions. Note that these are the same functions you use in a client application to set parameters when constructing an exchange request.
  5. Call alp_exg2_request_receive_complete() to signal that processing of the request is complete, passing back an appropriate return value. The Exchange Manager passes the request back to the client application.

Your handler application is notified of an incoming exchange request with an ALP_APP_EXCHANGE launch code. The parameter immediately following this launch code contains the request ID value that you use with alp_exg2_request_receive_start() function to obtain the request itself. Thus, as part of your launch code processing you might do something like that shown in Listing 7.2

Listing 7.2  Detecting an exchange request


if(strcmp(argv[i], ALP_APP_EXCHANGE) == 0){ 
	AlpExg2RequestId requestID; 
 
	// extract request ID from the next parameter 
	sscanf(argv[i+1], "%p", &requestID); 
	HandleExchangeRequest(requestID); 
} 

The code in Listing 7.3 shows how, given a request ID, you would receive the request, obtain any parameters passed in with the request, do the processing, set return parameter values, and complete the request, passing back a status code to the client application. In this simple example we have only registered for a single verb and subject; thus, we don't need to retrieve the request's verb and/or subject and conditionally process the request based upon those values. Many applications register for multiple verb and subject combinations and thus do need to differentiate between the exchange request types. Do this by obtaining the request's verb (with alp_exg2_request_get_verb()) and the subject (with alp_exg2_request_get_subject()); your handler can then execute conditionally based upon the verb and subject values.

Listing 7.3  A basic exchange handler


void HandleExchangeRequest(AlpExgRequestId requestID){ 
	AlpExg2Request request; 
	alp_status_t status; 
	int32_t left, right, sum; 
 
	status = alp_exg2_request_receive_start(&request, requestID); 
 
	// get verb and/or subject here if this handler deals 
	// with more than one request type 
 
	// get parameters 
	status = alp_exg2_request_int_parameter_get(request, 
		"left", &left); 
	status = alp_exg2_request_int_parameter_get(request, 
		"right", &right); 
 
	// perform the request 
	sum = left + right; 
 
	// set the result 
	status = alp_exg2_request_int_parameter_set(request, 
	"sum", sum); 
 
	// complete the request 
	alp_exg2_request_receive_complete(request, ALP_STATUS_OK); 
} 

Listing 7.4 shows how a client application would invoke the service provided by our sample exchange handler. Note that for this example the verb is "plus", the subject is "integer", and there are three parameters: "left" and "right" are integer-valued input parameters, while "sum" is an integer-valued output parameter. Lastly, while our sample exchange handler always returns a status value of ALP_STATUS_OK, in reality it probably would be written to return other values. The client application checks the value returned from alp_exg2_request_execute_sync(); this is the value that was set by the handler as the second parameter to the alp_exg2_request_receive_complete() call.

Listing 7.4  Employing the sample exchange handler


alp_status_t GetSum(int32_t left, int32_t right, 
	int32_t *sum) { 
 
	AlpExg2Request exgReq; 
	alp_status_t err; 
 
	// Default return value 
	*sum = 0; 
 
	// Create the exchange request 
	err = alp_exg2_request_create(&exgReq, "plus", "integer"); 
 
	// Fill in the exchange request 
	err = alp_exg2_request_int_parameter_set(exgReq, "left" "left"); 
	err = alp_exg2_request_int_parameter_set(exgReq, "right" "right"); 
 
	// Execute it 
	err = alp_ex2g_request_execute_sync(exgReq); 
	if(err == ALP_STATUS_OK){ 
		err = alp_exg2_request_int_parameter_get(exgReq, "sum",
			sum); 
	} 
 
	// Deallocate the request 
	alp_exg2_request_delete(exgReq); 
 
	return err; 
} 

 

Add as favourites (61) | Quote this article on your site | Views: 1206

Be first to comment this article
RSS comments

Only registered users can write comments.
Please login or register.

Powered by AkoComment Tweaked Special Edition v.1.4.6
AkoComment © Copyright 2004 by Arthur Konze - www.mamboportal.com
All right reserved

 


© 2008 ACCESS Developer Network    |    Joomla! is Free Software released under the GNU/GPL License.    |    ACCESS Global Website
Events Support Community Platforms Home