Using the extended notifier framework

The framework

Notifiers allow components with no direct UI linkage to interact with the user via an interface such as a dialog box. For example, a low level component might want to warn the user about a low battery level. Typically, such a component would not have direct access, or knowledge of, a UI. The solution to this problem is provided by what are known as notifiers and the extended notifier framework. The UI element (the dialog box) is provided by the device's UI through what are known as notifier plug-ins.

The extended notifier framework is a system that loads these plug-in DLLs from Z\sys\bin\notifiers.

These DLLs are expected to export a single factory function at ordinal #1 that returns an array of notifiers. A special notifier target type is supported by makmake. The second Uid for notifiers should be 0x10005522.

The behaviour of notifiers is supplied by providing an implementation of the MEikSrvNotifierBase2 interface . A notifier is associated with a channel and a priority. Priority is used to determine the order of activation if more than one notifier is activated at any time. Priority only affects notifiers on the same channel (for example, a screen or LED). This means that two notifiers can be active at the same time provided that they are on different channels.

The channel and priority used by all the notifiers in the system needs to be considered carefully to avoid them interfering with each other in unexpected ways. The MEikSrvNotifierBase2 derived class also needs to be implemented correctly. Notifiers run in the UIKON server thread and are accessed on the client side via RNotifier. Note that if a notifier panics it will lead to a device reset.

The factory function

The factory function at ordinal #1 is expected to return an array of notifiers. The following is a typical implementation:

EXPORT_C CArrayPtr<MEikSrvNotifierBase2>* NotifierArray()
    {
    CArrayPtrFlat<MEikSrvNotifierBase2>* notifiers=new CArrayPtrFlat<MEikSrvNotifierBase2>(5);
       if (notifiers)
        {
        TRAPD(err, CreateNotifiersL(notifiers));
        if(err)
            {
            TInt count = notifiers->Count();
            while(count--)
                {
                (*notifiers)[count]->Release();
                }
            delete notifiers;
            notifiers = NULL;
            }
        }
    return(notifiers);
    }

Note: Ownership of the notifier array or its contents is not transferred to the framework until this function returns. To avoid memory leaks, all acquired resources must be freed if anything goes wrong part of the way through its processing.

Calling Release() on a notifier should cause that notifier to free all of its resources, and as a minimum should call delete this;. See MEikSrvNotifierBase2::Release().

Returning a Null value from this function causes the framework to leave with KErrNoMemory.

The CreateNotifiersL() function should be implemented as follows:

LOCAL_C void CreateNotifiersL(CArrayPtrFlat<MEikSrvNotifierBase2>* aNotifiers)
    {
    MEikSrvNotifierBase2* notifier;
    notifier = CMyNotifierA::NewL();
    CleanupStack::PushL(notifier);
       aNotifiers->AppendL(notifier);
       CleanupStack::Pop(notifier);
    ... 
    ...
    // typically, repeat this procedure for as
    // many notifiers as are implemented
    // in the plug-in DLL.
    }

Note: Use of the standard Symbian platform technique of using the cleanup stack to hold pointers to allocated objects for as long as these objects have no owner; this prevents memory leaks. For this reason, avoid using a technique such as aNotifiers->AppendL(CMyNotifierA::NewL());, which, although shorter, will result in a memory leak if the AppendL() operation fails.