Key Concepts

In the following use case sections, we will guide you through the most common usage scenarios and reveal tips and easy-to-understand guidelines to help you get the most out of the HERE SDK for Android.

How to use this Guide?

You can read this guide in any order. All sections are independent from each other, making it easy to skip any section and to dive straight into the topics which you are most interested in.

  • In the example section, you can find the example apps accompanying this user guide.
  • If you are interested in building your first app showing a HERE map, take a look at the Get Started section to guide you through the first simple steps.

Conventions

For this guide, we preferably avoid the use of lambda notations to show the full type of information and other details, such as callback or listener name. Since Android Studio supports one-click conversion between anonymous classes and lambdas, adapting the examples to suit your personal preference should be simple.

Dispose Objects

All HERE SDK classes will be garbage collected by Android if the instance is no longer referenced or set to null.

For the SDKNativeEngine, which can be initialized automatically or programmatically, you can free resources by calling SDKNativeEngine.getSharedInstance().dispose(), for example, when the hosting activity's lifetime has ended. Calling dispose() will stop pending requests and close open files and databases that are still running on the main thread. After calling dispose() any related HERE SDK feature should no longer be used.

Callbacks and Listeners

  • The HERE SDK exposes callbacks for single event notification such as for search results.
  • For reoccurring event notifications such as for gesture events, listeners are used. When multiple listeners can be set, then the method pattern add_x() and remove_x() is used as naming convention. If only one listener can be set at a time, the set_x() pattern is used that can be set to null to stop listening.

Debug Logs

You can use the LogAppender interface to insert your own log class into the SDKNativeEngine. This way you can log HERE SDK messages for various predefined log levels even for release builds of your app.

Code Snippets

The shown code snippets cover best practice example code ready to be used for your own applications. However, for the sake of simplicity and to not shadow the educational approach of this guide, not all edge scenarios may be handled, especially when it comes to error handling or robust threading. In some cases, the obvious code is left out, but it can be found in the accompanying example apps that can be built and deployed instantly on any supported device with a set of valid HERE credentials.

Design Principles

The accompanying example apps follow the same structure. As much as possible the HERE SDK example code is decoupled from the surrounding platform code. We hope this makes it easier to see the relevant parts of the shown APIs. Each example app follows the same entry point from which the HERE SDK is initialized. Since each app is focusing on a different aspect of the HERE SDK, that code can be found in a single class postfixed with "...Example.java" in its class name. Most often this class gets a reference to a MapView to start its work.

Following the popular POJO (PLain-Old-Java-Object) principle, the example code is kept free of most Android dependencies - instead it's mostly pure Java code that shows how the HERE SDK can be used.

Dependency Management

Currently, dependency management, for example, via Gradle, is not yet supported. This means that the HERE SDK AAR binary must be copied locally to an application project as described in the Get Started section.

Is the HERE SDK Thread Safe?

The HERE SDK is not guaranteed to be thread safe and it is recommended to make calls to the SDK from the main thread. Internally, the HERE SDK will offload most of its work to a background thread, but callbacks to your code will always occur on the main thread. In general, thread safety is the responsibility of the caller. For example, it is unsafe to reuse an engine on different threads unless your code is synchronized.

Unit Tests

It's easy to write unit tests for your app logic that uses the HERE SDK as all classes are fully mockable. Inside the release package you can find a heresdk-mock JAR file that enables mocking of all HERE SDK classes. Below you can see an example using Mockito. This will also work with most other frameworks that allow to create mocked objects:

@RunWith(MockitoJUnitRunner.class)
public class TestExample {

    @Test
    public void testNonStaticMethod() {
        Angle angleMock = mock(Angle.class);

        when(angleMock.getDegrees()).thenReturn(10.0);

        assertEquals(10.0, angleMock.getDegrees());
        verify(angleMock, times(1)).getDegrees();
        verifyNoMoreInteractions(angleMock);
    }

    ...
}

Use the following dependency in your app's build.gradle setup:

def getHereSdkArtefactName() {
    def aarFile = fileTree(dir: 'libs', include: ['heresdk-*.aar']).first()
    // Filename without extension is necessary.
    return org.apache.commons.io.FilenameUtils.getBaseName(aarFile.name)
}

// Exclude HERE SDK's aar from unit test's dependencies.
configurations.testImplementation {
    exclude module: getHereSdkArtefactName()
}

dependencies {
    implementation(name: getHereSdkArtefactName(), ext:'aar')

    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'

    // Keep in mind that the original HERE SDK aar must be excluded from
    // the test dependency, see above.
    testImplementation fileTree(dir: 'libs', include: ['*mock*.jar'])
    testImplementation 'junit:junit:4.12'
    testImplementation 'org.mockito:mockito-core:3.1.0'
}

