ガイド変更履歴HERE SDK API references
ガイド

補足情報

単体テスト、スレッドセーフ、依存関係の管理など、重要な補足情報を以下に示します。

単体テスト

リリース パッケージの中には、静的メソッドを持つクラスでもモック化を有効にする heresdk-mock JAR ファイルが含まれています。コードにHERE SDKへの依存関係が含まれている場合、このライブラリは単体テストを記述するために必要になります。HERE SDKを初期化することなく単体テストを記述できます。

HERE SDKモックライブラリには、機能がなく中身のないスタブが含まれています。つまり、機能をシミュレートするためにモッキングを使用する必要があります。たとえば、GeoCoordinates コンストラクタにコードが含まれていないため、渡す値を設定できません。このため、geoCoordinates.latitudeの値はデフォルト値の 0 のままになります。

以下に、単体テストのビルド時にモック ライブラリを自動的に使用し、さらにアプリ コードのビルド時に実際の HERE SDK AAR を使用する Android Studio プロジェクトの手順を示します。

heresdk-mock-version-xxx.jarheresdk-version-xxx.aar と同じ app/libs フォルダーに配置します。

アプリの build.gradle 設定に次の依存関係を使用します。

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

この設定により、アプリで単体テストを実行するときはモック JAR を使用し、アプリをビルドするときは実際の HERE SDK AAR を使用します。

以下に、Mockito を使用した例を示します。これは、モック化されたオブジェクトを作成できる他のほとんどのフレームワークとも連携します。

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

    ...
}

「UnitTesting」サンプル アプリで、その他のユースケースの例を確認してください。

コンストラクタ ヘルパーを使用する

モック ライブラリにはコンストラクタ ヘルパーがあり、構造体のようなクラスの初期化を助けます。これらのヘルパーは、コンストラクタのパラメーター名と名前が一致する 静的でないパブリック フィールドを自動的に初期化します。パラメーター名とフィールド名が一致しない場合は、カスタム実装を提供できます。

カスタム実装を提供するには、ConstructorHelper インターフェースを実装するか ConstructorHelperImpl クラスを拡張して、この実装に ConstructorMockHelperInstance フィールドを設定します。

ConstructorHelper インターフェースには _constructor(...) という名前のメソッドが含まれ、ネストされているクラス内のコンストラクタごとに 1 つのメソッドがあります。それぞれの _constructor(...) メソッドは関連するコンストラクタと同じパラメーターを持ち、クラスのインスタンスを返します。

ConstructorHelperImpl クラスは ConstructorHelper インターフェースを実装し、前述のようにデフォルトの実装を提供します。このクラスを拡張して、選択した _constructor(...) メソッドのみを上書きできます。パラメーターのないコンストラクタを除く各コンストラクタは、対応するバージョンの ConstructorMockHelperInstance._constructor(...) を呼び出し、返されたインスタンスのすべてのパブリック フィールドを現在のインスタンスにコピーします。

コンストラクタにメンバーとして公開されていないパラメーター名が含まれている場合は、ConstructorMockHelperInstanceアプローチを使用します。この例は次のとおりです。

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

カスタム コンストラクタを使用した単体テスト

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

HERE SDKの使用状況統計情報を追跡する

HERE SDKは、UsageStatsを使用してネットワークの使用状況を監視する方法を提供します。このクラスは、アップロードおよびダウンロードされたデータに関する統計情報を収集します。sdkNativeEngine.getSdkUsageStats()sdkNativeEngine.enableUsageStats()を使用してネットワークの統計情報を取得します。カウンターをリセットするには、sdkNativeEngine.clearPersistentUsageStats()sdkNativeEngine.clearUsageStatsCache()を使用します。トラッキングを有効化するには、次を使用します。

SDKNativeEngine.getSharedInstance().enableUsageStats(true);

有効化すると、HERE SDKは異なるモジュール間でネットワーク使用状況を追跡します。追跡したデータを取得して記録するには、次のメソッドを使用します。

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

ログの例は次のようになります。ログには、対応するマップデータレイヤーのデータがアプリケーションによってリクエストされたときに発生するRENDERINGレイヤーがカウントされたことが示されています。

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

UsageStatsには、RENDERINGSEARCHなどの各Featureに対応するNetworkStatsのリストが含まれます。各NetworkStatsエントリーには、sentBytesreceivedBytesrequestCounter、およびそれぞれのFeatureで対応するmethodCallが含まれます。UsageStatsは、現在のアプリセッションでのみ保持されます。

