"How to" for the Android SDKTools

Prerequisites

Adding the SDKTools to the project

Steps to integrate:

  • Add SDKTools to your project:
    • Eclipse -> Add as reference the SDKTools library project
    • Android Studio -> Import module, navigate to the module location

Navigation component

This component provides an integral UI and logic for implementing a turn by turn navigation scenario or free drive navigation scenario. It also deals with audio advices and other settings.

Displaying the UI

The navigation and free drive UI is optimized for full screen display and it should be used as an overlay for the map view. The developer has to clean other views from the map before calculating a route or navigating. The UI supports both portrait and landscape orientations.

Starting navigation

To start a navigation use the startNavigation: method of the SKToolsNavigationManager.

The method requires as parameter an SKToolsNavigationConfiguration object. This object allows to customize different aspects of the navigation. For more details see the SKToolsNavigationConfiguration class.

For a quick start SKToolsNavigationConfiguration provides a default configuration. The only thing that has to be set is the start and destination coordinate, map style paths, and the navigation type (by default is set to SKNavigationSettings.SKNavigationType.REAL which is not very useful when using the emulator or standing in place).

SKToolsNavigationConfiguration configuration = new SKToolsNavigationConfiguration();
configuration.setStartCoordinate(startPoint);
configuration.setDestinationCoordinate(destinationPoint);
configuration.setDayStyle(new SKMapViewStyle(getMapResourcesDirPath() + ".DayStyle/",
               "daystyle.json"));
configuration.setNightStyle(new SKMapViewStyle(getMapResourcesDirPath() + ".NightStyle/",
               "nightstyle.json"));
navigationManager.startNavigation(configuration, mapView);

Starting free drive

To start free drive use the startFreeDriveWithConfiguration: method SKToolsNavigationManager. This method uses the same SKTNavigationConfiguration object.

SKToolsNavigationConfiguration configuration = new SKToolsNavigationConfiguration();
configuration.setNavigationType(SKNavigationType.FILE);
configuration.setFreeDriveNavigationFilePath(filePath);
configuration.setDayStyle(new SKMapViewStyle(getMapResourcesDirPath() + ".DayStyle/",
               "daystyle.json"));
configuration.setNightStyle(new SKMapViewStyle(getMapResourcesDirPath() + ".NightStyle/",
               "nightstyle.json"));
navigationManager.startFreeDriveWithConfiguration(configuration, mapView);

Navigation routes

Navigation requires calculating a route first. You can either calculate the route yourself or you can let the library to do it for you.

When route calculation is finished the user has the option to choose which route to be used for navigation.

You can use different routing profiles when calculating the route: car, bike, pedestrian.

SKToolsNavigationConfiguration configuration = new SKToolsNavigationConfiguration();
configuration.setStartCoordinate(startPoint);
configuration.setDestinationCoordinate(destinationPoint);
configuration.setDayStyle(new SKMapViewStyle(getMapResourcesDirPath() + ".DayStyle/",
               "daystyle.json"));
configuration.setNightStyle(new SKMapViewStyle(getMapResourcesDirPath() + ".NightStyle/",
               "nightstyle.json"));
configuration.setNavigationType(SKNavigationType.SIMULATION);
configuration.setRouteType(SKRouteMode.CAR_FASTEST);
navigationManager.launchRouteCalculation(configuration, mapView);

The navigation callback

The SKToolsNavigationManager provides a listener to inform you when the route/ navigation started or ended.

Map styles

To be more visually appealing, the navigation library uses different map styles and UI colors for day and night. You can choose which styles to be used for both by setting dayStyle and nightStyle in the SKToolsNavigationConfiguration.

Download component

