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

ベストプラクティス

以下のセクションでは、HERE SDK for Androidを最大限に活用できるよう、最も一般的なユースケースについて説明し、ヒントとわかりやすいガイドラインを示します。

最適化の計画

HERE SDKのパフォーマンスを向上させるためのその他のオプションを確認できます。

  • マップキャッシュを最適化する:マップ キャッシュ ドキュメントのガイドラインに従って、キャッシュ メカニズムを調整します。
  • **条件付きのHERE SDKの初期化:**リソースを節約するには、必要な場合にのみ HERE SDK を初期化します。
  • フレームレートを調整する:MapViewのフレームレート設定を変更して、パフォーマンスと表示の滑らかさのバランスをとります。詳細なガイダンスについては、以下のフレームレートの調整に関するセクションを参照してください。
  • **カスタムマップスタイルでビジュアルを簡素化する:**レンダリングする要素の数が少ないカスタムマップスタイルを使用することで、レンダリングの効率が向上し、データ処理の負荷が軽減されます。

HERE SDK for Android Navigateを使用すると、次のことができます。

  • マップデータをプリロードする:オフライン マップを使用して事前にマップ データをダウンロードして保存することで、アクセスがスムーズになり、ライブ データ接続への依存が軽減されます。

さらに、HERE SDKでは、さまざまなエンジンで多様な設定オプションを提供しています。たとえばSearchEngineを利用すると、SearchOptionsを定義して、返される検索結果の範囲を絞り込んで制限できます。

低メモリ状態を処理する

アプリケーションがメモリに制約のあるデバイス上で実行される場合や、負荷が高い場合は、クラッシュを回避するためにメモリを効率的に管理することが重要です。HERE SDKには、このようなシナリオでメモリ使用量を最適化するメカニズムが用意されています。

低メモリの警告を検出して対応する

オペレーティングシステムからの (onLowMemory()onTrimMemory()コールバックなどを通じた) メモリ不足の圧力に対応するために、メモリ警告をリッスンし、それに応じてアクションを実行するハンドラーを実装します。以下は、考えられる実装の1つです。

@Override
public void onTrimMemory(int level) {
    super.onTrimMemory(level);
    if (level >= ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL) {
        handleLowMemory();
    }
}

@Override
public void onLowMemory() {
    super.onLowMemory();
    handleLowMemory();
}

handleLowMemory()の実装例を以下に示します。

低メモリモードを有効にしてキャッシュを消去する

メモリ消費を事前に削減するには、SDKOptionslowMemoryModeを有効にし、必要に応じてキャッシュを消去します。

public void handleLowMemory() {
    Log.d("Low Memory", "System is running low on memory. Initiating memory cleanup.");

    SDKNativeEngine.getSharedInstance().purgeMemoryCaches(SDKNativeEngine.PurgeMemoryStrategy.FULL);

    AuthenticationMode authenticationMode = AuthenticationMode.withKeySecret("YOUR_ACCESS_KEY_ID", "YOUR_ACCESS_KEY_SECRET");
    SDKOptions options = new SDKOptions(authenticationMode);
    options.lowMemoryMode = true;

    try {
        SDKNativeEngine.makeSharedInstance(context, options);
        Log.d("Low Memory", "Reinitialized HERE SDK with low memory mode enabled.");
    } catch (InstantiationErrorException e) {
        Log.e("Low Memory", "Failed to reinitialize HERE SDK: " + e.error.name());
    }
}

lowMemoryMode = trueを設定すると、SDKの内部キャッシュがより少ないメモリを使用するように構成されます。これは、RAMが制限されているデバイスや、メモリの圧力が高い場合に役立ちます。

lowMemoryModeをオンにすると、マップビューのレンダリングなど、HERE SDKのいくつかの機能のパフォーマンスに影響します。このため、オペレーティングシステムから低メモリ警告を受け取った後にのみ有効にするのが合理的な場合もあります。次のセクションでは、これを行う方法について説明します。

システムからメモリ圧力信号が送信された場合は、次のメソッドを使用してHERE SDKの内部キャッシュをクリアします。

SDKNativeEngine.getSharedInstance().purgeMemoryCaches(SDKNativeEngine.PurgeMemoryStrategy.FULL);

これにより、すべてのメモリ内のキャッシュに保持されているメモリが解放され、OOM (Out of Memory) クラッシュを防止できます。

