Implementing the CPosPrivacyNotifier Subclass

To use the Privacy Query and Notification API to create a notifier a licensee must first implement a single notifier class that derives from the Privacy Query and Notification API base class CPosPrivacyNotifier.

The CPosPrivacyNotifier subclass must implement the virtual functions of the base class:

Implementing HandleNewRequestL()

New privacy verification query and notification requests are received by the notifier through CPosPrivacyNotifier::HandleNewRequestL(). The example code below shows how the notifier handles requests sequentially by simply calling a helper function HandleNextRequestL() to get the next request.

void CMyPrivacyNotifier::HandleNewRequestL(TPosQNRequestId /*aRequestId*/)
    {
    if (iIsBusy) // TBool flag which specifies if the notifier is already
        {        // handling a request. If it is, do nothing for now.
        return;
        }

    // Handle the request
    HandleNextRequestL();
    }

HandleNextRequestL()

The example code below shows how the notifier gets the next request to be processed. The code shows how the notifier:

  • Gets an array of all waiting requests by calling CPosPrivacyNotifier::GetRequestsL().

  • Gets the first request in the array and sets it as the current request by calling CPosPrivacyNotifier::SetCurrentRequestL().

  • Checks if the request is a notification, and if so, checks if the request type is supported by calling CPosPrivacyNotifier::NotificationReason(). If the request type is not supported the request is completed by calling CPosPrivacyNotifier::CompleteRequest().

  • Checks if the type of request is a privacy verification (EQuery) or a notification (ENotification) and launches the appropriate dialog for each case.

    Note: LauchQueryDialog() and LaunchNotificationDialog() show the dialogs. Dialog code varies between licensee platforms but it is important that these methods do not launch modal dialogs. The methods must return quickly and not wait for the dialogs to be dismissed.
void CMyPrivacyNotifier::HandleNextRequestL()
    {
    // Read the next request
    RArray<TPosQNRequestId> requests;
    CleanupClosePushL(requests);
    GetRequestsL(requests);

    // Choose next request to handle
    TBool requestFound = EFalse;
    while (!requestFound)
        {
        if (requests.Count() == 0)
            { // There are no requests to handle. Do nothing.
            CleanupStack::PopAndDestroy(); // requests
            return;
            }
        // Read information about the active request
        iActiveRequest = requests[0];
        SetCurrentRequestL(iActiveRequest);

        // In case of notification request, check that notification reason is
        // supported, otherwise complete the request with KErrNotSupported.
        if (RequestTypeL(iActiveRequest) == ENotification &&
            !(NotificationReason() == EPosDecisionByRequestSource ||
            NotificationReason() == EPosVerificationTimeout))
            { // The notification reason is not supported by the UI.
            CompleteRequest(iActiveRequest, KErrNotSupported);
            requests.Remove(0);
            }
        else
            {
            requestFound = ETrue;
            }
        }
    CleanupStack::PopAndDestroy(); // requests

    iIsBusy = ETrue;

    CDesCArrayFlat* requestors = new (ELeave) CDesCArrayFlat
        (KRequestorGranularity);
    CleanupStack::PushL(requestors);
    
    TInt nofRequestors = RequestorCountL();
    for (TInt I = 0; I < nofRequestors; I++)
        {
        CPosRequestor* requestor = RequestorLC(I);
        requestors->AppendL(requestor->RequestorIdString());
        CleanupStack::PopAndDestroy(requestor);
        }

    // Check whether the request is a query or a notification
    if (RequestTypeL(iActiveRequest) == EQuery)
        {
        LaunchQueryDialogL(requestors); // takes array ownership
        }
    else // RequestTypeL(iActiveRequest) == ENotification
        {
        LaunchNotificationDialogL(requestors); // takes array ownership
        }
    CleanupStack::Pop(requestors);
    }

Implementing a method to handle dialog closure

When the mobile device user has responded to the dialog, the notifier must send a response back to the LBS subsystem. In the example code below, the method DialogDismissed() is called when the dialog is closed. The type of request (EQuery or ENotification) and the reason why the dialog was closed is passed as an input parameter to the method.

Note: It is important to note that CPosPrivacyNotifier::CompleteRequest() must be called for both privacy verification (query) requests and privacy notification requests.

Note also how requests are handled sequentially in the code: CPosPrivacyNotifier::HandleNextRequest() is called to process the next request only when the current request is completed.

void CMyPrivacyNotifier::DialogDismissed(TRequestType aRequestType, TInt aDismissReason)
    {

    iIsBusy = EFalse;

    // Complete the request with correct completion code.
    TInt completionCode = KErrNone;
    if (aRequestType == EQuery)
        {
        switch (aDismissReason)
            {
            case EUserChooseAccept : completionCode = KErrNone; break;
            case EUserChooseReject : completionCode = KErrAccessDenied; break;
            case EDialogTimedOut : completionCode = KErrTimedOut; break;
            default : completionCode = KErrGeneral;
            }
        }
    else // aRequestType == ENotification
        {
        switch (aDismissReason)
            {
            case EUserPressedOk : completionCode = KErrNone; break;
            case EDialogTimedOut : completionCode = KErrTimedOut; break;
            default : completionCode = KErrGeneral;
            }
        }
    CompleteRequest(iActiveRequest, completionCode);

    // Handle the next request
    HandleNextRequest();
    }

// Non leaving method for handling the next request
void CMyPrivacyNotifier::HandleNextRequest()
    {
    TRAPD(err, HandleNextRequestL());
    if (err)
        {
        CompleteAllRequests(err);
        }
    }

Implementing HandleRequestCancelled()

A privacy request can be cancelled by the network. The LBS subsystem calls CPosPrivacyNotifier::HandleRequestCancelled() on the notifier to cancel the request. The code example below shows an implementation.

void CMyPrivacyNotifier::HandleRequestCancelled(TPosQNRequestId aRequestId)
    {
    switch (CancelReason())
        {
        case EPosCancelReasonTimeout:
            // Notify the user that the query timed out.
            break;
        default: // Do nothing
            break;
        }

    // We only need to do anything if the request is the one which is currently
    // handled.
    if (iActiveRequest == aRequestId)
        {
        // Close the active dialog
        DismissDialog();
        HandleNextRequest();
        }
    }

Implementing HandleAllRequestsCancelled()

The notifier must implement this method to allow all outstanding requests to be cancelled.

void CMyPrivacyNotifier::HandleAllRequestCancelled()
    {
    // Close the active dialog
    DismissDialog();
    }