To create a CCA View Plugin, it is needed to inherit from API classes and
implement at least some of the callback methods based on the need of plug-in
functionality. This API is built on top of ECOM plug-in architecture, so it
is needed to create also a ECOM plug-in resource file.
Implementing new view plug-ins to Contact Centric Application
Implementing only what is mandatory to get the plug-in running
To implement a new view plug-in it is needed to create ECOM plug-in resource
file with some specific values.
RESOURCE REGISTRY_INFO theInfo
{
// UID for the DLL. See mmp files
dll_uid = KMyDllUid;
// Declare array of interface info
interfaces =
{
INTERFACE_INFO
{
// UID of interface that is implemented
interface_uid = 0x2000B1AB;//KCCAppViewPluginBaseInterfaceUID
implementations =
{
IMPLEMENTATION_INFO
{
implementation_uid = KMyCCAViewPluginImplementationUid;
version_no = 1;
display_name = "";
default_data = "";
opaque_data = "500";
}
};
}
};
}
Attention should be paid for the following fields:
-
interface_uid. Here you must use
KCCAppViewPluginBaseInterfaceUID,
which is defined in ccappviewpluginbase.h.
-
opaque_data. This defines the position of the plug-in among the other
plug-ins. The value received from the team responsible of Contact Centric
Application is used.
-
display_name. This defines the display name of the plug-in. If there are
some service tabs in Phonebook , and you want to make the order of the service
tabs in Contact Centric Application the same as the order of the service tabs
in Phonebook, the display name must not be empty and must be identical with
the name of the service tab view in Phonebook. If you do not want to make
the order of the service tabs in Contact Centric Application the same as the
orders of the service tabs Phonebook, this field can be left empty and the
opaque_data is taken into use for positioning of plug-ins. The names of the
service tab views in Phonebook are described in reference document 1.
After this, you need to derive your view class from
CCCAppViewPluginBase (which
is inherited from CCCAppViewPluginAknView). Keep the construction
of the plug-in light, since all plug-ins are constructed while Contact Centric
Application is starting. Leave more time-consuming operations to the PreparePluginViewL call.
class CCCAppMyPlugin : public CCCAppViewPluginBase
{
...
CCCAppViewPluginAknView is inherited from CAknView. CAknView has
pure virtual method for view ID. With plug-in views, this method is used to
return the implementation ID. This is the same as defined in the ECOM resource.
This ID plays a major role to identify the views and the plug-ins with each
other.
TUid CCCAppMyPlugin::Id()const
{
return TUid::Uid( KMyCCAViewPluginImplementationUid );
}
During the activation of the plug-in view
NewContainerL() is
called. Use it to construct your container class inherited from CCCAppViewPluginAknContainer.
void CCCAppMyPlugin::NewContainerL()
{
iContainer = new (ELeave) CCCAppMyContainer();
}
After this, you need to derive your container class from
CCCAppViewPluginAknContainer.
Implement ConstructL() and construct the controls in there.
void CCCAppMyContainer::ConstructL()
{
iLabel = new (ELeave) CEikLabel;
iLabel->SetContainerWindowL( *this );
iLabel->SetTextL( _L("Hello CCApp-world") );
}
Now you should have a running plug-in.
Related APIs
CAknViewCCCAppViewPluginAknContainerCCCAppViewPluginAknViewCCCAppViewPluginBaseConstructL()KCCAppViewPluginBaseInterfaceUIDNewContainerL()PreparePluginViewL
Adding tab graphics
To add a bitmap to be shown in the Contact Centric Application tab, you
need to take the
ProvideBitmapL callback in use from CCCAppViewPluginBase.
This callback is called by Contact Centric Application during the construction.
If this is not implemented in the CCA View Plugin side, the tab is left empty.
void CCCAppMyPlugin::ProvideBitmapL(
TCCAppIconType aIconType,
CAknIcon& aIcon )
{
if ( ECCAppTabIcon == aIconType )
{
CFbsBitmap* bmp = NULL;
CFbsBitmap* bmpMask = NULL;
AknsUtils::CreateIconL(
AknsUtils::SkinInstance(),
KAknsIIDDefault,//skin id
bmp,
bmpMask,
KCCAppMyPluginIconIconFileName,
EMbmCCAppMyPluginIcon,
EMbmCCAppMyPluginIcon_mask );
aIcon.SetBitmap( bmp );
aIcon.SetMask( bmpMask );
}
}
Related APIs
CCCAppViewPluginBaseProvideBitmapL
Adding menu handling
To add plug-in specific menus, add similar resources as with normal AVKON
applications.
RESOURCE AVKON_VIEW r_myplugin_view
{
menubar = r_myplugin_menubar;
cba = R_AVKON_SOFTKEYS_OPTIONS_BACK;
}
RESOURCE MENU_BAR r_myplugin_menubar
{
titles =
{
MENU_TITLE { menu_pane = r_myplugin_menupane; }
};
}
RESOURCE MENU_PANE r_myplugin_menupane
{
items =
{
MENU_ITEM
{
command = 1;
txt = "Hello world";
}
};
}
During the preparations,
CCCAppViewPluginBase's PreparePluginViewL() is
called. It is called only once in plug-in's lifespan. Use it to load a resource
file containing the resources your plug-in needs. Actual loading of menus/softkeys
can be left to base class via calling BaseConstructL() and
the ID of the AVKON_VIEW resource struct.
_LIT( KCCCAppMyPluginResourceFileName, "\\resource\\mypluginrsc.rsc" );
void CCCAppMyPlugin::PreparePluginViewL(
MCCAppPluginParameter& aPluginParameter )
{
TFileName fileName( KCCCAppMyPluginResourceFileName );
BaflUtils::NearestLanguageFile( iCoeEnv->FsSession(), fileName );
iResourceLoader.OpenL( fileName );
BaseConstructL( R_MYPLUGIN_VIEW );
}
Then, in code you can use
DynInitMenuPaneL as in normal
AVKON applications to dynamically modify the menus when the user is opening
them. Also HandleCommandL is used in a similar manner as
with normal AVKON applications. EEikCmdExit, EAknSoftkeyBack, EAknSoftkeyExit and EAknCmdHelp are handled in base classes, so leave handling of those out from plug-in
implementation.
void CCCAppMyPlugin::HandleCommandL( TInt aCommand )
{
// Forward the command handling 1st to base-class.
// The "Exit"- and "Back"-commands are handled there.
CCCAppViewPluginAknView::HandleCommandL( aCommand );
// Add here plugin's own command handling
...
Related APIs
BaseConstructL()CCCAppViewPluginBaseDynInitMenuPaneLEAknCmdHelpEAknSoftkeyBackEAknSoftkeyExitEEikCmdExitHandleCommandLPreparePluginViewL()
Adding activation/deactivation awareness to plug-in
To be able to start and stop plug-in specific notification systems, or
to free resources from use when CCA View Plug-in is deactivated, it is good
to know if the plug-in is currently active or not. This can be done by implementing
AVKON's
DoActivateL and DoDeactivate and
store the call to own member variable etc. Call to base class is needed to
let the base class handle the container creation/deletion.
void CCCAppMyPlugin::DoActivateL(
const TVwsViewId& aPrevViewId,
TUid aCustomMessageId,
const TDesC8& aCustomMessage )
{
// Forward the activation-call to base-class
CCCAppViewPluginAknView::DoActivateL(
aPrevViewId, aCustomMessageId, aCustomMessage );
// Plugin specific implementation
...
void CCCAppMyPlugin::DoDeactivate()
{
// Forward the deactivation-call to base-class
CCCAppViewPluginAknView::DoDeactivate()
...
Related APIs
Adding Help-functionality to plug-in
Contact Centric Application handles the
EAknCmdHelp commands,
so it is enough to add the appropriate menu resource and implement GetHelpContext callback
in the container class.
RESOURCE MENU_PANE r_myplugin_menupane
{
items =
{
#ifdef __SERIES60_HELP
MENU_ITEM
{
command = EAknCmdHelp;
txt = qtn_options_help;
},
#endif // __SERIES60_HELP
MENU_ITEM
{
command = EAknCmdExit;
txt = qtn_options_exit;
}
};
}
void CCCAppMyPluginContainer::GetHelpContext( TCoeHelpContext& aContext ) const
{
aContext.iMajor = iPlugin.Id();
aContext.iContext = HLP_MY_PLUGIN;
}
Related APIs
EAknCmdHelpGetHelpContext
Adding keyhandling to plug-in
Key events can also be handled by plug-in. However some of the key events
are reserved for the Contact Centric Application to take care of plug-in switching
etc. Therefore it is important to first forward the key event to the base
class and use the event only if it was not consumed.
TKeyResponse CCCAppMyPluginContainer::OfferKeyEventL(
const TKeyEvent& aKeyEvent, TEventCode aType)
{
// Forward the key-event 1st to base-class
TKeyResponse returnValue =
CCCAppViewPluginAknContainer::OfferKeyEventL( aKeyEvent, aType );
if ( EEventKey == aType
&& EKeyWasNotConsumed == returnValue )
{
// Plugin keyevent handling
You can also query the reserved keys from Contact Centric Application,
see
MCCAppPluginParameter.
Related APIs
Using MCCAppPluginParameter
MCCAppPluginParameter is received via the PreparePluginViewL call.
This parameter-class can be used to dig information for example from the key
events which are reserved for the Contact Centric Application. This can be
done via ReservedKeys() method. You can also get reference
to MCCAParameter via CCAppLaunchParameter(). MCCAParameter contains
launching related information like the contact link.
Related APIs
CCAppLaunchParameter()MCCAParameterMCCAppPluginParameterPreparePluginViewLReservedKeys()
Setting the title of Plugin View
Each plug-in is responsible for setting the required title in the Title
pane. This is facilitated by calling the base class,
CCCAppViewPluginAknView::SetTitleL(aParam) API.
The value of aParam is set as the title for the Plugin View.
void CCCAppMyPlugin::AnyFunctionL()
{
// Forward the SetTitleL-call to base-class
CCCAppViewPluginAknView::SetTitleL(iTitle);
...
Note: By default, the Plugin View's title is empty. If this API is not
used by the plug-in to set the title, the title set by the previous Plugin
View will be visible. If the previous views title is empty, then even this
Plugin Title pane will be empty.
Related APIs
CCCAppViewPluginAknView::SetTitleL(aParam)aParam
Error handling
Most leavable callback methods to the plug-in are TRAPped. Therefore, most
of the cases are tried to be handled when plug-in leaves at critical point.
Panics are out of reach.
In practise, the leaving plug-in is removed from the plug-in array and
the first plug-in in the array is then activated. Handles at least the cases
if leave occurs in one of the following plug-in methods;
NewL / ConstructL, PreparePluginViewL, NewContainerL and DoActivateL.
DoActivateL call happens in AVKON framework and by default
the last working view is set to be active. To keep the functionality similar
(and simple) in most cases, CIdle callback ResetViewL() is
used. Since recovering should not be an everyday use case, implementation
is a compromise. Recovering functionality is not recursive. If the plug-in
failing is the first one, application is closed.
Related APIs
CIdleConstructLDoActivateLNewContainerLNewLPreparePluginViewLResetViewL()