現在サポートされているのはPurgeMemoryStrategy.FULLのみであり、これにより、どのデータも保持せずに、キャッシュされたすべてのコンテンツがクリアされます。

JavaDocをIDE (統合開発環境) に統合する

リリース パッケージには、オフラインで使用するための圧縮された HTML パッケージとして最新の「API リファレンス」と、JAR パッケージと同じデータを含む heresdk-javadoc.jar ファイルが含まれています。通常、IDE で作業しているときは API リファレンスにすぐにアクセスできません。

選択した IDE 内から API リファレンスに簡単にアクセスするには、IDE の指示に従って API リファレンス ファイルを統合します。

たとえば Android Studio の場合、次のように HERE SDK AAR を JavaDoc ファイルにリンクできます。

  1. 便宜上、heresdk-javadoc.jar ファイルを HERE SDK AAR と同じフォルダーにコピーします。
  2. Android Studioを開いて[プロジェクト]ビューに切り替えます。このビューは、ナビゲーションバーの上にあるプルダウンメニューから選択できます。
  3. [External Libraries](外部ライブラリ) ノードを展開します。HERE SDK AARが表示されます。
  4. HERE SDK AARファイルを右クリックし、[Library Properties](ライブラリプロパティ) を選択します。

Screenshot showing step 4: Right-click on the HERE SDK AAR file.

  1. [Library Properties](ライブラリプロパティ) ダイアログで**+**記号を選択します。
  2. ダウンロードしたJavaDoc JARファイルに移動して選択します。
  3. 選択したheresdk-javadoc.jarファイルのカテゴリーとして[JavaDocs]を選択します。

Screenshot showing step 7: Choose category for selected file.

  1. [OK]をクリックします。

最後に、JavaDoc API リファレンスがプロジェクト内で使用できることを確認します。

無料のリソース

インスタンスが参照されなくなった場合や null に設定された場合は、Android によりすべての HERE SDK クラスのガベージ コレクションが実行されます。

アプリの有効期間が終了したら、SDKNativeEngine.getSharedInstance().dispose() を呼び出してリソースを開放できます。また、SDKNativeEngine へのすべての参照を null に設定する必要があります (存在する場合)。dispose() を呼び出すと、保留中のリクエストが停止され、実行中の開いているファイルやデータベースが閉じられます。dispose() を呼び出した後、HERE SDK を再度初期化しない限り、関連する HERE SDK 機能は使用されなくなります。デフォルトのコンストラクタを使用して SearchEngine()RoutingEngine() のようなエンジンを作成した場合は、これらのインスタンスも再作成する必要があります。基本的に、SDKNativeEngine のインスタンスを破棄したら、同じインスタンスを使用していたすべてのエンジンを再作成する必要があります。

未使用の音声ファイルとフォント ファイルを削除してパッケージ サイズを小さくする

voice_package_ar-SAなどの未使用の音声ファイルを削除することで、HERESDKのパッケージサイズを小さくできます。これらの音声パッケージファイルは、音声合成エンジンを使用したターン・バイ・ターンナビを使用する場合にのみ必要です。音声ファイルはNavigateの一部としてのみ含まれます。

さらに、HERE SDKには、サポートされているすべての言語でマップラベルをレンダリングするために、いくつかのフォントファイルが含まれています。アプリ全体のサイズを最適化するために、選択したフォントを削除できます。

たとえば、DroidSansFallbackフォントでは、共有のUnicodeコードポイントに簡体字中国語の表意文字が使用されています。これは HERE SDK の AAR ファイルにパッケージ化されています (ファイル名に「.zip」を追加して開くことができます)。

  • assets/geoviz/fonts/DroidSansFallback.ttf

別の例として、日本語文字の完全なセットをレンダリングする必要がない場合は、以下を削除できます。

  • assets/geoviz/fonts/NotoSansJP-Regular.otf

なお、これらのフォントは日本と中国で使用されるだけでなく、世界中の他の地域でもユーザーがデバイスの言語を日本語または中国語に切り替える際に使用される可能性があります。

ファイルを削除するには、アプリの build.gradle ファイルを編集する必要があります。

Android Gradle プラグインのバージョンが 7.0 以上の場合は、以下のように AndroidResources を使用します。

