When using Profiles Engine Wrapper API, the first step is to create the
engine by using ProEngFactory::NewEngineLC
. It should be
noted, that for all operations that modifies Profiles data, the client process
must have WriteDeviceData
capability. For reading Profiles
data, no capabilities are needed.
Below is an example of the initialization process of the Profiles Engine Wrapper API.
// Create an engine instance: MProEngEngine* engine = ProEngFactory::NewEngineLC();
After the engine has been created, the ID of the active profile can be got (Use case 1.) like below.
// Get the ID of the active profile TInt activeId( engine->ActiveProfileId() );
Changing the active profile (Use case 2.) can be done as in the code snippet below.
// Change the active profile to Off-line engine->SetActiveProfileL( KProfileOfflineId );
The class MProEngEngine
offers methods to get the settings
of any profile. MProEngEngine::ActiveProfileLC()
returns
the settings of the profile which is active by the time of the method call. MProEngEngine::ProfileLC(
TInt aId )
returns the settings of the profile with the ID aId
.
Both of those methods have also versions that don’t leave pointers to the
cleanup stack.
The settings returned by MProEngEngine
are contained in
an object of a class implementing the MProEngProfile
interface.
This interface offers methods to get and set the so called “Alert For” groups
for the profile. “Alert For” groups are Contact groups for which an audible
alert should be played if a call comes in from a person who belongs in such
a group in the contacts database. If no groups are set in a profile, it means
that all the calls must be alerted according to the settings of the profile. MProEngProfile
interface
contains also a method for checking the silent status of the profile. This
service is needed for example by the component updating the silent indicator
in the navi pane. Other settings of the profile can be got by using MProEngProfileName,
MProEngTones
and MProEngToneSettings
interfaces.
The references to these interfaces are acquired from the MProEngProfile
interface.
After the client has updated the desired settings of a profile, the changes
has to be committed in by using the method MProEngProfile::CommitChangeL()
.
This method does the actual committing of the changes in the Profiles data
repository.
Below is an example code snippet which reads and modifies some the settings (Use cases 3. and 4.) of the current active profile.
// Get the settings of the active profile: MProEngProfile* activeProfile = engine->ActiveProfileLC(); MProEngToneSettings& ts = activeProfile->ToneSettings(); TBool ringingType( ts.RingingType() ); TProfileRingingVolume volume( ts.RingingVolume() ); // Make sure that the vibrating alert is enabled, if the ringing type // or volume is such that I might not hear the alert: if( ( ringingType == EProfileRingingTypeSilent ) || ( ringingType == EProfileRingingTypeBeepOnce ) || ( ringingVolume < EProfileRingingVolumeLevel3 ) ) { ts.SetVibratingAlert( ETrue ); } // Commit the change in Profiles Data: activeProfile->CommitChangeL(); // Release the resources used: CleanupStack::PopAndDestroy(2); // activeProfile,engine
The names and the IDs of all the profiles can be received in a form of MProEngProfileNameArray
by
calling MProEngEngine::ProfileNameArrayLC()
. Below is an
example code snippet for this use case (Use case 5.).
// Get the list of existing profiles: MProEngProfileNameArray* profileNames( engine->ProfileNameArrayLC() );
Notifications about changes in the Profiles data can be received by implementing
the appropriate Observer interface and by using MProEngNotifyHandler
interface.
A Notify Handler can be created with the factory method ProEngFactory::NewNotifyHandlerL()
.
There are 4 Observer interfaces that the client can implement. The interface
to be implemented depends on the type of changes that the client is interested
in. All the observer interfaces follows the same pattern; they have one method
for handling the notification and one for handling errors. In addition for
implementing the appropriate interface, client must also register for the
corresponding type of notifications through MProEngNotifyHandler
.
When the client does not need notifications anymore it should cancel them
through the Notification Handler. There are cancellation methods for each
type of the notifications and also one method which cancels all the notifications
previously requested from the particular Notification Handler instance.
The notifications about profile changes (in other words, about the event
when someone has called SetActiveProfileL()
from Profiles
Engine) is received through the MProEngProfileActivationObserver
interface.
The registration for these notifications is done by calling MProEngNotifyHandler::
RequestProfileActivationNotificationsL(
MProEngProfileActivationObserver& aObserver )
.
The notifications about the active profile modifications (in other words,
a setting in the current active profile is modified) is received through the MProEngActiveProfileObserver
interface.
A client that needs these notifications will probably need also the profile
activation notifications. However the interfaces are separated because a client
needing activation notifications is not necessarily interested in the active
profile modification notifications.
The notifications about the changes that relates to the contents of a Profile
Name Array can be received through the MProEngProfileNameArrayObserver
interface.
The events that trigger these notifications comprise a profile has been created,
a profile has been deleted and the name of a profile has been changed.
The notifications about the modifications of a specific profile can be
received through the MProEngProfileObserver
interface. These
notifications are tied to the certain profile which ID is given as a parameter
in the registration method. Note however, that the notifications are sent
only about the modifications of the settings in the given profile. So the
activation notification should be received via MProEngProfileActivationObserver
though.
The standard protocol for notification handler usage is:
Create instances of MProEngEngine
, MProEngNotifyHandler
and
the observer implemented by the client
Register for the notifications through MProEngNotifyHandler
giving
a reference to the client-implemented observer as a parameter
Read the Profiles data of interest by using MProEngEngine
Everytime a notification is received re-read the Profiles data of interest
by using MProEngEngine
.
The last item in the list above is important. The data does not get updated
automatically to the MProEngProfile
or MProEngProfileNameArray
objects
once created by the client. It must always be re-read by recreating the object
in question through MProEngEngine
after the notification
is received.
It should also be taken into account when using the notification handler
that only one observer of each type can be attached to one notification handler
instance. The only exception is MProEngProfileObserver
, the
instances of which there can be registered as many as there are profiles in
the device (this means: there can be one MProEngProfileObserver
per
profile registered through the same Notification Handler instance).
Below is an example code of getting notifications of changes (Use case 6.) that have influence on name array contents.
// From CMyProfileNameArrayObserver.h: class CMyProfileNameArrayObserver : public CBase, public MProEngProfileNameArrayObserver { . . . public: /// from MProEngProfileNameArrayObserver void HandleProfileNameArrayModificationL(); void HandleProfileNameArrayNotificationError(TInt aError); . . . private: /// data MProEngProfileEngine* iEngine; MProEngNotifyHandler* iNotifyHandler; MProEngProfileNameArray* iProfileNames; }; // From CMyProfileNameArrayObserver.cpp: void CMyProfileNameArrayObserver::ConstructL() { iEngine = ProEngFactory::NewEngineL(); iNotifyHandler = ProEngFactory::NewNotifyHandlerL(); User::LeaveIfError( iNotifyHandler-> RequestProfileNameArrayNotificationsL( *this )); iProfileNames = iEngine->ProfileNameArrayLC(); CleanupStack::Pop(); // iProfileNames } void CMyProfileNameArrayObserver::HandleProfileNameArrayModificationL() { // Name array data changed, re-read the name array: MProEngProfileNameArray* tmpNames = iEngine->ProfileNameArrayLC(); // Succeeded to read new names, delete the old array object: delete iProfileNames; iProfileNames = tmpNames; CleanupStack::Pop(); // tmpNames } void CMyProfileNameArrayObserver::HandleProfileNameArrayNotificationError(TInt aError) { // Error handling here }
There is one service more offered by Profiles Engine Wrapper API, it can
be used for searching the device (and the memory card) for files that are
suitable to be set as alert tones. This service is provided by MProEngAlertToneSeeker
interface,
which has two methods. FetchAlertToneListL(MProEngAlertToneSeekerObserver&
aObserver)
is used for starting the asynchronous search operation.
This operation may take really long time depending on the amount of tones
in the device. The operation can be cancelled by calling CancelFetch()
.
To use the service, client has to implement the MProEngAlertToneSeekerObserver
interface.
This interface contains a method for receiving a notification when the search
has completed. The array of the path names of the tones is delivered as a
parameter in this method to the caller. The ownership of the array is also
transferred to the client. The other method in this interface is for error
handling. The code snippet below shows an example usage of Alert Tone Seeker
(Use case 7.).
// Client-implemented observer for getting the list of tone files: class CClientImplementedAlertToneSeekerObserver : public CBase, public MProEngAlertToneSeekerObserver { . . . public: /// from MProEngAlertToneSeekerObserver void HandleAlertToneListCompletedL(MDesCArray* aToneList); void HandleError(TInt aError); . . . private: /// data . . . MProEngAlertToneSeeker* iSeeker; MDesCArray* iToneList; }; // : void CClientImplementedAlertToneSeekerObserver::ConstructL() { . . . iSeeker = ProEngFactory::NewAlertToneSeekerL(); // start the asynchronous fetch operation iSeeker->FetchAlertToneListL( *this ); } // Alert tone fetch has completed: void CClientImplementedAlertToneSeekerObserver::HandleAlertToneListCompletedL( MDesCArray* aToneList) { iToneList = aToneList; // Use the tone list here, for example delegate it to a list box etc. } // An error occurred during fetch operation or in the client-implemented handler // method above: void CClientImplementedAlertToneSeekerObserver::HandleError( TInt aError ) { // handle errors here . . . }
Releasing the resources used by MProEngEngine
is done
with Release()
method. Below is an example code snippet of
the usage.
// Release the resources: if( iProfileEngine ) { iProfileEngine->Release(); }
Profiles Engine Wrapper API uses standard Symbian error reporting mechanism. It does not define any panic codes of its own, since all the data received from the client is delivered in object references instead of pointers. Leaves and system wide error codes as function return values are used if the error is recoverable. A client application can handle these errors similarly as a normal Symbian platform application.
Memory consumption of Profiles Engine Wrapper API is directly proportional
to the number of profiles read by the client (if the client does not destroy
them in between). Also if there are huge amount of alert tones in the device
then the list returned by MProEngAlertToneSeeker
may take
a lot of memory.
This API cannot be used by a server component which needs to set a DRM-protected tone as an alert tone. This is because the DRM library used by this API launches some UI notes that are not global. Launching a non-global UI note in a server process will result in a panic.