With this setup your app will use the mock JAR when executing unit tests and the real HERE SDK AAR when building the app. Place the heresdk-edition-mock-version.jar into the same app/libs folder as the heresdk-edition-version.aar.

Check the UnitTesting example app to find more use case examples.

Engines

The HERE SDK contains several modules - or engines as we call them - to execute specific tasks such as calculating a route with the RoutingEngine or requesting search results via the SearchEngine. There are many more engines you can use with the HERE SDK and you can read more about them in the dedicated chapters below. However, most engines share common concepts that makes it easier to use them. For example:

  • All engines execute their tasks asynchronously and receive their results on the main thread.
  • All engines share similar interfaces, callbacks and error handling.
  • It is possible to start multiple instances of an engine in parallel.
  • An online connection is required.

Pre-Initialize the HERE SDK

Usually, the HERE SDK is initialized together with the map view. Below you can find several ways to initialize the HERE SDK manually. This can help to speed up loading time of the map view - as by default, the HERE SDK is initialized automatically when a map view is shown.

  • If your app immediately wants to show a map view after app start, then for most use cases it's sufficient to follow the Get Started guide - and the HERE SDK will be automatically initialized together with the map view. However:
  • If your app needs to show a map view at a later point in time or if a fast loading time is critical for you, consider to manually initialize the HERE SDK beforehand at a suitable point in time. Then, when the map view needs to be shown, the HERE SDK is already initialized and thus, less loading time is needed to show the map.

Below you can see how to manually initialize the HERE SDK. This also allows to inject credentials programmatically - together with other initialization options.

Set HERE Credentials from Manifest or Programmatically

All HERE SDK engines, except for SDKNativeEngine, can operate independently from each other and require HERE credentials to request data. The credentials can be set in the AndroidManifest file as shown in the Get Started guide - or programmatically. This can be useful, for example, to inject credentials at runtime from a web service.

By default, when using a map view in your app, the HERE SDK is initialized automatically and it is reading the credentials from the manifest. In addition, a default cache path is used for caching map data.

Use SDKOptions to set HERE Credentials and Cache Path

When you want to set the credentials programmatically, you need to create your own instance of the SDKNativeEngine, which can then be used to set or to change your HERE SDK credentials at runtime:

SDKOptions sdkOptions = new SDKOptions("YOUR_ACCESS_KEY_ID", "YOUR_ACCESS_KEY_SECRET", "");

SDKNativeEngine sdkNativeEngine = null;
try {
    sdkNativeEngine = new SDKNativeEngine(sdkOptions);
} catch (InstantiationErrorException e) {
    // Handle exception.
}

SDKNativeEngine.setSharedInstance(sdkNativeEngine);

try {
    SearchEngine searchEngine = new SearchEngine();
    // ...
} catch (InstantiationErrorException e) {
    // Handle exception.
}

This allows you to set a shared instance that will be used for all engines under the hood. Above, we initialize the SearchEngine as an example. Note that a shared instance is also required when you add a map view.

By setting an empty string as cache path, you keep the default cache path - which is also accessible via context.getCacheDir().getPath() or SDKNativeEngine.getSharedInstance().getOptions().cachePath.

Note: It is also possible to specify the cache path from the AndroidManifest file. Consult the API Reference for the SDKNativeEngine to see an example.

Multiple SDKNativeEngine instances can’t have the same access key id and the cache path is ensured to be unique per access key id. After creating a new SDKNativeEngine, the access key id cannot be changed. Only the secret key can be changed afterwards.

In general, it should not be necessary to initialize the HERE SDK multiple times and only one sharedInstance can be set.

Since turn-by-turn navigation requires caching, a valid cache path should be set when manually creating a SDKNativeEngine.

Alternatively, in rare use cases it may be useful to set an individual SDKNativeEngine instance for each of the feature engines:

SearchEngine searchEngine = new SearchEngine(sdkNativeEngine);

By default, the InitProvider of the HERE SDK will look for the credentials in your AndroidManifest file. Therefore, when setting credentials programmatically, keep the tags holding dummy values for id and secret, like shown in the snippet below. Empty values will lead to an exception:

<meta-data android:name="com.here.sdk.access_key_id" android:value="cdefgabc" />
<meta-data android:name="com.here.sdk.access_key_secret" android:value="cdefgabc" />