android {
  ...
  androidResources {
      def languagesToRemove = ['ru-Ru', 'zh-HK']
      def languagePatterns = languagesToRemove.collect {"!voice_package_${it}*"}.join(":")
      ignoreAssetsPattern "${languagePatterns}:!DroidSansFallback.ttf:!NotoSansJP-Regular.otf"
  }
  ...
}

この操作により、リストされているフォントと音声アセットは最終パッケージから除外されます。さらに除外する必要がある場合は、それらもリストする必要があります。

この例では、区切り記号構文を使用してファイルを除外します。

こちらでは、サポートされているすべての音声言語のリストと、HERE SDK フレームワーク内に保存されている関連する音声スキンの名前を確認できます。または、AAR を解凍して AAR を調べ、除外する音声ファイルやフォント ファイルを検索します。

お使いの Android Gradle プラグインのバージョンが 7.0 未満の場合は、aaptOptions を使用して androidResources を置き換えます。

フォントを削除する場合は、削除したフォント以外の言語に地図言語を切り替えることをお勧めします。マップラベルを表示するには、少なくとも1つのフォントを残す必要があります。削除されたフォントの言語でラベルを表示する必要があるたびに、欠落している各文字に対してエラーメッセージが記録されます。

フォントファイルのサイズは、数百キロバイトから数メガバイトの幅があります。選択したフォントを削除すると、アプリケーションがデバイスにインストールされたときに消費される領域が少なくなります。この手順で節約できる最大容量は、約11MBです。

未使用のトラック制限アイコンを削除してパッケージサイズを削減する

HERE SDKバイナリ内の以下のパスから、未使用のトラック制限アイコンを手動で削除できます。

- /assets/geoviz/assets/oslo/truck_restriction/night/ui/
- /assets/geoviz/assets/oslo/truck_restriction/day/ui/

これらのアイコンは、IconProvider.createVehicleRestrictionIcon()およびIconProviderAssetType.UI設定を使用して以下の車両制限アイコンを作成する場合にのみ使用されます。これらは、対応するIconProviderAssetType.MAPと比べて、UIレンダリングに適しています。これらのファイルが削除されると、HERE SDKは自動的にMAPアセットを使用するようにフォールバックします。

これらのSVGアイコンはHERE SDKバイナリに含まれており、圧縮時に約264 KBを占有します。

IconProviderを使用する予定がなく、MapFeatures.VEHICLE_RESTRICTIONレイヤーを表示する必要もない場合は、assets/geoviz/assets/oslo/truck_restrictionフォルダー全体を削除することで、さらに大幅に容量を節約できます。

これらのファイルを削除するには、上記のセクションで説明されている手順に従ってください。

Android用ABI分割を使用して未使用のABIを削除する

サイズ管理:ABI 分割を使用すると、HERE SDK AAR バイナリ ファイルのパッケージ サイズを削減できます。その結果、アプリケーションがデバイス上で占有するストレージ容量が減ります。

デフォルトでは、HERE SDK for Android には、armeabi-v7aarm64-v8a (主にデバイスに使用)、x86x86_64 (主にエミュレータに使用) の ABI が含まれています。ABI 分割を有効にして、たとえば、armeabi-v7aarm64-v8a アーキテクチャ専用にアプリを構築できます。armeabi-v7a アーキテクチャは主に古いデバイスで使用されます。

そのためには、アプリの build.gradle ファイルを以下のように変更します。

android {
  (...)
  splits {
    abi {
      enable true
      reset()
      include 'x86_64', 'arm64-v8a' // Choose what you need.
      universalApk false
    }
  }
  (...)
}

これで、コマンド ラインから ./gradlew assembleRelease を実行すると、app-x86_64-release.apkapp-arm64-v8a-release.apk の 2 つの APK が生成されます。各 APK には必要な ABI のみが含まれるため、サイズはかなり小さくなっています。splitsブロックを変更してuniversalApk trueを設定すると、すべてのABIを含むuniversa APKも生成されますが、サイズはかなり大きくなります。

splits Gradle ブロックの詳細については、「ABI 用に複数の APK を設定する」を参照してください。

レガシー パッケージを使用することをお勧めします。

アプリの機能にもよりますが、デフォルトでは、リリース用の HERE SDK で構築された APK は約 103 MB 以上になります。そのため、アプリを Play ストアにリリースするには、ABI 分割または Android App Bundles (AAB) のいずれかを使用する必要があります。現時点では、Play ストアは APK を 100 MB まで、ABB は 150 MB までと制限しています。ABI 分割で構築した複数の APK を一部のアーキテクチャで維持しない場合、代わりに ABB を使用することを検討してください。

