> ## Documentation Index
> Fetch the complete documentation index at: https://docs.here.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Supplemental information

Find below essential supplemental information such as covering unit testing, thread safety, and dependency management.

## Unit testing

Inside the release package you can find a `heresdk-mock` JAR file that enables mocking - even for classes with static methods. This library is required to write unit tests when your code contains dependencies to the HERE SDK. It allows writing unit tests without the need to initialize the HERE SDK.

Note that the HERE SDK mock library contains hollow stubs without functionality. This means that you must use mocking to simulate functionality. For example, the `GeoCoordinates` constructor contains no code and can't set the values you pass. As a result, the value of `geoCoordinates.latitude` remains at its default value, which is `0`.

Below you can find instructions for an Android Studio project to automatically use the mock library when building unit tests and to use the real HERE SDK AAR when building your app code:

Place the `heresdk-mock-version-xxx.jar` into the same `app/libs` folder as the `heresdk-version-xxx.aar`.

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

```java
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'

    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.

Below you can see an example using [Mockito](https://site.mockito.org/). This will also work with most other frameworks that allow to create mocked objects:

```java
@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);
    }

    @Test
    public void testStaticMethod() {
        Angle angleMock = mock(Angle.class);
        when(angleMock.getDegrees()).thenReturn(10.0);

        // Each HERE SDK class with static methods contains helper code to make mocking easier.
        // Add heresdk-xxx.jar to access these additional mock helper instances.
        Angle.StaticMockHelperInstance = mock(Angle.StaticMockHelper.class);
        when(Angle.StaticMockHelperInstance.fromRadians(anyDouble())).thenReturn(angleMock);

        // Test static creation of Angle class. Static HERE SDK classes require a StaticMockHelperInstance.
        assertEquals(10.0, Angle.fromRadians(0.174533).getDegrees());

        verify(Angle.StaticMockHelperInstance, times(1)).fromRadians(anyDouble());
        verify(angleMock, times(1)).getDegrees();
        verifyNoMoreInteractions(Angle.StaticMockHelperInstance);
        verifyNoMoreInteractions(angleMock);
    }

    ...
}
```

Check the "UnitTesting" [example app](android-examples.md) to find more use case examples.

### Use constructor helpers

The mock library contains constructor helpers that help initialize struct-like classes. These helpers automatically initialize public, non-static fields, whose names match the constructor's parameter names. When the name of a parameter and a field don't match, you can provide a custom implementation.

To provide a custom implementation, implement the `ConstructorHelper` interface or extend the `ConstructorHelperImpl` class and set the `ConstructorMockHelperInstance` field to this implementation.

The `ConstructorHelper` interface contains methods named `_constructor(...)`, with one method for each constructor in the class where it is nested. Each `_constructor(...)` method has the same parameters as the related constructor and returns an instance of the class.

The `ConstructorHelperImpl` class implements the `ConstructorHelper` interface and provides default implementations as described earlier. You can extend this class and override only selected `_constructor(...)` methods. Each constructor, except the parameterless one, calls the corresponding version of `ConstructorMockHelperInstance._constructor(...)` and copies all public fields from the returned instance to the current instance.

Use the `ConstructorMockHelperInstance` approach when the constructor contains parameter names that are not exposed as members. See this example:

```java
class GeoCoordinatesUpdateMockHelper extends GeoCoordinatesUpdate.ConstructorHelperImpl {

    /**
     * The default implementation of `GeoCoordinatesUpdate.ConstructorHelperImpl` can't initializie the `latitude`,
     * `longitude`, and `altitute` fields of the `GeoCoordinatesUpdate` class. To initialize those fields,
     * you must use custom logic.
     */
    public GeoCoordinatesUpdate _constructor(@NonNull final GeoCoordinates coordinates) {
        // Each class of the HERE SDK Mock Library contains a parameterless constructor even if the original class doesn't.
        // This constructor can be used to create instances of the class and initialize
        // fields with default values.
        GeoCoordinatesUpdate _result = new GeoCoordinatesUpdate();
        _result.latitude = coordinates.latitude;
        _result.longitude = coordinates.longitude;
        _result.altitude = coordinates.altitude;
        // All public fields are copied in constructor
        // "GeoCoordinatesUpdate(@NonNull final GeoCoordinates coordinates)"
        return _result;
    }
}
```

#### Unit tests with custom constructors

```java
@RunWith(MockitoJUnitRunner.class)
public class TestBasicTypes {

    @Before
    public void SetUp() {
        // Use custom logic for constructors of "GeoCoordinatesUpdate" class.
        GeoCoordinatesUpdate.ConstructorMockHelperInstance = new GeoCoordinatesUpdateMockHelper();
    }