Alternatively, call InitProvider.initialize(appContext) to avoid that the SDKInitializer will look into the AndroidManifest file - this procedure is described in the next section.

Manually Initialize the HERE SDK

When you want to set credentials programmatically and you want to avoid keeping meta-data tags in the manifest (see above), you can disable the HERE SDK's InitProvider and manually initialize the HERE SDK.

The InitProvider is responsible for the initialization of the HERE SDK and it reads the credentials from the manifest file. If it cannot find the <meta-data>-tag that is supposed to hold the credentials, it will throw a MetaDataNotFoundException.

To disable the InitProvider, add a new <provider> tag to the app's manifest nested under the <application>-tag. As name/authorities, specify the InitProvider. Disable it by setting tools:node="remove":

<provider
    android:name="com.here.sdk.engine.InitProvider"
    android:authorities="com.here.sdk.engine.InitProvider"
    android:exported="false"
    tools:node="remove" />

For this, you also need to bind the tools namespace declaration to the manifest tag as follows:

<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.your_domain.your_app">

Finally, after the InitProvider has been disabled, you need to call InitProvider.initialize(appContext) to initialize the required platform modules. Make sure to call this before creating the SDKNativeEngine - and before setting the content view holding your map view (if your app contains a map view):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Specify credentials programmatically and keep default cache path by setting an empty string.
    SDKOptions sdkOptions = new SDKOptions("YOUR_ACCESS_KEY_ID", "YOUR_ACCESS_KEY_SECRET", "");

    // Manually initialize the HERE SDK.
    InitProvider.initialize(appContext);

    SDKNativeEngine sdkNativeEngine = null;
    try {
        sdkNativeEngine = new SDKNativeEngine(sdkOptions);
    } catch (InstantiationErrorException e) {
        // Handle exception.
    }

    SDKNativeEngine.setSharedInstance(sdkNativeEngine);

    setContentView(R.layout.activity_main);

    // Get a MapView instance from the layout.
    mapView = findViewById(R.id.map_view);
    mapView.onCreate(savedInstanceState);

    // Handle required Android permissions ...
}

This way, you can manually initialize the HERE SDK and avoid setting dummy credentials in your manifest file.

If you don't set your credentials programmatically, the HERE SDK will be initialized automatically using the values found in the manifest. Either way, invalid credentials will not block execution until these credentials are used to authenticate your app when you start to use an engine to request data - or when you want to show a map view.

Tip: One option to keep credentials secure is to store them on a secure server and retrieve them by requests using SSL connections. Credentials stored in AndroidManifest are easy to unveil, a better option can be to use data protection mechanisms.

For best practice, consider:

  • To avoid keeping sensitive data in plain text.
  • To transfer credentials using a secure communication channel.
  • To store credentials using device security mechanisms and strong encryption ciphers.
  • To add anti-tampering and anti-debugging code, so that a potential attacker cannot intercept data during dynamic runtime execution.
  • Track the application usage to detect anomalies.

Use Engines with or without a Map View

Engines do not need a map view to operate. Therefore it is possible to run an engine as a stand-alone, without any map view added to your application. This way, you can build an app solely around a specific engine. With or without a map view - the procedure to create a new engine is exactly the same:

try {
    searchEngine = new SearchEngine();
} catch (InstantiationErrorException e) {
    // Handle exception.
}

When you use the default constructor to initialize an engine for a stand-alone usage, the HERE SDK will use a shared SDKNativeEngine under the hood to take the credentials as found in the AndroidManifest file. Alternatively, you can provide the credentials programmatically as shown in the previous section.

It is not possible to initialize an engine during the Application's onCreate() lifecycle. Any other point in time is fine. For example, a good place to initialize an engine may be in an Activity's onCreate()-method.

Maps

One of the core features of the HERE SDK for Android is Mapping, which includes adding a map view, changing the location displayed by the map, and modifying its properties. The primary component of the mapping API is the map view, which is integrated as a View subclass. The map view represents a vector based view to display a map and various properties.

HERE map data is updated on a weekly basis to ensure you always get the freshest map data available. By integrating the map view you can automatically benefit from this. While the map is vector based, you can also integrate custom map tiles from other providers.

Note: To create a simple map application, please refer to the Get Started section.

To manipulate the map and its properties, it is best to start looking at the Camera section. More features include:

  • Map gestures to handle common map gestures and default map behaviors like pan or rotate.
  • Map schemes to instantly switch default map styles such as satellite versus normal map layer. More on the available map schemes you can find below.
  • Map items to place objects and shapes onto the map and interact with them.
  • Custom raster tiles to show custom server images as an additional map layer.
  • Custom map styles to fully customize the look of the existing map schemes.