マップ レンダリング モード

サーフェス ビューまたはテクスチャ ビューを選択します。アプリケーションのニーズに応じて、MapView は 2 つの異なるネイティブ レンダリング モードをサポートしています。

  • デフォルトでは MapRenderMode.SURFACE を使用します。この場合、パフォーマンスは最適ですが、Android 12 以降でグラフィックに不具合が発生する可能性があります。
  • 複雑で動的な UI や複数の MapView インスタンスを使用するアプリケーションでは、グラフィックの不具合を防ぐために、MapRenderMode.TEXTURE を使用することを検討してください。このモードは、デフォルトの SurfaceView を使用するよりもパフォーマンスに大きな影響を与える可能性があります。

HereMapOptions.renderMode を使用して MapRenderMode を選択すると、レンダリング用にネイティブな SurfaceView または TextureView を内部的に設定できます。

フレームレートを調整する

デフォルトでは、MapViewは60フレーム/秒 (FPS) でレンダリングされます。mapView.get/setFrameRate() を使用して最大フレーム レートを調整し、たとえば、ローエンド デバイスでの CPU/GPU の使用量を削減できます。FPSを0に設定することで、自動レンダリングサイクルを非アクティブ化することもできます。負の値を設定しても効果はありません。この値は、アプリに複数のMapViewが含まれている場合は、MapViewインスタンスごとに設定できます。

もう 1 つのオプションは、レンダリングする要素が少ないカスタム マップ スタイルを使用することです。

資格情報を保護する

資格情報は、使用を意図していない第三者による不正使用を防止するために保護する必要があります。

資格情報の安全を確保するための選択肢の 1 つは、資格情報を安全なサーバーに保存し、SSL 接続を使用するリクエストによってその情報を取得することです。

ベストプラクティスとして、以下の点を考慮してください。

  • 秘密データをプレーンテキストで保持しないようにする。
  • 安全な通信チャネルを使用して資格情報を転送する。
  • デバイスのセキュリティ メカニズムと強力な暗号化機能を使用して資格情報を保存する。
  • 改ざん防止とアンチデバッグのコードを追加して、潜在的な攻撃者が動的なランタイム実行中にデータを傍受できないようにする。
  • アプリケーションの使用状況を追跡して異常を検出する。

コールバックとリスナー

  • HERE SDK は検索結果などの単一イベント通知のコールバックを公開しています。
  • ジェスチャー イベントなどの繰り返し発生するイベント通知にはリスナーが使用されます。複数のリスナーを設定できる場合は、メソッド パターンの add_x() および remove_x() が命名規則として使用されます。一度に設定できるリスナーが 1 つのみの場合は、プロパティ パターンが使用されます。リスナーを停止するには、リスナーのプロパティを null に設定します。
  • 開発者には、コールバックの範囲内のエラーを適切に処理する責任があります。ガイドラインとして、例外をスローする可能性のあるコードを処理する必要があります。

TaskHandlesを使用して非同期操作をキャンセルする

ほとんどの非同期メソッドは、即時の戻り値としてTaskHandleを提供しますが、操作の最終結果は遅れて完了ハンドラーで返されます。TaskHandleはステータス情報を提供し、進行中の操作を中止できます。

外部REST APIで使用するアクセストークンを取得する

HERE SDKが初期化されるたびに、新しいアクセストークンが内部的に生成されます。複数のSDKNativeEngineインスタンスがある場合、各インスタンスは独自のトークンを保持します。トークンは Authentication.authenticate(SDKNativeEngine.getSharedInstance(), callback) を介して更新および取得することもできます。このコールバックでは authenticationData.token を介してトークンが提供され、このトークンを使用すると外部の HERE REST API にアクセスできます。

HERE SDK自体を使用するためにトークンを把握する必要はありません。トークンは内部的にのみ必要とされ、HERE SDKはトークン生成を自動的に処理します。

バックエンドを不正使用から保護するため、生成されたトークンが多すぎる場合、または短期間に非常に多くのサービスにアクセスがあった場合は、レート制限が適用される場合があります。このような場合、エンジンはrequestLimitReachedまたは類似するエラーを返します。アプリの使用率が非常に高くなることが予想される場合は、HERE担当者に事前に連絡し、必要に応じて制限を調整してください。


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