    @After
    public void TearDown() {
        // Reset to the default implementation.
        GeoCoordinatesUpdate.ConstructorMockHelperInstance = new GeoCoordinatesUpdate.ConstructorHelperImpl();
    }

    @Test
    public void testAutoGeneratedConstructor() {
        // "GeoCoordinates" has constructor with parameters "latitude" and "longitude" and
        // fields with the same names. In the example, the fields are
        // initalized by the constructor's parameters and "altitude" has the default value.
        GeoCoordinates geoCoordinates = new GeoCoordinates(10.0, 20.0);
        assertEquals(geoCoordinates.latitude, 10.0);
        assertEquals(geoCoordinates.longitude, 20.0);
    }

    @Test
    public void testSelfImplementedConstructor() {
        GeoCoordinates geoCoordinates = new GeoCoordinates(5.0, 10.0, 20.0);
        // This constructor uses "GeoCoordinatesUpdateMockHelper" which is set in "SetUp".
        GeoCoordinatesUpdate geoCoordinatesUpdate = new GeoCoordinatesUpdate(geoCoordinates);

        assertEquals(geoCoordinatesUpdate.latitude, 5.0);
        assertEquals(geoCoordinatesUpdate.longitude, 10.0);
        assertEquals(geoCoordinatesUpdate.altitude, 20.0);
    }
}
```

## Track HERE SDK Usage Statistics

The HERE SDK provides a way to monitor network usage using `UsageStats`. This class collects statistics on uploaded and downloaded data. Use `sdkNativeEngine.getSdkUsageStats()` and `sdkNativeEngine.enableUsageStats()` to retrieve network statistics. To reset the counters, use `sdkNativeEngine.clearPersistentUsageStats()` and `sdkNativeEngine.clearUsageStatsCache()`. To enable tracking, use the following:

```java
SDKNativeEngine.getSharedInstance().enableUsageStats(true);
```

Once enabled, the HERE SDK tracks network usage across different modules. To retrieve and log the tracked data, use the following method:

```java
private void logUsageStats() {
    List<UsageStats> currentUsageStats = SDKNativeEngine.getSharedInstance().getSdkUsageStats();
    for (UsageStats usageStat : currentUsageStats) {
        Log.d("UsageStats", "Network usage for feature: " + usageStat.feature.name());
        for (UsageStats.NetworkStats currentNetworkUsage : usageStat.networkStats) {
            Log.d("UsageStats", "Bytes sent: " + currentNetworkUsage.sentBytes);
            Log.d("UsageStats", "Bytes received: " + currentNetworkUsage.receivedBytes);
            Log.d("UsageStats", "Network requests sent: " + currentNetworkUsage.requestCounter);
            Log.d("UsageStats", "For method: " + currentNetworkUsage.methodCall);
        }
    }
}
```

Example logs may look like below. The log shows that the `RENDERING` layer was counted which occurs when data for the corresponding map data layer is requested by the application:

```xml
Network Usage for feature: RENDERING
Bytes sent: 12843
Bytes received: 257590
Network requests sent: 10
For method MapContent%RENDERING
```

`UsageStats` contains a list of `NetworkStats` for each `Feature`, such as `RENDERING` or `SEARCH`. Each `NetworkStats` entry includes `sentBytes`, `receivedBytes`, `requestCounter`, and the corresponding `methodCall` used by the respective `Feature`. `UsageStats` is retained only for the current app session.

Note that calling `enableUsageStats()` is not persisted by the HERE SDK - same as for other settings: therefore, `UsageStats` should be enabled every time before the initialization of the HERE SDK - if they have been enabled before at runtime and if you want to continue to track the network statistics. Also, please note that the gathered data is only counting HERE SDK usages for the executed app on a device.

## Thread safety

The HERE SDK is not guaranteed to be thread-safe and it is required 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.

Note that this rule does not apply to some classes, for example, the map data loading classes from the `mapdata` module such as `AdministrativeRulesLoader`, `SegmentDataLoader`, and `SegmentReferenceConverter`. Loading map data can be time‑consuming, so these classes can be used in a background thread to avoid blocking the main thread. However, please keep in mind that these classes are not thread‑safe, and each object should be used exclusively by a single thread.

## 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 [Integrate the HERE SDK](android-integrate-here-sdk.md) topic.

## Use the HERE SDK with other frameworks

You can use the HERE SDK with other frameworks. For example, it is possible to combine an open street map with a `SearchEngine`, if you wish to do so.

* [Xamarin](https://docs.microsoft.com/xamarin/get-started/): The HERE SDK does not support Xamarin, but customers can implement a wrapper for Xamarin on top of the public APIs offered by the HERE SDK. We do no commit to make changes to the HERE SDK to support the related test tooling for Xamarin.

* [React Native](https://github.com/facebook/react-native): React Native is not supported. However, customers can implement a wrapper on their own, but we do not provide any support for such a task.