Map Schemes

The HERE SDK supports five preconfigured map schemes:

  • NORMAL_DAY: A lossless scaleable vector base map for usage during daylight.
  • NORMAL_NIGHT: A lossless scaleable vector base map for usage during night.
  • HYBRID_DAY: A day version of a hybrid scheme combining satellite imagery with vector street network, map labels and POI information.
  • HYBRID_NIGHT: A night version of a hybrid scheme combining satellite imagery with vector street network, map labels and POI information.
  • SATELLITE: A bitmap based map showing satellite imagery for various zoom stages.

Note that it is also possible to fully customize your own map styles, except for the satellite imagery.

Use the following code snippet to load a map scheme:

MapScheme mapScheme = MapScheme.NORMAL_DAY;

mapView.getMapScene().loadScene(mapScheme, new MapScene.LoadSceneCallback(){
    @Override
    public void onLoadScene(@Nullable MapError mapError) {
        if (mapError == null) {
            // ...
        } else {
            Log.d(TAG, "Loading of map scheme failed: mapError: " + mapError.name());
        }
    }
});

It is recommended to use the day variants during day time when the surrounding light is brighter. The night variants are optimized for usage when there is less light. For example, an application may switch from day to night scheme when a driver is passing through a tunnel.

MapScheme.NORMAL_DAY
MapScheme.NORMAL_NIGHT
MapScheme.HYBRID_DAY
MapScheme.HYBRID_NIGHT

In addition, the HERE SDK offers a satellite scheme, that does not contain any labels:

MapScheme.SATELLITE

The available map styles are optimized to easily add additional content and overlays onto the base map without visual interference. The map schemes are less colorful and support a clean and neutral tone to maximize readability even in case of color blindness:

  • The street network is designed in gray scales and provides a hierarchy through brightness, contrast and widths.
  • Colors are overall rather bright set up.
  • Key colors are grey, blue, green, white.

HERE Logo Watermark

When using the HERE SDK, it is required that the HERE logo is always visible on the map view. By default, the HERE logo is located at the bottom right corner of the map. However, you can easily customize its location to meet your app design by calling setWatermarkPosition() on your map view instance. It is recommended to change the default placement only when it is required due to overlapping UI elements. Note for very small views: If both edges of the map are less than 250 density independent pixels in size, the watermark will be hidden automatically.

Remove Unused Font Files

The HERE SDK contains fonts to render map labels for all supported languages. If you want to optimize the size of the overall app, you can remove selected fonts. For example, the font with Chinese, Japanese and Korean characters is around 1.7MB. To remove this font, open the HERE SDK AAR file and remove the following files:

  • style/fonts/DroidSansFallback.woff
  • style/fonts/DroidSansFallback.license

When you remove a font, it is recommended to switch the map language to any other language than the removed font. At least one font needs to be left to see any map labels. Note that each time a label needs to be displayed in a language for a font that was removed an error message is logged - for each character that is missing.

Map Language

You can customize the language that is used on the map to show labels for streets, cities and other map data. By default, the local language of a region is used.

Call mapView.setPrimaryLanguage(languageCode) to set the language for the world - or set null to switch back to the default behavior. If a language is not supported in any region of the world, the local language for that region is shown instead.

Availability of Map Data

By default, a few regions in the world including Japan, China and Korea, contain limited map data. To get access to the full map data, please get in contact with your HERE representative.

Map Caching

To better support online and offline use cases, the HERE SDK for Android supports caching of downloaded vector map data. This happens in the background. While interacting with the map, the data is stored locally on the device and can be accessed even when the device loses connection or operates in an offline mode.

The integrated map caching mechanism only supports the standard vector based map schemes - satellite images, for example, are not cached.

Please note that the amount of cached data is limited and will be overwritten with new map data while using the map. In most cases, this is sufficient to give the user the impression of a faster start-up time - as no additional data must be downloaded when you start an app again at the same location as before.

Indoor Map

The HERE SDK provides the possibility to load, show and interact with private venues on the map. The HERE Indoor Map feature provides a wealth of hyperlocal information about indoor spaces, including building geometry and points of interest, spanning across multiple floors. HERE has mapped thousands of buildings globally, including, shopping malls, airports, train stations, parking garages, corporate campuses, factories, warehouses and many other types of buildings.

Your venue data will be shown only in your own app.

If you are a venue owner and are interested in leveraging the HERE Indoor Map feature with the HERE SDK, contact us at: venues.support@here.com.

results matching ""

    No results matching ""