S60 Map and Navigation Provider API

DN078378
CONFIDENTIAL

©Nokia Corporation and/or its subsidiaries 2007
This material, including documentation and any related computer programs, is protected by copyright controlled by Nokia. All rights are reserved. Copying, including reproducing, storing, adapting or translating, any or all of this material requires the prior written consent of Nokia. This material also contains confidential information, which may not be disclosed to others without the prior written consent of Nokia.

Nokia is a registered trademark of Nokia Corporation. S60 and logo is a trademark of Nokia Corporation. Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. Other company and product names mentioned herein may be trademarks or tradenames of their respective owners.

Change History

Version

Date

Status

Description

1.0

21.02.2007

Approved

 

 

 

 

 


Table of Contents

Purpose
API availability
API description
Use cases
API class structure
Using Map and Navigation API
Register support of Map and Navigation services
Service support declaration
Additional info in installation package
Implement services
Implementing MapView service
Implementing Navigation service
Implementing Geocoding service
Implementing MapImage service
Implementation guidelines
Split implementation
Minimize service start-up time
Running background
Reuse navigating instance
Security
Error handling
Memory overhead
Extensions to the API
See also
Glossary
Abbreviations
Definitions
References

 


Purpose

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).

 


API availability

This API is available for S60 release 3.2 and later. MapImage service and related classes are defined since S60 release 5.0.

 


API description

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:

  • Map and Navigation API
  • Geocoding API
  • Map and Navigation Provider Discovery API
  • Map and Navigation AIW API
  • Map Image API
Provider applications are application servers and are executed in their own processes and utilize their own views. Client applications only request map and navigation services via APIs listed above and those are forwarded to provider application via this API.

 


Use cases

The main use cases provided by the API are the following:

  • Register support for Map and Navigation services
  • Implement Map and Navigation services:
    • MapView service
    • Navigation service
    • Geocoding service
    • MapImage service

 


API class structure

This API provides three main interfaces to map and navigation features implementations:
  • CMnMapViewServiceBase - displaying map view on screen. Additional parameters are set of landmarks to show over the map, view area, etc. Also selection from map is requested via this interface.
  • CMnNavigationServiceBase - starting navigation to a destination specified by landmark.
  • CMnGeocodingServiceBase - processing geocoding and reverse geocoding requests.
  • CMnMapImageServiceBase - rendering map images of a specified area.

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.

Figure 1: Map and Navigation API class structure

 


Using Map and Navigation API

 


Register support of Map and Navigation services

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:

  • Declare service support in application registration file.
  • Provide additional information in installation package.

These steps are described in details in next chapters.

 


Service support declaration

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.

Table: Map and Navigation application services
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:

Table: Map and Navigation service features
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.

 


Additional info in installation package

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.

 


Implement services

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.

From a high level, the provider application, when used as an application server, is operated as follows:
  1. Application Framework starts application normally with the exception that the application is informed that it is started as a server. This information is given in CEikEnv::StartedAsServerApp().
  2. The application is asked to create server class.
  3. When the client application asks Map and Navigation FW for a service, the application is asked to create an appropriate service class.
  4. Map and Navigation FW calls one of virtual Handle methods.
  5. A service class is destroyed by Application FW, when the client does not need the service any more. The application can continue or shut down (see "Execution modes" note below).
    • Application can also be closed by user, if she selects "Exit" command.

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:

Figure 2: Provider application lifetime

Application startup

The provider application should do two things at this stage:
  • Determine if it is started as server.
  • Determine execution mode.

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

When service class is destroyed, the client is not interested in provider's service anymore. The further behavior of provider application depends on the mode it was started in:
  • The provider application must close, if started in chained (embedded) mode. This ensures that the client application regains focus.
  • If started standalone:
    • if no other views are open, the provider application must close.
    • if any view is open, the provider application remains running until closed by the user.

The following examples explain these rules.

  1. MapView service is usually started in chained mode and is visible to the user as one of the views of the client application. If the client application closes MapView service it means that it wants to return the user to the main view.
  2. Navigation is started usually as standalone, because the user wants to be able to switch back to the original application without stopping the navigation. The user closes the navigation when needed.

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;
    }
  }

 


Implementing MapView service

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.

Table: MapView service features-to-methods mapping
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.

These additional parameters can be retrieved by calling protected methods of CMnMapViewServiceBase. The following parameters can be defined by the client and must be verified and taken into account in the implementation of this feature.
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.

