S60 Map and Navigation Provider API |
DN078378 |
CONFIDENTIAL |
Version |
Date |
Status |
Description |
---|---|---|---|
1.0 |
21.02.2007 |
Approved |
|
|
|
|
|
![]() |
This API provides interface for implementation by Map and Navigation Provider applications. It enables these applications to provide their map, navigation and geocoding services to the interested client applications in the system. It also defines how the provider application registers its support to these services within the system. This API is based on Server Application Service API concept (see Symbian OS documentation for details).
![]() |
This is a Framework API: the client has to implement classes and methods defined by this API. It is intended for applications, which are capable of map, navigation and geocoding services and want to expose those to other applications. Further in the document these services will be referred to as "map and navigation services".
This API does not implement map and navigation services itself but instead is a server side of a gateway between client applications and provider applications, which actually implement map views, navigation and geocoding requests. The client side of this gateway is represented by following APIs:
![]() |
The main use cases provided by the API are the following:
![]() |
These classes represent map and navigation services, which can be implemented by provider application. They are derived from CMnServiceBase class, which is an extension to CAknAppServiceBase.
In addition to the C++ classes, this API defines resource data structure MN_SERVICE_INFO, which is used in declaration of map and navigation services supported by provider application.
![]() |
![]() |
Client applications use APIs defined by Map and Navigation Framework to access Map and Navigation services. Services are defined by this API and implemented by provider applications. Map and Navigation FW serves as a gateway between clients and providers.
There may be several provider applications in the system, which implement Map and Navigation services, and in order to expose these services to clients, provider applications must register in Map and Navigation FW. This will allow the system to find the provider application when a client application requests map and navigation services.
Registration consists of two mandatory steps:
These steps are described in details in next chapters.
![]() |
There are three Map and Navigation services defined in MnAppServiceUids.hrh. They correspond to three service classes defined by this API as shown in the following table. Applications may support all of these services or only some of them. If an application declares support for a service, it means that this application implements appropriate service classes defined by this API.
Service | Description | Implementation |
---|---|---|
KMnAppMapViewService | MapView service | CMnMapViewServiceBase |
KMnAppNavigationService | Navigation service | CMnNavigationServiceBase |
KMnAppGeocodingService | Geocoding service | CMnGeocodingServiceBase |
KMnAppMapImageService | MapImage service | CMnMapImageServiceBase |
Which services are supported is declared in application registration resource file (usually named in form MyApplication_reg.rss). This is generic technique for application servers and more details on that can be found from "Server applications" article in Symbian OS document chapter "Application framework". Here only specifics related to Map and Navigation FW will be covered.
Provider application lists implemented services in the service_list field of the APP_REGISTRATION_INFO structure, defined in appinfo.rh as shown below:
RESOURCE APP_REGISTRATION_INFO { ... service_list = { SERVICE_INFO { uid = KMnAppMapViewService; ... }, ... }; ... }
In this example, the application supports MapView service. Literally it means that when queried by Application FW this application provides implementation of this service. (Application returns its own implementation of the CMnMapViewServiceBase class.) It is also used when Map and Navigation FW searches for implementations of MapView service for a client.
Base service classes, defined in this API cover the whole services, but applications are not required to support all the functionality defined in these services. The application must specify what pieces of functionality, or "features", of each service are supported. In MnAppServiceUids.hrh file, the following service features are defined:
Service | Features | Description |
---|---|---|
KMnAppMapViewService | KMnSvcFeatureShowMap | Displaying map with landmarks and current location. |
KMnSvcFeatureSelectFromMap | Selecting location from map. | |
KMnAppNavigationService | KMnSvcFeatureNavigateTo | Basic navigation. |
KMnAppGeocodingService | KMnSvcFeatureCoordToAddr | Coordinate to Address conversion. |
KMnSvcFeatureAddrToCoord | Address to Coordinate conversion. | |
KMnSvcFeaturePlainAddrToCoord | Plain-string-address to Coordinate conversion. | |
KMnAppMapImageService | KMnSvcFeatureVectorMap | Rendering of scalable vector-based map. |
KMnSvcFeatureSatelliteImage | Rendering of map image from satellite photos of Earth. |
Applications must explicitly specify, which features of each service are supported, because this information is used by Map and Navigation FW to improve performance of client's requests. For example, if it is known that the client wants to show map views only, but is not interested in selection from map, then M&N FW will return all providers, which support KMnSvcFeatureShowMap regardless of support of KMnSvcFeatureSelectFromMap. This allows selected support for provider applications and fine-grained search for clients.
Standard SERVICE_INFO structure does not have such mechanisms, but allows extensions via its opaque_data field. Application must declare separate resource of type MN_SERVICE_INFO (from mnserviceinfo.rh) in its resource file and list supported features in the service_features field and link it from SERVICE_INFO, as shown below.
RESOURCE MN_SERVICE_INFO r_testprovider_mapview_opaquedata { service_features = KMnSvcFeatureShowMap | KMnSvcFeatureSelectFromMap; }
In this example, application declares support for both features of KMnAppMapViewService.
The complete example of registration file of hypothetical "TestProvider" application, which fully supports Map and Navigation services, is given below.
#include <appinfo.rh> #include "mnappserviceuids.hrh" #include "mnappservices.hrh" #include "mnserviceinfo.rh" #include <testprovider.rsg> UID2 KUidAppRegistrationResourceFile UID3 0x0313200B RESOURCE APP_REGISTRATION_INFO { app_file = "TestProvider"; localisable_resource_file = "\\resource\\apps\\testprovider"; localisable_resource_id = R_TESTPROVIDER_LOCALISABLE_APP_INFO; service_list = { // declare support for MapView service SERVICE_INFO { uid = KMnAppMapViewService; datatype_list = {}; opaque_data = r_testprovider_mapview_opaquedata; }, // declare support for Navigation service SERVICE_INFO { uid = KMnAppNavigationService; datatype_list = {}; opaque_data = r_testprovider_navigation_opaquedata; }, // declare support for Geocoding service SERVICE_INFO { uid = KMnAppGeocodingService; datatype_list = {}; opaque_data = r_testprovider_geocoding_opaquedata; }, // declare support for MapImage service SERVICE_INFO { uid = KMnAppMapImageService; datatype_list = {}; opaque_data = r_testprovider_mapimage_opaquedata; } }; } // Declare feature support for MapView service RESOURCE MN_SERVICE_INFO r_testprovider_mapview_opaquedata { service_features = KMnSvcFeatureShowMap | KMnSvcFeatureSelectFromMap; // all features supported } // Declare feature support for Navigation service RESOURCE MN_SERVICE_INFO r_testprovider_navigation_opaquedata { service_features = KMnSvcFeatureNavigateTo; // all features supported } // Declare feature support for Geocoding service RESOURCE MN_SERVICE_INFO r_testprovider_geocoding_opaquedata { service_features = KMnSvcFeatureCoordToAddr | KMnSvcFeatureAddrToCoord | KMnSvcFeaturePlainAddrToCoord; // all features supported } // Declare feature support for MapImage service RESOURCE MN_SERVICE_INFO r_testprovider_mapimage_opaquedata { service_features = KMnSvcFeatureVectorMap | KMnSvcFeatureSatelliteImage; // all features supported }
Note that the datatype_list field of the SERVICE_INFO structure is not used: there is no datatype associated with Map and Navigation application services.
![]() |
Clients use Map and Navigation Provider Discovery API to get information about available provider applications. The CMnProvider class of that API gives more information about provider application than can be specified in registration resource file: version and localized vendor name.
This information is taken from applications installation package, which is required as part of application registration in Map and Navigation FW. For ROM-based applications a stub installation package must be provided. Installation package is also required for security reasons.
Below is an example of installation package source file for the TestProvider application:
; Installation file for TestProvider application ; Language - standard language definitions &EN ; UID and version are used by Map and Navigation FW #{"MnTestProvider"},(0x0313200B),1,2,4 ; Localised Vendor name - also used by Map and Navigation FW %{"Vendor-EN"} ; Unique Vendor name :"Vendor" ;Supports S60 3.1 [0x102032BE], 0, 0, 0, {"S60ProductID"} ; Files to install "\epoc32\release\ARMV5\UREL\testprovider.exe"-"!:\sys\bin\testprovider.exe" "\epoc32\data\z\resource\apps\testprovider.rsc"-"!:\resource\apps\testprovider.rsc" "\epoc32\data\z\private\10003a3f\apps\testprovider_reg.rsc"-"!:\private\10003a3f\import\apps\testprovider_reg.rsc"
See details about installation packages in Symbian OS documentation.
![]() |
The main part of application's support of Map and Navigation services is implementation of service classes.
Map and Navigation services are represented by three service classes, which are derived from CMnServiceBase. As already mentioned above, the application does not have to implement all the services and features, but what is implemented must be declared in the resource file.
If a service is not implemented, the provider application should not declare it in the resource file and then it will not be asked for these services by Application Framework and therefore does not need to implement the appropriate service class at all.
All three service classes contain virtual methods, which represent separate service features and must be implemented by the provider application, if service support is declared. If some features are not supported, the implementation must leave from appropriate methods with KErrNotSupported.
Other methods are helpers and are not intended for implementation by provider application.
At the moment, only one service is requested from the application at the moment. If client requests another service from the same provider application, a new instance of application will be started.
This is illustrated in the following diagram:
Application startup
The first step is achieved by calling CEikonEnv::StartedAsServerApp():
void CTestProviderAppUi::ConstructL() { ... if ( !iEikonEnv->StartedAsServerApp() ) { // Started normally, open first view as usual ActivateLocalViewL( ... ); } else { // Started as server. // Postpone creating views until a service created } }
Determination of execution mode is done by overriding CEikAppUi::ProcessCommandParametersL and checking parent window group. If it is not zero, than application is started in embedded mode:
TBool CTestAppUi::ProcessCommandParametersL( CApaCommandLine &aCommandLine ) { TInt parentWg = aCommandLine.ParentWindowGroupID(); iChainedMode = ( parentWg != 0 ); return CAknAppUi::ProcessCommandParametersL( aCommandLine ); }
Execution modes
Provider application may be started in two different execution modes: standalone (the user can switch between client application and provider application), and "chained" (when the provider application's main window group is made child of client's window group thus hiding the client application from the user and making it impossible to switch back until the provider application is closed). The chained mode is similar to the embedded mode with the exception that the child application (here, provider application) is running in its own process.
In chained mode the provider application looks like one of the views of client application. It should display the "Back" button as right softkey instead of "Exit" to emphasize that pressing this button will return the user to the previous view in the application where the user originally was. The "Exit" option must still be present in the Options menu. By selecting this command the user can close the client application (as well as this provider application, of course).
In standalone mode, the provider application looks as it would be started from the main menu and should behave as usual: the "Exit" button is shown.
Creating server and services
Override CEikApplication::NewAppServerL to enable server creation.
void CTestApplication::NewAppServerL( CApaAppServer*& aAppServer ) { aAppServer = new (ELeave) CTestAppServer; }
Implement CApaAppServer to create service classes.
EXPORT_C CApaAppServiceBase* CTestAppServer::CreateServiceL( TUid aServiceType) const { switch ( aServiceType.iUid ) { case KMnAppMapViewService: return CTestMapViewService::NewL(); case KMnAppNavigationService: return CTestNavigationService::NewL(); default: // call default implementation for not supported services return CAknAppServer::CreateServiceL( aServiceType ); } }
See more details on that in Symbian OS documentation.
Service classes returned by server class must be implementations of base service classes, defined by this API: CMnMapViewServiceBase, CMnNavigationServiceBase and CMnGeocodingServiceBase.
Service closure
The following examples explain these rules.
The application can handle this by overriding CAknAppServer::HandleAllClientsClosed() as shown below:
EXPORT_C void CTestAppServer::HandleAllClientsClosed() { CTestAppUi* appUi = (CTestAppUi*) CEikonEnv::Static()->AppUi(); if ( !appUi || ( !appUi->IsAnyUserViewActive() ) ) { // default implementation will close the application CAknAppServer::HandleAllClientsClosed(); } }
The IsAnyUserViewActive() method mentioned in the example should be implemented by the provider application as part of the CTestAppUi class. It can verify if any user views are open, for example map view or navigation view. This applies to views open in response to client's request.
Application closure
The provider application may also be closed by the user, when they select the "Exit" or "Back" command. The provider application must inform the client correctly about the way it has been closed. This is done by calling CApaAppServer::NotifyServerExit(). If the user has selected "Exit" (from menu or command bar), pass EAknCmdExit. Otherwise other command ID, or exit reason. For example, the application can use the following code for that:
void CTestAppUi::HandleCommandL( TInt aCommand ) { CEikAppServer* server = iEikonEnv->AppServer(); switch( aCommand ) { case EEikCmdExit: case EAknSoftkeyExit: { if ( server ) { server->NotifyServerExit( EAknCmdExit ); } Exit(); break; } case EAknSoftkeyBack: { // simple exit will send EEikCmdExit // as exit reason to client Exit(); break; } default: break; } }
![]() |
MapView service (KMnAppMapViewService) implementation must be based on CMnMapViewServiceBase. This class exposes three abstract methods to be realized by the provider application. These methods are tied to service features as shown in the table below.
Feature | Methods |
---|---|
KMnSvcFeatureShowMap | CMnMapViewServiceBase::HandleShowMapL() |
CMnMapViewServiceBase::HandleShowCurrentLocationL() | |
KMnSvcFeatureSelectFromMap | CMnMapViewServiceBase::HandleSelectFromMapL() |
The provider application is not required to support all of the features of the services. It must specify which features are supported in resource file and provide leaving implementation for not supported ones. Implementation must leave with KErrNotSupported error code.
HandleShowMapL
This method should be implemented in the way that map view is displayed on the screen. The actual content of the view is determined by the provider application, however it must obey parameters given by the client application.
Parameter | Description |
---|---|
Area of the map view | Area of the map, which should be visible when the view is opened, is defined by a central point, retrieved by calling GetAreaCentralPoint() and area radius, AreaRadius(). If the area is too small and cannot be used, the implementation must select the lowest possible radius. If radius value is KAutomaticRadius, it is considered not set and the application can select reasonable radius by its own. If a central point is not set, then the central point can be e.g. last used location or current location. This setting does not limit the area visible for user: the user is allowed to change it by cursor and/or zooming keys or other control means provided by the application. |
Landmarks to be shown over the map | LandmarksToShow() returns a list of landmark objects, which should be marked on the map. LinkedLandmarksToShow() and LandmarksToShowDatabases() together define the list of landmark IDs and landmark database URIs of the landmarks, which reside in databases. The application should load these landmarks using Landmarks API and also mark them on the map. Note: no other landmarks should be marked on the map.It is preferred that implementation uses landmark's icon as a symbol to mark the landmark on the map. If the landmark has no own icon, then landmark's category icon can be used. If the category also does not have an icon, or the landmark has multiple categories, some default icon defined by implementation can be used.The implementation should listen for landmark changes in order to be informed if linked landmarks (specified by ID and database URI) have been changed and update view accordingly.If a view area is not specified, then such a view should be selected, which covers all landmarks, specified by the client (if possible). |
Current location option | If the current location option is set, then current location should be marked on the map. This option can override map view area specified by client, see details on CMnMapView::TCurrentLocationOption. |
This is a synchronous request. Client's request is completed when this method exits, therefore it should exit immediately after the map view is shown.
Landmarks arrays should not be accessed after returning from this method as they might be changed by the client application. Implementations should copy array data if later access to landmark lists is needed.
Generally the implementation should ignore changes in other parameters after exit from HandleShowMapL: they only have effect for current request. The only exception is linked landmarks. Implementations should set landmarks observers for databases listed in LandmarksToShowDatabases() and update accordingly to detected changes. If those changes affect currently displayed landmarks, such changes should be reflected on the screen. For example, currently displayed landmarks may be removed or changed, category icons can be changed, the whole database can be deleted, etc.
Below is the diagram showing how provider applications should implement the KMnSvcFeatureShowMap feature. CMapViewService is assumed an implementation of CMnMapViewServiceBase.
Map view can be dismissed by the user by selecting the "Exit" or "Back" command. In that case the application must shut down informing the client about the exit reason as described in the beginning of this chapter.
Below is the code example of how to read landmarks requested to be shown on the map.
// 1. Reading free landmarks TArray<const CPosLandmark*> landmarks = LandmarksToShow(); for ( TInt i = 0; i < landmarks.Count(); i++ ) { // make a copy of given landmark CPosLandmark* lm = CPosLandmark::NewLC( *(landmarks[i]) ); ... // store landmark to some array } // 2. Reading linked landmarks TArray<const HBufC*> lmdbs = LandmarksToShowDatabases(); for ( TInt db = 0; db < lmdbs.Count(); db++ ) { // URI of the database HBufC* databaseUri = lmdbs[db]; // store it // Read IDs of landmarks, which belong to this database TArray<TPosLmItemId> linkedLms = LinkedLandmarksToShow( db ); for ( TInt i = 0; i < linkedLms.Count(); i++ ) { // ID of the landmark TPosLmItemId id = linkedLms[i]; ... // store ID in an array } }
HandleShowCurrentLocationL
Implementation of this method is very much the same as for HandleShowMapL with the only exception that central point setting should be ignored and the current location should be used instead. The provider application itself is responsible for obtaining the current location (should be done via Location Acquisition API). Note: current location option should be taken into account anyway.
HandleSelectFromMapL
This feature is asynchronous: implementation should show a map view on the screen, from which the user can select a location, and exit from the method. When the user selects a location (or cancels selection), implementation completes the request with one of the CompleteSelectionRequestL methods or CompleteSelectionRequest, and the selected location is sent back to the client application. If any error occurs, the implementation should call the base method CompleteRequest() with appropriate error code. If the user cancels the selection, the error code must be KErrCancel.
All the additional parameters defined for HandleShowMapL are also valid for this call.
Landmarks arrays are guaranteed to be unchanged until the request is not completed or cancelled. It is done to make sure that indexes used with CompleteSelectionRequest methods are valid, when the request is completed.
Parameters | Description |
---|---|
Request text | This is the text that should be displayed to the user during selection. Usually it will be something like "Select a location", "Choose location for new landmark", etc. This text is read from SelectionRequestText(). |
Selection restriction option | If this option is set it means that the user should not be allowed to select arbitrary location, but should be allowed to select only from those landmarks, which are specified by the client to be shown over the map. Hence it is not allowed to complete this request with CompleteSelectionRequestL (const CPosLandmark& aLandmark). The request can only be completed with other overloads (which accept landmark index or ID and database URI) or cancelled. Check this option by calling the CMnMapViewServiceBase::Options() method. |
Below is the diagram showing how provider applications should implement the KMnSvcFeatureSelectFromMap feature. CMapViewService is assumed an implementation of CMnMapViewServiceBase.
The application must not shut down if the user made a selection, the client will need to make another request for retrieving result data, and the application must keep alive to allow that. If the user has cancelled the selection (for example, by pressing the "Cancel" command), the application can close safely informing the client about exit. However it is not required, the client can close the application by destroying MapView service.
Note: the application must not continue working if the MapView service is closed, because the user view (here, selection view) is already closed and is not needed for the user. This is contrary to simple map showing, where the view is not closed as part of sequence flow.
Below is the dummy code example of completing selection request, where the first landmark given by client is returned as selection result, if selection was restricted, or a random location is returned. This code is assumed as a part of member method of a class implementing CMnMapViewServiceBase.
if ( Options() & CMnMapView::EOptionRestrictSelection ) { // if selection was restricted, return one of given landmarks if ( LandmarksToShowDatabases().Count() && LinkedLandmarksToShow( 0 ).Count() ) { // take first linked landmark from first database TInt dbIndex = 0; TPosLmItemId lmId = LinkedLandmarksToShow( dbIndex )[0]; CompleteSelectionRequest( lmId, dbIndex ); } else if ( LandmarksToShow().Count() ) { // take first not linked landmark CompleteSelectionRequest( 0 ); } else { // this does not happen, because base implementation // will check that landmarks are given if selection is restricted User::Leave( KErrArgument ); } } else { // return random landmark CPosLandmark* lm = CPosLandmark::NewLC(); _LIT( KSelected, "RandomLandmark" ); lm->SetLandmarkNameL( KSelected ); // north pole lm->SetPositionL( TLocality( TCoordinate( -90, 0 ), 0 ) ); CompleteSelectionRequestL( *lm ); CleanupStack::PopAndDestroy( lm ); }
![]() |
Geocoding service (KMnAppGeocodingService) implementation must be based on CMnGeocodingServiceBase. This class exposes three abstract methods to be realized by provider application. These methods are tied to service features as shown in the table below.
Feature | Methods |
---|---|
KMnSvcFeatureCoordToAddr | CMnGeocodingServiceBase::HandleFindAddressByCoordinateL() |
KMnSvcFeatureAddrToCoord | CMnGeocodingServiceBase::HandleFindCoordinateByAddressL(const CPosLandmark&) |
KMnSvcFeaturePlainAddrToCoord | CMnGeocodingServiceBase::HandleFindCoordinateByAddressL(const TDesC&) |
Provider application is not required to support all of the features of the services. It must specify which features are supported in resource file and provide leaving implementation for not supported ones. Implementation must leave with KErrNotSupported error code.
All features of this service are asynchronous: implementation must return from Handle methods as soon as possible and report completeness by calling CMnGeocodingServiceBase::CompleteGeocodingRequestL, if request is processed successfully or CMnServiceBase::CompleteRequest in case of error.
During processing this request if any ambiguity exists, the implementation can ask the user for clarification (for example, clarification of address information or selection of one of possible addresses for given coordinates in case of coordinate given in the middle of a street or joint).
Parameter | Description |
---|---|
Dialog disabled | Check this option by calling CMnGeocodingServiceBase::Options(). If the CMnMapView::EOptionDialogDisabled option is set it means that geocoding must be done silently, without any UI open. If ambiguity exist, it should be solved without user's intervention (or request should be rejected with KErrArgument error, in unsolvable cases). |
HandleFindAddressByCoordinateL
Implementation retrieves coordinate information from given landmark, and starts searching for appropriate address information. When address information is found, it must call CMnGeocodingServiceBase::CompleteGeocodingRequestL with CPosLandmark parameter, which contains resulting address information. As much address info as possible should be given. See CPosLandmark::SetPositionFieldL and TPositionFieldId documentations for details on how to fill address data in the landmark object.
Below is the diagram showing how provider applications should implement the KMnSvcFeatureCoordToAddr feature. CGeocodingService is assumed an implementation of CMnGeocodingServiceBase.
Below is the dummy example of serving and completing this request. In this example, request is completed immediately upon receiving. CGeocodingService is assumed implementation of CMnGeocodingServiceBase.
void CGeocodingService::HandleFindAddressByCoordinateL( const CPosLandmark& aLandmark) { // verify input data if ( aLandmark.GetPosition( loc ) != KErrNone ) { User::Leave( KErrArgument ); } CPosLandmark* landmark = CPosLandmark::NewLC(); // set address information _LIT( KCountry, "Finland"); _LIT( KCity, "Tampere"); landmark->SetPositionFieldL( EPositionFieldCountry, KCountry ); landmark->SetPositionFieldL( EPositionFieldCity, KCity ); // complete request CompleteGeocodingRequestL( *landmark ); // cleanup CleanupStack::PopAndDestroy( landmark ); }
HandleFindCoordinateByAddressL with CPosLandmark input
This method receives input as a landmark, which has address fields set. Every address field is a part of street address information, which makes it easier for implementation to understand where is the country name and where is the building number, etc. However, address information in the input might be incomplete (some fields are missing or text is incomplete). Implementation can ask user for clarification if allowed by options, otherwise it must attempt to do its best effort to solve ambiguities.
Result should be given in the form of landmark, which coordinate corresponds to given address.
Below is the dummy example of serving and completing this request. In this example, request is completed immediately upon receiving. CGeocodingService is assumed as implementation of CMnGeocodingServiceBase.
void CGeocodingService::HandleFindCoordinateByAddressL( const CPosLandmark& aLandmark ) { // verify that landmark has at least some address info TBool valid = EFalse; TPositionFieldId fieldId = aLandmark.FirstPositionFieldId(); while ( fieldId != EPositionFieldNone ) { if ( fieldId > EPositionFieldAddressCapabilitiesBegin && fieldId < EPositionFieldNMEACapabilitiesBegin) { TPtrC field; aLandmark.GetPositionField( fieldId, field ); if ( field.Length() ) { valid = ETrue; break; } } fieldId = aLandmark.NextPositionFieldId( fieldId ); } if ( !valid ) { User::Leave( KErrArgument ); } CPosLandmark* landmark = CPosLandmark::NewLC(); // set some coordinate TCoordinate coord; coord.SetCoordinate( 90, 0 ); // North Pole landmark->SetPositionL( TLocality( coord, 0 ) ); // complete request CompleteGeocodingRequestL( *landmark ); // cleanup CleanupStack::PopAndDestroy( landmark ); }
HandleFindCoordinateByAddressL with plain string input
This method receives address as a plain string, which requires from implementation some capabilities to analyze the input string and get the street address information from it. Ambiguities may be clarified from user if allowed by options.
Result should be given in the form of landmark, the coordinate of which corresponds to the given address.
Below is the dummy example of serving and completing this request. In this example, request is completed immediately upon receiving. CGeocodingService is assumed implementation of CMnGeocodingServiceBase.
void CGeocodingService::HandleFindCoordinateByAddressL( const TDesC& aAddress ) { // verify input data if ( aAddress.Length() == 0 ) { User::Leave( KErrArgument ); } CPosLandmark* landmark = CPosLandmark::NewLC(); // set some coordinate TCoordinate coord; coord.SetCoordinate( -90, 0 ); // South Pole landmark->SetPositionL( TLocality( coord, 0 ) ); // complete request CompleteGeocodingRequestL( *landmark ); // cleanup CleanupStack::PopAndDestroy( landmark ); }
![]() |
MapImage service (KMnAppMapImageService) implementation must be based on CMnMapImageServiceBase. This class exposes single abstract method HandleRenderingL to be realized by the provider application. This method is tied to both service features, defined for this service.
Feature | Methods |
---|---|
KMnSvcFeatureVectorMap | CMnMapImageServiceBase::HandleRenderingL() |
KMnSvcFeatureSatelliteImage |
Provider application is not required to support all of the features of the service. It must specify, which features are supported, in resource file and implementation must leave with KErrNotSupported error code for not supported ones.
All features of this service are asynchronous: implementation must return from HandleRenderingL method as soon as possible and report completeness by calling CMnMapImageServiceBase::CompleteRendering, if request processed successfully or CMnServiceBase::CompleteRequest in case of error.
Implementation of this service is supposed to render map image of an area to a bitmap object supplied by client. Various parameters, which define what area of world should be drawn and how, are defined in the TMnMapImageParams class, which is accessible via CMnMapImageServiceBase::MapImageParams(). See detailed description of these parameters in Map Image API specification.
Projection and coordinate conversions
Implementations can use different projections for map rendering (although it is not recommended to use projection, which cause heavy shape distortions). Usually the best approach is to use same projection as is used for normal map rendering as in MapView or Navigation services.
That means there is no way for client to calculate world coordinates from image coordinates and vice versa. Therefore, implementation of this service must also provide implementation of Map Image Conversion Plug-In API: an ECom plug-in, which implements such coordinate conversions. This plug-in will be loaded into client's process.
If given implementation utilizes several projections, it needs to inform its coordinate conversion plug-in about how exactly an image was rendered to be able to perform coordinate conversion appropriately. There is one parameter in TMnMapImageParams reserved for that purpose (described in the table below). Implementation of this service should put its internal ID of projection used for rendering every particular image to this field. It will be then transferred to coordinate conversion plug-in, when client requests such conversions.
Parameter | Description |
---|---|
Projection ID | Access this option in instance of TMnMapImageParams returned from CMnMapImageServiceBase::MapImageParams(). Exact values in this setting are solely implementation-dependent. Map and Navigation FW only guarantees to transfer that value from MapImage service implementation to coordinate conversion plug-in. |
Even if the current version of the provider application utilizes only single projection, it might be useful to assign it an ID and use it in this field. This may help to ensure future compatibility of different versions of this service implementation and coordinate conversion plug-in.
See Map Image Conversion Plug-In API for further details on implementing coordinate conversion plug-in.
Visible items
The CMnMapImageServcieBase::ShowOptions() method returns a bit map of options defined in CMnMapImage::TShowOptions. They specify what additional content client wants to be drawn over the map image. By default neither of these flags is required to be drawn (i.e. if implementation does not support e.g. country borders, it can ignore that option) unless the EShowOptionsMandatory flag is also set. In this case, if some of required options are not supported, then rendering should be refused with KErrNotSupported.
One specific note goes to the EShowOptionCurrentLocation flag. This option can only be satisfied if the client application has the Location capability. The base class takes care of this: if client does not have the capability, then this option is silently dropped, or the whole request is refused, if EShowOptionsMandatory flag is also set.
HandleRenderingL
Implementation reads map image parameters from MapImageParams() and renders map to the area, defined by CMnMapImageServcieBase::TargetRect(), of the bitmap object defined by CMnMapImageServcieBase::TargetBitmap(). It is guaranteed that the size of this bitmap is sufficient to fit map of requested size.
The main option to consider is TMnMapImageParams::ImageType(). If it is set to the value of TMnMapImageParams::ETypeUnspecified, then implementation is free to render any type of map, best suitable for given center and visible area. It should inform the chosen image type back to the TMnMapImageParams instance returned by MapImageParams(). Otherwise it must obey the setting and leave with KErrNotSupported, if it cannot render maps of that particular type.
This is asynchronous request and implementation should exit this method as soon as possible. When rendering is completed, it should complete this request by calling CMnMapImageServcieBase::CompleteRendering() if rendering ended successfully or inherited CMnServiceBase::CompleteRequest() in case of error. It is allowed to call it also during execution of HandleRenderingL, in which case it is not needed to call it later.
If this request is cancelled by the client during processing, then DoCancel() is called. It is not needed to call any completion methods in that case.
HandleRenderingL can leave, which is treated as failure to start rendering. In that case leave code is returned to the client and it is not needed to call completion methods either.
Below is the diagram showing how provider applications should implement this service. CMapImageService is assumed an implementation of CMnMapImageServiceBase.
![]() |
Below is the dummy example of serving and completing this request. In this example, request is completed immediately upon receiving. CMapImageService is assumed implementation of CMnMapImageServiceBase.
void CMapImageService::HandleRenderingL() { TMnMapImageParams& params = MapImageParams(); if ( params.ImageType() == TMnMapImageParams::ETypeSatelliteImage ) { User::Leave( KErrNotSupported ); } CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL( &(TargetBitmap()) ); CleanupStack::PushL( bitmapDevice ); CFbsBitGc* gc = NULL; User::LeaveIfError( bitmapDevice->CreateContext( gc ) ); CleanupStack::PushL( gc ); // Very simple map example gc.Clear( TargetRect() ); // clear the area gc.DrawEllipse( TargetRect() ); // draw ellipse to the area // cleanup CleanupStack::PopAndDestroy( gc ); CleanupStack::PopAndDestroy( bitmapDevice ); // complete request params.SetImageType( TMnMapImageParams::ETypeVectorMap ); params.SetProjectionId(0); CompleteRendering(); }
![]() |
The behavior of provider application affects look and feel of client applications. Therefore below some implementation guidelines are given, which should be followed. It will help to keep overall user experience generic and good.
![]() |
Map and Navigation application deal with a large amounts of content data and implement a number of use cases. This implies that such applications are complex but also that they are big. Startup times may be high due to the need to allocate huge amounts of memory, initialize many internal engines.
However, when executed via Map and Navigation FW, not all features of applications are needed. For example, when serving geocoding, rendering engine is not needed and therefore should not be initialized. If clarification dialog is disabled, then no UI needed at all and it also should not be loaded. Landmark data is not used in this use case and so no connection to landmark databases should be open.
The main thing to be considered is that Map and Navigation FW starts new instance of the provider application for every new connection made by client. It means that if client uses MapView, Navigation and Geocoding services, it will start three instances of the application.
![]() |
When started in server mode, the provider application should minimize time, required for getting the user to the target view. The application should not start with default views, which take long time to load. The application should not try to load all resources it needs in normal case, until service class is created and it is clear what is required by client application and what needs to be loaded and what can be omitted.
For example, there is no need to load all landmarks from all landmark databases for map view service, because only those landmarks, which are requested by client, need to be shown.
![]() |
Geocoding service should not show any UI, if disabled by client. However, when server application is started it shows still by default some UI elements: command and status bars. This should be avoided and it can be achieved by moving implementation of geocoding service to a separate application, which is started in background. The same applies for the MapImage service. It also should be run in the background, because clients draw rendered map image bitmaps on their own UI.
launch = KAppLaunchInBackground;directive into application's APP_REGISTRATION_INFO resource.
hidden = KAppIsHidden;to the same resource.
Following is the full example of such registration file.
#include <appinfo.rh> #include "mnappserviceuids.hrh" #include "mnappservices.hrh" #include "mnserviceinfo.rh" #include <testgeocoder.rsg> UID2 KUidAppRegistrationResourceFile UID3 0x03132014 RESOURCE APP_REGISTRATION_INFO { app_file = "testgeocoder"; localisable_resource_file = "\\resource\\apps\\testgeocoder"; localisable_resource_id = R_TESTGEOCODER_LOCALISABLE_APP_INFO; launch = KAppLaunchInBackground; hidden = KAppIsHidden; service_list = { SERVICE_INFO { uid = KMnAppGeocodingService; datatype_list = {}; opaque_data = r_testgeocoder_geocoding_opaquedata; } }; } RESOURCE MN_SERVICE_INFO r_testgeocoder_geocoding_opaquedata { service_features = KMnSvcFeatureCoordToAddr | KMnSvcFeatureAddrToCoord | KMnSvcFeaturePlainAddrToCoord; }
![]() |
If several navigation views are running at the same time (which is possible, if the user starts it from different applications), the user gets "not best" experience. It is recommended that the provider application, when requested for navigation, tries to identify if some other of its instances is already running navigation and cancels that navigation in favor of a newly started one. For better compatibility it should be done in the way as if the user would stop old navigation manually (i.e. by closing old navigating instance).
![]() |
Implementations must not compromise Platform Security. That means that when and if the client's request requires some functionality, which is usually protected by capabilities, those capabilities must be checked and in case of absence of such, operation must not be performed.
Client capabilities can be read from the message object, which is involved in every communication between client and server. RMessagePtr2::HasCapability() is the shortest method to verify if the client has some particular capability. Implementations can check it in the following ways:
When service is refused due to lack of capabilities, implementation must complete client's request with error code KErrPermissionDenied.
![]() |
This API uses only standard Symbian OS leave codes. Panic codes are defined in the mnerrors.h header file.
Panic code | Reason |
KMnPanicArrayIndexOutOfBounds | Raised if attempt is made to access an item of an array and specified index is out of bounds. This may happen for example, when calling CMnMapViewServiceBase::LinkedLandmarksToShow(). |
KMnPanicAttemptToCompleteNoRequest | Raised if implementation tries to call asynchronous request completion methods, when there was no such request issued or it was already cancelled by the client. Implementation is informed about asynchronous request cancellation via CMnServiceBase::DoCancel(). |
Provider application reports the following error codes for specific cases:
Error code | Case |
---|---|
KErrCancel | If the user has cancelled operation. |
KErrArgument | If the given argument cannot be used for operation. For example, landmark has no coordinate or address and cannot be shown on map or address information is not sufficient for geocoding. |
KErrNotSupported | If the service feature is not supported, or cannot be executed with given parameters. For example, map content not available for specified area, etc. |
KErrPermissionDenied | The client does not have a capability, which is required for serving its request. |
![]() |
The main concern about RAM usage is related to set of landmarks requested to be shown on map. The clients can send landmarks as instances, not only as linked landmarks, these instances are kept in provider application's memory (implementation of CMnMapViewServiceBase) until reset by client or client disconnects. The implementation has to create another copy of landmark fields, which it is using (or all landmark data), before using them on the map view. This will require more memory. In any case, if available memory is not enough for requested operations, they should be refused with KErrNoMemory error code. For synchronous operations, such as CMnMapViewServiceBase::ShowMapL, it means leaving and for asynchronous methods, such as CMnMapViewServiceBase::SelectFromMapL, it can also be completing request with that error code by calling CMnServiceBase::CompleteRequest.
![]() |