他の設定と同様に、enableUsageStats() の呼び出しは HERE SDK によって保持されません。そのため、UsageStats が実行時以前に有効になっており、ネットワーク統計の追跡を継続する場合は、HERE SDK を初期化する前に毎回これを有効にします。また、収集されたデータは、デバイス上で実行されたアプリの HERE SDK の使用量のみを集計していることに注意してください。

スレッド セーフ

HERE SDK では、スレッド セーフであることは保証されていません。メイン スレッドから SDK を呼び出す必要があります。内部的には、HERE SDK はほとんどの作業をバックグラウンド スレッドにオフロードしますが、コードへのコールバックは常にメイン スレッドで行われます。一般的に、スレッド セーフの確保は呼び出し元の責任です。たとえば、コードが同期されていない限り、さまざまなスレッドで 1 つのエンジンを再利用することは安全ではありません。

依存関係の管理

現時点では、Gradle などを使用する依存関係管理はまだサポートされていません。つまり、HERE SDK AARバイナリは、「HERE SDKを統合する」トピックで説明されているように、アプリケーションプロジェクトにローカルでコピーする必要があります。

HERE SDK を他のフレームワークと使用する

HERE SDK は他のフレームワークと併用できます。たとえば、希望する場合はオープン ストリート マップと SearchEngine を結合できます。

  • Xamarin:HERE SDK は Xamarin をサポートしていませんが、HERE SDK が提供する公開 API に Xamarin のラッパーを実装できます。HERE SDK に変更を加えて Xamarin 向けの関連するテスト ツールをサポートするお約束はできません。

  • React Native:React Native はサポートされていません。ただし、お客様ご自身でラッパーを実装することはできます。しかし、このようなタスクに対するサポートは提供していません。


EN 日本語

HERE documentation

Find answers to your product and technical questions

Documentation

What's new

Videos

EN 日本語

HERE ドキュメント

製品や技術に関する質問の答えを見つけましょう。より多くの内容と最新の情報については、英語版をご覧ください。

ドキュメント

ダイナミックマップ

動的コンテンツ関連のAPIをアプリやサービスに活用して、ドライバーが安全・快適かつ予定どおりに目的地へ到着できるよう支援します。

地図とデータ

世界中を走行する多数のマッピング車両から得られる最新の位置情報データを活用し、精度の高い地図やカスタムレイヤーを構築できます。

最新情報

動画

(function () { const input = document.querySelector('input[data-typeahead]'); if (!input) return; // Prevent the form from submitting/navigating input.closest('form')?.addEventListener('submit', e => e.preventDefault()); input.addEventListener('input', function () { const q = this.value.trim().toLowerCase(); document.querySelectorAll('.nav-group-name').forEach(group => { let anyVisible = false; group.querySelectorAll('.nav-group-task').forEach(task => { const text = task.textContent.trim().toLowerCase(); const show = !q || text.includes(q); task.style.display = show ? '' : 'none'; if (show) anyVisible = true; }); // Hide the whole group header if nothing matches group.style.display = anyVisible || !q ? '' : 'none'; }); }); })(); (function () { function onTokenClick(event) { var link = event.target.closest('.sdk-for-ios .item .token'); if (!link) return; event.preventDefault(); console.log('token clicked', link.textContent.trim()); var item = link.closest('.item'); if (!item) return; var content = item.querySelector('.height-container'); if (!content) { console.log('no .height-container found for item', item); return; } var isHidden = window.getComputedStyle(content).display === 'none'; content.style.display = isHidden ? 'block' : 'none'; link.classList.toggle('token-open', isHidden); var href = link.getAttribute('href'); if (href) { if (history.pushState) history.pushState({}, '', href); else location.hash = href; } } function openHashTarget() { var hash = window.location.hash.slice(1); if (!hash) return; var anchor = document.querySelector('.sdk-for-ios a[name="' + hash + '"]'); if (!anchor) return; var item = anchor.closest('.item'); if (!item) return; var link = item.querySelector('.token'); var content = item.querySelector('.height-container'); if (!link || !content) return; content.style.display = 'block'; link.classList.add('token-open'); } function init() { console.log('HERE SDK accordion init'); openHashTarget(); } document.removeEventListener('click', onTokenClick); document.addEventListener('click', onTokenClick); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } window.addEventListener('hashchange', openHashTarget); window.addEventListener('pageLoad', init); })();