Figure 3: Implementing HandleShowMapL request

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.

There are some other parameters that can be specified by the client for this feature:
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.

Figure 4: Implementing HandleSelectFromMapL request

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 );
  }

 


Implementing Navigation service

Navigation service (KMnAppNavigationService) implementation must be based on CMnNavigationServiceBase. This class exposes a single abstract method HandleNavigateToL() to be realized by the provider application, which is tied to single navigation service feature KMnSvcFeatureNavigateTo.

Table: Navigation service feature-to-method mapping
Feature Methods
KMnSvcFeatureNavigateTo CMnNavigationServiceBase::HandleNavigateToL()

If the provider application declares support for the KMnAppNavigationService service, it must implement the KMnSvcFeatureNavigateTo feature, because it is the only feature of that service. If navigation is not supported no support for this service should be declared.

HandleNavigateToL

Navigation service is defined less strictly in comparison to MapView service. Entry method HandleNavigateToL() has only one parameter: landmark of the destination point of navigation. Starting point is assumed as current location.

Implementation is supposed to activate the navigation view and return from this method as soon as the view is activated. Navigation view should execute the navigation or allow the user to start navigation.

Exact navigation functionality is not defined, it may depend on application capabilities. For example, some applications implement full navigation with map view and voice guidance, while others can provide only route planning and so forth.

Below is the diagram showing how provider applications should implement KMnSvcNavigateTo feature. CNavigationService is assumed an implementation of CMnNavigationServiceBase.

Figure 5: Implementing HandleNavigateToL

 


Implementing Geocoding service

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.

Table: Geocoding service features-to-methods mapping
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).

There is only one additional parameter, which must be taken into account:
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.

Figure 6: Implementing HandleFindAddressByCoordinateL

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 );
    }
    

 


Implementing MapImage service

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.

Table: MapImage service features-to-methods mapping
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.

Figure 7: Implementing HandleRenderingL

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();
}

 


Implementation guidelines

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.

 


Split implementation

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.

The best approaches are:
  • Split implementation to smaller pieces and load them only when needed.
  • Put core functionality to a server and implement UI as a set of thin views, which share core functionality from that server. Database reader, network and file manager are good examples of core functionality. Separating them to a server helps to solve performance and robustness problems dramatically.

 


Minimize service start-up time

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.

 


Running background

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.

This can be done by putting
launch = KAppLaunchInBackground;
directive into application's APP_REGISTRATION_INFO resource.
As such this application makes no interest for user and therefore it should be hidden from main menu. This is done by adding
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;
    }

 


Reuse navigating instance

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).

 


Security

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.

Let's consider implementations, which store their content on network. Some or all client requests may require accessing network in order to execute them. If client does not have the NetworkService capability, that must not be allowed. Capabilities may be checked at different stages:
  1. Client creates a connection to service class
  2. Client issues a request
Implementation can refuse services at any point, but it is recommended to refuse only those parts of service, which actually violate security, if possible. For this example, if network content is cached locally and for serving some particular request cached data is enough, then request can succeed. In contrast, if serving the request always requires network content, then service can be refused already at the stage of creating of the service class.

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:

  1. Override CApaAppServer::CreateServiceSecurityCheckL(). It is called even before service class is created (i.e. before CreateServiceL is called) and provides get type of the required service and first message object from client, which can be checked for client's security info.
  2. During a Handle..L (e.g. HandleShowMapL, HandleRenderingL, HandleNavigateToL, etc.) method execution of currently executing service, i.e. CMnServiceBase-derived class, call Server() and get pointer to application's server. That object will provide current message object (CServer2::Message()) from client, which also can be used to get its capabilities.

When service is refused due to lack of capabilities, implementation must complete client's request with error code KErrPermissionDenied.

 


Error handling

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.

 


Memory overhead

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.

 


Extensions to the API

This API does not allow extending.

 


See also

See also related APIs:
  • Map and Navigation API
  • Geocoding API
  • Map and Navigation Provider Discovery API
  • Map and Navigation AIW API
  • Landmarks API
  • Landmarks Search API
  • Landmarks Database Management API
  • Location Acquisition API

 


Glossary

 


Abbreviations

Table: Abbreviations
None  

 


Definitions

Table: Definitions

Landmark

A landmark is principally a location with a name.

Provider Application An application, which implements map and navigation services and provides access to those for clients of Map and Navigation API and Geocoding API.

 


References

None

 

Back to top