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:
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. 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);
}
@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 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:
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
@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:
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:
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:
Network Usage for feature: RENDERING
Bytes sent: 12843
Bytes received: 257590
Network requests sent: 10
For method MapContent%RENDERINGUsageStats 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.
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 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: 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: 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.
Updated yesterday