# Accessing Services

Services provide access to device applications, hardware, the system, cloud computing, and more. The same services that are available to JavaScript apps are also available to Plug-in apps, though the calling format is somewhat different. All services are called asynchronously, and Plug-in apps can call services with or without a callback function.

## Callback function signature

Callback functions used when requesting a response from a service must have the following `PDL_ServiceCallbackFunc` type signature:

>     PDL_bool <callback function name>(PDL_ServiceParameters *params, void *user);

Argument | Type | Description
--- | --- | ---
params | `PDL_ServiceParameters` | Pointer to a hidden type used to provide context and pass data.
user | pointer | A pointer or four-byte field used to identify who is invoking the callback function. An app, for instance, could be waiting on responses from any number of services and need a way to identify one from the other.

## Calling a Service

When calling a service, a Plug-in app has two options:

- Call a service without a response.
- Call a service, giving it a callback function to handle a response.

### Calling a service without a response

To invoke a service without a response, use this call:

>     PDL_Err PDL_ServiceCall(const char *uri, const char *payload);

Argument | Type | Description
--- | --- | ---
uri | string | Service's URI (Uniform Resource Identifier). Has the form: `"palm://<service name>/<service type>"`. For example: `"palm://com.palm.applicationManager/launch"` -- call the Application Manager's launch (an app) service.
payload | string | JSON (JavaScript Object Notation) style parameters. For example: `"{ par1:"val1", par2:"val2", ...}"` Note that, in C code, the inner double quotes would need to be escaped with a backslash (\").

For example:

>     PDL_ServiceCall("palm://com.palm.applicationManager/launch", "{ \"id\":\"com.palm.app.email\"}");

This invokes the system's Application Manager service to launch the Palm's resident email application. Note the use of the backslash character ("\") to allow the use of a double quote within a double quote.

If you were calling this from JavaScript, the call would look like this:

>     this.controller.serviceRequest('palm://com.palm.applicationManager',
>       {
>           method: 'launch',
>           parameters: { id: 'com.palm.app.email' }
>       }
>     );

Keep in mind this difference in calling format when you are invoking other services.

### Calling a service with a callback response

To invoke a service with a callback function to handle a response, use this call:

>     PDL_Err PDL_ServiceCallWithCallback( const char *uri, const char *payload,
>       PDL_ServiceCallbackFunc callback, void *user, PDL_bool removeAfterResponse);

Argument | Type | Description
--- | --- | ---
uri | string | Service's URI (Uniform Resource Identifier). Has the form: `"palm://<service name>/<service type>"`.
callback | `PDL_ServiceCallBackFunc` | Callback function for handling response.
payload | string | JSON (JavaScript Object Notation) style parameters. For example: `"{ par1:"val1", par2:"val2", ...}"`. Note that, in C code, the inner double quotes would need to be escaped with a backslash (\").
user | pointer | Can be a pointer to anything or even used as four-byte value. Sent back in callback invocation and can be used to uniquely identify service source.
removeAfterResponse | `PDL_bool` | `PDL_TRUE` if no further callbacks after first; `PDL_FALSE` otherwise.

For example:

>     PDL_bool DisplayCallback(PDL_ServiceParameters *params, void *user)
>     {
>       char result[10];
>       if (PDL_ParamExists(params, "state"))
>       {
>           PDL_GetParamString(params, "state", result, 10);
>           fprintf(stdout, "Display state =%s\n", result);
>       }
>       else
>       {
>           fprintf(stdout, "Did not get display state\n");
>       }
>       return PDL_TRUE;
>     }

>     //**
>     //** Get state of display.
>     //**
>     void GetDisplayStatus()
>     {
>       PDL_ServiceCallWithCallback("palm://com.palm.display/status", "",
>           DisplayCallback, NULL, PDL_TRUE);
>     }

Note the use of the `PDL_ParamExists` and `PDL_GetParamString` calls for parsing the string value returned. There are four calls for parsing returned callback values:

- `PDL_bool PDL_ParamExists(PDL_ServiceParameters *params, const char *name);`

- `void PDL_GetParamString(PDL_ServiceParameters *params, const char *name, char *buffer, int bufferLen);`

  `Returns "" by default.`

- `int PDL_GetParamInt(PDL_ServiceParameters *params, const char *name);`

  `Returns 0 by default.`

- `double PDL_GetParamDouble(PDL_ServiceParameters *params, const char *name);`

  `Returns 0.0 by default.`

- `PDL_bool PDL_GetParamBool(PDL_ServiceParameters *parms, const char *name);`

  `Returns PDL_FALSE if the parameter does not exist.`

These functions work pretty much the same. `PDL_ParamExists` checks if a named parameter has been passed to a callback function. The other three functions parse the value of a named parameter depending on type.

### Unregistering a service callback

In the `PDL_ServiceCallWithCallback` call, the `removeAfterResponse` boolean parameter indicates if the callback should be invoked one-time only. If not one-time `(PDL_TRUE)`, it can be invoked indefinitely. However, you can stop any further callback invocations with this call:

>     PDL_Err PDL_UnregisterServiceCallback(PDL_ServiceCallbackFunc callback);

For example:

>     PDL_Err err = PDL_UnregisterServiceCallback(DisplayCallback);