The download component is completely separated from any UI or any database operation. It just downloads a list of items. Besides the separation between UI and back-end, the big gain is that now, we must only define „what to” download and we are not concerned „how to” download. The download is serial, but download and install operations can run in parallel. It contains the following sub-components:

  • SKToolsFileDownloadStep: defines an object corresponding to current URL from where we download ; it contains the download URL, the destination path and the item size ; it was created to differentiate between different URL downloads (an item can contain more URLs, so more download steps may be needed to finish its download).
  • SKToolsDownloadItem: defines an item that will be downloaded ; it contains an array of SKToolsFileDownloadStep objects, for each corresponding URL ; in addition, it defines the following properties: download item code, download state, number of downloaded bytes (from the beginning or only in current internet connection ; they are saved for the entire item, not just for current step), current step index. It also contains the variables that tell if an unzip or an install operation are needed (unzip is not needed for items that don't have a ZIP file ; install - performed by NG library - is not needed for sounds).
  • SKToolsDownloadManager: defines the methods which the client can use in order to access the download component (start, pause, resume, cancel, cancel all, check if download is running). It acts like an interface between client and download component ; it contains a list of download items and a listener used to notify the client about current download state.
  • SKToolsDownloadListener: defines the methods used by download component to notify the client. The client that uses our download component must implement this interface and override the methods defined here ; the download component notifies the client through its listener when the download is in progress (at each second) or when it is cancelled, paused, when the internet connection is down (after a retry of 15 seconds or 20 seconds when the internet connection blocks), when install operation starts or finishes, when there is not enough storage to perform current download.
  • SKToolsDownloadPerformer: represents the core download component. It takes a list of SKToolsDownloadItem objects and downloads them. It implements some operations like: cancel, resume, pause, retry if internet is not available. It doesn't implement persistence, so if the download process is paused, when resuming, the client must send again the list of SKToolsDownloadItem objects that were not downloaded yet.
  • SKToolsUnzipPerformer: represents the core unzip component. It performs the unzip for downloaded items that have a ZIP file and, if these components needs to be installed (sounds don't need, but maps must be installed), calls a NG method for each component . Then, the NG library takes care to copy the downloaded files at right place, in the application folder.
  • SKToolsDownloadUtils: defines some helper methods for download module (methods that remove a file/folder from disk, check if there is enough storage on device for current download, if the storage is accessible etc).

Setting up the download component

The demo application performs map package downloads through the download component which it integrates. In this particular case the UI through which downloads are controlled is a list containing the items that can be downloaded.

At first some metadata describing the download items needs to be obtained. This metadata is contained in the Maps.json file available on the server. A request is made to get the file's content which is then parsed. These actions are performed only the first time the "Map downloads" option in the menu is accessed. After the parsing completes a local database is populated with the metadata. The database provides the persistence of the download data between application runs. The list UI component is then filled with the map data.

// get URL for Maps.json file
String jsonUrl = SKPackageManager.getInstance().getMapsJSONPathForCurrentVersion();
HttpURLConnection connection = (HttpURLConnection) new URL(jsonUrl).openConnection();
// parse the content of the JSON file
new MapDataParser().parseMapJsonData(parsedMapResources, parsedMapItemsCodes, regionItemsCodes, connection.getInputStream());
// populate database with results
mapsDAO.insertMaps(parsedMapResources, parsedMapItemsCodes, regionItemsCodes, this);

Several download operations are available for the map packages in the list: start, pause, cancel, cancel all. These were implemented as methods of the SKToolsDownloadManager class in the download component. These methods should be used to control the download process of a download item:


public void startDownload(List<SKToolsDownloadItem> downloadItems)
public boolean pauseDownloadThread()
public boolean cancelDownload(String downloadItemCode)
public boolean cancelAllDownloads()

The download UI should stay up-to-date with the events in the download process. This is accomplished by implementing the SKToolsDownloadListener interface which provides several notifications.

Register the domain certificate to download packages using HTTPS

In order to download packages using HTTPS an sslContext object needs to be configured as shown in the snippet code below.

KeyStore keyStore = buildKeyStore(skMapsPath + HTTPS_CERTIFICATE_NAME);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);

// Create an SSLContext that uses our TrustManager
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);

private KeyStore buildKeyStore(String certRawResFileName) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException {
    // init a default key store
    String keyStoreType = KeyStore.getDefaultType();
    KeyStore keyStore = KeyStore.getInstance(keyStoreType);
    keyStore.load(null, null);

    // read and add certificate authority
    Certificate cert = readCert(certRawResFileName);
    keyStore.setCertificateEntry("ca", cert);

    return keyStore;
}

private Certificate readCert(String certPath) throws CertificateException, IOException {

    // read certificate resource
    InputStream caInput = new FileInputStream(certPath);
    Certificate ca;
    try {
        // generate a certificate
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        ca = cf.generateCertificate(caInput);
    } finally {
        caInput.close();
    }

    return ca;
}

Once the sslContext is configured the SKToolsDownloadPerformer can be used as with HTTP requests, the configuration difference is shown in the snippet code below.

HttpsURLConnection httpsURLConnection = (HttpsURLConnection) packageUrl.openConnection();
httpsURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());
httpsURLConnection.setReadTimeout(TIME_OUT_LIMIT); //15000
httpsURLConnection.setConnectTimeout(TIME_OUT_LIMIT); //15000
httpsURLConnection.setRequestMethod("GET");
httpsURLConnection.setUseCaches(false);
httpsURLConnection.setRequestProperty("Connection", "close");

OneBox component

OneBox search provides a cleaner, easier way of searching for cities, addresses or POIs inside one search field, instead of using one for country, city, street and number. To find out more about the internals of the OneBox search tool (the OpenStreetMap based implementation) please see the dedicated page.

Displaying the UI

The OneBox UI is optimized for full-screen display and encapsulates all the UI components into one fragment. The UI supports both portrait and landscape orientations. To start the OneBox component the developer should create a function to open the OneBoxFragment.

Setting up the OneBox component

The OneBox component is completely separated from any UI or application logic. The OneBoxFragment handles UI components and the SKToolsSearchServiceManager performs search operations. The search method requires as parameter an SKToolsSearchObject. This object defines the input parameters for a search.

The one line search and nearby search functionalities are available when the developer adds the OneBoxFragment to the current activity.