現在地を検索

マッピングアプリケーションを使用する主な理由の 1 つは、自分がどこにいるかを確認することです。

HERE SDK が提供するLocationEngineは、 GPS やその他のグローバル衛星ナビゲーションシステム( GNSS )受信機、モバイルネットワーク信号、 Wi-Fi ネットワーク信号などの複数の位置情報源と連携して正確な位置を判断する、包括的な位置情報ソリューションを実装しています。

iOS デバイス 自体が GNSS 精度に対応している場合は、 iOS デバイス のハードウェアに依存します。 サブメーターの精度は現在 iOS ではサポートされていないため、別のレシーバーが必要です。 Android デバイスでは、サブメーターの精度は、資格情報 が有効になっている場合にのみサポートされます ( 以下を参照 ) 。

簡単に確認できます

HERE SDK の位置情報フィーチャーを統合するには、少なくとも次の手順を実行する必要があります。

  1. マニフェストファイル( Android の場合)およびファイル .plist ( iOS の場合)に必要な権限を追加し、ユーザーに権限を要求します。
  2. データをLocationEngine によって収集できるかどうかを確認する承諾ダイアログConsentEngineを作成して表示します。
  3. 承諾ダイアログの結果を表示し、ユーザーが以前の決定を削除できるようにします。
  4. LocationEngineを作成し、少なくとも 1 つのLocationListenerを設定します。
  5. LocationEngineを1回開始し、必要な精度レベルを設定します。
  6. Location の更新を受信し、アプリで処理します。

必要な権限を追加

フラッター自体には、権限の処理はありません。 そのため、 Android および iOS のネイティブプロジェクト用に、生成されたファイルをいくつか調整する必要があります。

まず、 Android を使用してみましょう。

Android デバイスのアプリでのLocationEngineの使用を開始する前に、アプリ のAndroidManifest.xmlファイルに必要な権限を追加する必要があります( _PROJECT_dir/Android/app/src/main/ にあります)。

...
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />

アプリが Android SDK バージョン 31 以降を対象とする場合 、アプリのユーザーはデバイスの「正確な」位置情報を付与する必要があります。 プロンプトが表示された場合 、「近似」の精度を選択するだけでは不十分です。 したがって 、上記のように、マニフェストファイルにACCESS_COARSE_LOCATIONACCESS_FINE_LOCATION権限が存在する必要があります。 HERE Positioning で GNSS を使用し、携帯電話および WiFi スキャンを行うには、ファインロケーション許可が必要です。 このACCESS_COARSE_LOCATION権限だけでは、 HERE Positioning が動作するのに十分ではない近似の精度になるため、十分ではありません。 この場合、LocationEngineMISSING_PERMISSIONS エラーで失敗します。

WAKE_LOCK HERE SDK によって権限が強制されませんが、アプリケーションに権限が付与されている場合、 HERE SDK はウェークロックを使用して、省電力モードになっているデバイスによってネットワークスキャンおよび位置の計算が中断されないようにします。 ウェイクロックは、バッテリー消費への影響をできるだけ少なくするために、必要な時間だけ保持されます。 Android オペレーティング システムは、ウェイクロックを継続的に維持しているアプリケーションまたはサービスがバッテリー消費の原因であることに注意してください。そのため、アプリケーションをユーザーにとって魅力的な状態に保つには、ウェイクロックがユースケースにとって必須であるかどうか、またはウェイクロックが必須であるかどうかを慎重に検討する必要があります。

次に、 iOS に移動します。

アプリ Info.plist のファイルに追加 します( _PROJECT_dir/ios/Runner/に あります)。

<key>UIRequiredDeviceCapabilities</key>
<array>
   <string>location-services</string>
   <string>gps</string>
</array>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
   <string>This app needs to access your current location to display it on the map.</string>
<key>NSLocationWhenInUseUsageDescription</key>
   <string>This app needs to access your current location to display it on the map.</string>
<key>NSMotionUsageDescription</key>
   <string>Motion detection is needed to determine more accurate locations, when no GPS signal is found or used.</string>

バックグラウンド NSLocationAlwaysAndWhenInUseUsageDescription で位置情報の更新を要求する場合にのみ、権限が必要になります。

permission_handler プラグインを使用して、ユーザーから特定の権限を要求できます。 詳細については、プラグインの公式サイトを参照してください。 または、 HERE SDK for iOS for the HERE SDK for Android and 開発者ガイド for the 開発者ガイドの「 Find Your Location 」セクションで、権限を要求するためのプラットフォーム固有のコードを見つけることもできます。

GPS などのネイティブの位置情報サービスを使用するアプリは、ユーザーの許可を要求します。 すべてのデバイスが同じ機能を提供しているわけではありません。また、特定のハードウェアの制約があるため、結果が異なる可能性があります。

最近の iPad または Android タブレットデバイスであっても、 UIRequiredDeviceCapabilities に必要なものが不足 gpsしている可能性があります。 Info.plist ファイルに存在する場合、アプリ はこのようなデバイスにインストールされません。 この機能を削除すると、アプリ がインストールされますが Location 、デバイスから受け取る更新の精度は半径が大きくなり、結果として非常に不正確になります。 GPS センサーがない場合、デバイスはネットワークの配置などにフォールバックすることがあります。

を使用する前 LocationEngineに、ネイティブの位置情報サービスが有効になっているかどうかを確認することをお勧めします。 ほとんどの Android デバイスでは、ユーザーが位置情報サービスをオンにすることを選択できます。さらに、デバイスの [ 設定 ] を開き、 [ セキュリティと位置情報 ] セクションに移動することで、精度を上げることもできます。 ほとんどの iOS デバイスでは、ユーザーは [ 設定 ] > [ プライバシー ] > [ 位置情報サービス ] の順に移動して位置情報サービスがオンになっていることを確認できます。

LocationEngine は、 HERE SDK が使用する HERE サービスを改善するために、モバイル機器の周辺についての特定の情報を収集できる機能が含まれています。 そのような情報の例として、近くの Wi-Fi およびモバイルネットワークの信号の強度があります。

HERE SDK は ConsentEngine 、ユーザーがデータを収集することに同意したことを取得するためのフローを処理するを提供します。 さらに、現在のステータスを取得し、データを収集するかどうかを判断する前の決定を削除できます。 アプリケーションは、ユーザーがいつでもアクセスできるようにする必要があります。

注 : 要件

承諾ダイアログの表示は必須です。 LocationEngine は、ユーザーが決定するまで位置情報データをアプリ に送信しません。 ユーザーが承諾を付与または拒否した場合でも、LocationEngine 完全に動作可能になります。

次の 2 つのステップが必要です。

  • consentEngine.requestUserConsent()を呼び出して、承諾ダイアログを表示します。
  • アプリケーションは、ユーザーの現在の決定内容を表示し、以前の決定内容を削除する必要があります。 consentEngine.userConsentState経由で現在の決定を取得します。 ユーザーが再度 consentEngine.requestUserConsent() をコールすることを許可して、前の決定を取り消します。 これは、アプリのライフサイクル中いつでも可能である必要があります。

これらの手順については、以下で詳しく説明します。 詳細については、 HERE SDK のプライバシーに関する補足情報を参照してください。 情報は、ユーザーが同意した場合にのみ収集されることに注意してください。 収集された情報はユーザーを特定するものではなく、 HERE は匿名化された情報のみを保持します。

注 : 上記の要件は、現在 iOS プラットフォームにデータ収集がないため、 Android アプリケーションにのみ適用されます。 これは今後変更される可能性があります。

iOS デバイスでは、呼び出し consentEngine.requestUserConsent() によってダイアログが表示されますが 、呼び出す必要はありません。 デフォルトの承諾状態はです notHandled。 iOS では、 ConsentEngineのメソッドおよびプロパティ(userConsentStategrantUserConsent() および denyUserConsent())は Android と同じように動作しますが 、 iOS では処理しないことをお勧めします。 Android で は、有効な状態(granted または denied)を設定するための承諾を要求する必要があるため、notHandled状態によってLocationEngineを使用できません。 iOS で LocationEngine は、状態に関係なく、はすぐに使用できます。

ローカリゼーションの設定中です

承諾エンジンは、最大 31 の言語をサポートしています。 ダイアログが表示されたときに使用された言語は、現在のデバイスの言語設定に基づいて自動的に選択されます。 デバイスの言語がサポートされている言語でない場合は、代わりに英語が使用されます。 以下のコード スニペットでは、ローカライズされた承諾ダイアログをサポートするようにアプリケーションを設定する方法を示します。

// File: main.dart

import 'package:flutter/material.dart';
import 'package:here_sdk/consent.dart';

import 'PositioningExample.dart';

// ...

void main() {
    runApp(
        MaterialApp(
            // Add consent localization delegates.
            localizationsDelegates: HereSdkConsentLocalizations.localizationsDelegates,
            // Add supported locales.
            supportedLocales: HereSdkConsentLocalizations.supportedLocales,
            home: MyApp(),
        ),
    );
}

// ...

class MyApp extends StatefulWidget {
    
    PositioningExample createState() => PositioningExample();
}

LocationEngineを開始する前 に、前述の情報を収集するユーザーの同意が得られていることを確認する必要があります。 回答の内容に関係なく ( ユーザーがデータの収集を承諾したかどうかに関係なく ) 、承諾ダイアログが表示され、回答が提供されたことのみが該当します。 LocationEngineは、ユーザーの同意を得ずに開始しようとすると、LocationEngineStatus.USER_CONSENT_NOT_HANDLEDステータスを返します。

以下のコード スニペットは、 ConsentEngineのインスタンスを作成し、ユーザーの同意がすでに要求されているかどうかを確認します。要求されていない場合は、ユーザーに収集された情報の詳細を説明する UI ダイアログ ( 以下の図も参照 ) を呼び出します。 権限を付与または拒否することができます。

try {
  _consentEngine = ConsentEngine();
} on InstantiationException {
  throw ("Initialization of ConsentEngine failed.");
}

// ...

Future<void> _ensureUserConsentRequested() async {
  // Check if user consent has been handled.
  if (_consentEngine.userConsentState == ConsentUserReply.notHandled) {
    // Show dialog.
    await _consentEngine.requestUserConsent(context);
  }

  _updateConsentInfo();
  _startLocating();
}

マップ シーンのロード中は、requestUserConsent()を呼び出さないことをお勧めします。

のコード _updateConsentInfo() は HERE の外にあります。 基本的に、ユーザーの現在の承諾の決定が表示されます。

スクリーンショット: 承諾のダイアログ。

このダイアログには、 HERE のプライバシープラクティスについて説明した Web ページへのリンクが含まれており、 37 言語をサポートしています。 表示されているダイアログは、デバイスの言語設定に従って表示されます。サポートされていない場合は、英語で表示されます。

ユーザーの応答は、アプリケーションの使用セッション間で保持され、 userConsentState プロパティを使用して取得できます。このプロパティは Consent.UserReply 、次の値を返します。

switch (_consentEngine.userConsentState) {
  case ConsentUserReply.granted:
    //The user has previously given permission.
    break;
  case ConsentUserReply.denied:
    // The user has previously denied permission.
    break;
  case ConsentUserReply.notHandled:
    //The user has not been asked for consent.
    break;
  case ConsentUserReply.requesting:
    //The dialog is currently being shown to the user.
    break;
  default:
    throw Exception("Unknown consent state.");
}

アプリケーションは、プロパティにアクセスして、ユーザーが以前に入力した応答を参照できるようにする必要 userConsentState があります。 また、 requestUserConsent() このアプリケーションでは、メソッドを呼び出して承諾ダイアログを再度表示することで、いつでもユーザーが同意についての考え方を変更できるようにする必要があります。

Android で requestUserConsent() は、が呼び出されると、 HERE SDK に Activity ダイアログを含む新しいが表示されます。 ダイアログが閉じると、前の Activity ダイアログが再開されます。 MapView ダイアログを開く前にが表示 MapView されている場合、は再び表示されるまで一時停止されます。

注 : 重要

現在、 iOS プラットフォームにはデータ収集がありません。 これは今後変更される可能性があります。 それまでの間、上記の要件は Android アプリケーションにのみ適用されます。 以下のコード スニペットでは、 Android プラットフォームでユーザーが承諾に与えた応答、およびユーザーの心理を変更できることを示す画面を実装する方法を 1 つ示しています。 また、他のプラットフォームでは、データ収集がないことをユーザーに通知するメッセージが表示されます。

// ...

// Platform class from dart:io library provides a way to check on what platform your app is running.
import 'dart:io' show Platform;

// ...

class ConsentPreferencesPage extends StatefulWidget {
  ConsentPreferencesPage({Key key, this.title}) : super(key: key);

  final String title;

  
  State<ConsentPreferencesPage> createState() {
    //Use different states according to the platform the app is running on.
    if (Platform.isAndroid) {
      return _ConsentPreferencesPageAndroid();
    }
    return _ConsentPreferencesPageOther();
  }

// ...

// This state shows what response the user has given to the consent, by accessing the consentEngine.userConsentState property. Additionally, it allows the user to change their mind on the consent by including a button "Manage Consent" that calls the requestUserConsent() method and displays the consent dialog again.
class _ConsentPreferencesPageAndroid extends State<ConsentPreferencesPage> with WidgetsBindingObserver {
  try {
    _consentEngine = ConsentEngine();
  } on InstantiationException {
    throw ("Initialization of ConsentEngine failed.");
  }

  String _getConsentAnswer() {
    switch (_consentEngine.userConsentState) {
      case ConsentUserReply.granted:
        //The user has previously given permission.
        return "You have granted consent to the data collection.";
      case ConsentUserReply.denied:
        // The user has previously denied permission.
      case ConsentUserReply.notHandled:
        //The user has not been asked for consent.
      case ConsentUserReply.requesting:
        //The dialog is currently being shown to the user.
        return "You have denied consent to the data collection.";
      default:
        throw Exception("Unknown consent state.");
    }
  }

  // ...

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        margin: const EdgeInsets.only(left: 25, right: 25),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Flexible(
                child: Text(
                    'The Location Engine contains functionality that can gather certain '
                        'information about the surroundings of the mobile device in order '
                        'to improve the HERE services used by the HERE SDK. An example '
                        'of such information is the strength of the nearby Wi-Fi and '
                        'mobile network signals.'
                ),
            ),
            SizedBox(height: 20),
            Flexible(
                child: Text(
                    _getConsentAnswer(),
                ),
            ),
            SizedBox(height: 20),
            PlatformButton(
                child: const Text("Manage Consent"),
                onPressed: () {
                  setState(() {
                    _consentEngine.requestUserConsent(context);
                  });
                }
            ),
          ],
        ),
      ),
    );
  }

// ...

// This state informs the user that there is currently no data collection.
class _ConsentPreferencesPageOther extends State<ConsentPreferencesPage> {
  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        margin: const EdgeInsets.only(left: 25, right: 25),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Flexible(
              child: Text('This app does not collect any data on this platform.'),
            ),
          ]
        )
      )
    );
  }
}

サンプルのフローは 、 GitHub にある Positioning Example アプリに記載されています。

LocationEngineを使用するには、ユーザーの同意を要求する必要があります。 既定では、上記の API を使用してこの問題が発生します。

ダイアログの外観と内容をカスタマイズできます。 このためには、 HERE に、アプリケーション独自にカスタマイズしたユーザーの同意ダイアログを証明するよう依頼します。 証明書を受け取ると、アプリケーションは grantUserConsent()denyUserConsent() のメソッドを使用して HERE SDK に対するユーザーの応答を伝達できます。HERE が、アプリケーションによってカスタムダイアログを開始できることを承認した場合、requestUserConsent() の呼び出しは不要になります。 通信したユーザーの応答は HERE SDK によって保持 getUserConsentState() され、メソッドを使用して以前に指定した応答を取得できます。

特定の事前要件の下で、別の方法で承諾の決定を要求または更新することも可能です。 たとえば、ユーザーがすでに外部の Web サイトで承諾を付与している場合です。 ただし、ソリューションについては、 HERE チームと個別に話し合う必要があります。

このオプションの詳細について確認 するか、または HERE の営業担当者またはヘルプページから HERE に連絡して認定プロセスを開始してください。

LocationEngine を作成します

LocationEngine の新規作成は簡単です。

try {
  _locationEngine = LocationEngine();
} on InstantiationException {
  throw ("Initialization of LocationEngine failed.");
}

ApplicationonCreate()ライフサイクル中は、LocationEngineを初期化できません。 それ以外の任意の時点で問題はありません。 たとえば、エンジンを初期化するのに適した場所が ActivityonCreate()メソッドに含まれている可能性があります。

最後に確認した場所を取得

エンジンが初期化されると、少なくとも 1 回前にエンジンが始動し、少なくとも 1 つの位置を受信している限り、最後に確認された位置を取得できます。そうでない場合、null が返されます。 この情報は残ります。したがって、最後に確認された場所もアプリケーションセッション間で利用できます。

Location? myLastLocation = _locationEngine.lastKnownLocation;

if (myLastLocation != null) {
    // Log the last known location coordinates.
    print("Last known location: " + myLastLocation.coordinates.latitude.toString() + ", " + myLastLocation.coordinates.longitude.toString());
}

LocationEngine 最後の既知の場所を取得するために、を開始する必要はありません。また、リスナーを設定する必要もありません。 が LocationEngine 前のセッションで 1 回正常に開始され、有効な位置イベントが少なくとも 1 回受信されただけで十分です。 Location オブジェクトには timestamp 、その場所がいつ受信されたかを示すが含まれています。

位置情報イベントに関する通知を受信

次に、 LocationEngine を開始する前に LocationStatusListener を登録して、エンジンのステータスの変更が通知されるようにすることをお勧めします。 そのためには LocationStatusListener 、抽象クラスを実装し、 Location Engine addLocationStatusListener() のメソッドに登録します。 さまざまなステータスの詳細については、 API リファレンス を確認してください。

class PositioningExample extends State<MyApp> implements LocationStatusListener {

  
  onFeaturesNotAvailable(List<LocationFeature> features) {
    for (var feature in features) {
      print("Feature not available: " + feature.toString());
    }
  }

  
  onStatusChanged(LocationEngineStatus locationEngineStatus) {
    print("LocationEngineStatus: " + locationEngineStatus.toString());
  }

// ...

// Add the listener.
_locationEngine.addLocationStatusListener(this);

開始が成功すると、LocationStatusListenerは常にステータスLocationEngineStatus.engineStartedを受信し、停止が成功すると、常にステータスLocationEngineStatus.engineStoppedを受信します。

また、リスナー onFeaturesNotAvailable() のコールバック を通じて LocationFeature 、利用できないものがあれば通知されます。 必要な機能が利用できない場合は、HERE の担当者にご連絡ください。

エンジンを始動する前に考慮すべき最後の作業は、LocationListenerを登録することです。これにより、新しいLocationが検出されたときに通知を送信するonLocationUpdated()コールバックが提供されます。 これは、前述のLocationStatusListenerと同様の方法で行うことができます。

class PositioningExample extends State<MyApp> implements LocationListener {
    
    onLocationUpdated(Location location) {
        print("Received location: " + location.coordinates.latitude.toString() + ", " + location.coordinates.longitude.toString());
    }

// ...

// Add the listener.
_locationEngine.addLocationListener(this);

コールバック onLocationUpdated() はメインスレッドで受信されます。他のすべてのコールバックと同じです。

現在の地理座標およびタイムスタンプを除き、その他 Location のすべてのフィールドはオプションです。 たとえば、受信 したオブジェクトLocation には、ベアリング角度および現在の速度に関する情報が含まれている場合がありますが、この情報は利用できることは保証されていません。 使用できない値は、として返さ nullれます。 ポジショニングに使用されるソースの種類( エンジンの始動に使用されるLocationAccuracyによって定義されます。以下の「 Start and Stop Receiving Locations 」セクションを参照してください)と、デバイスの機能が利用可能なフィールドに影響を与えます。

それぞれのaddLocationStatusListener()メソッドおよびaddLocationListener()メソッドを呼び出して、必要なだけLocationStatusListenerおよびLocationListenerを追加できます。

受信地点の開始および停止

LocationEnginestartWithLocationAccuracy() メソッドを呼び出す準備ができました。

class PositioningExample extends State<MyApp> implements LocationListener, LocationStatusListener {
    try {
      _locationEngine = LocationEngine();
    } on InstantiationException {
      throw ("Initialization of LocationEngine failed.");
    }

    try {
      _consentEngine = ConsentEngine();
    } on InstantiationException {
      throw ("Initialization of ConsentEngine failed.");
    }

// ...

    if (_consentEngine.userConsentState == ConsentUserReply.notHandled) {
        await _consentEngine.requestUserConsent(context);
    }

    _updateConsentInfo();
    _startLocating();

// ...

void startLocating() {
    _locationEngine.addLocationListener(this);
    _locationEngine.addLocationStatusListener(this);
    _locationEngine.startWithLocationAccuracy(LocationAccuracy.bestAvailable);
}

エンジンを始動する最も簡単な方法は、上記のコード スニペットのように、定義済みのモードの 1 つLocationAccuracyを渡すことです。 使用可能なすべてのモードの詳細については、次の表を参照するか、 API リファレンス を確認してください。

LocationEngineが開始された後、最初にstop()をコールしないで、再度開始しようとすると、LocationEngineStatus.alreadyStartedが届きます。 このメソッドisStarted() を使用して、エンジンが始動しているかどうかを確認できます。 同様に、LocationEngineを開始し、最初のを停止せずに別のを開始しようとすると、LocationEngineStatus.alreadyStartedエラーが発生します。 一度に始動できるエンジンは 1 つだけです。

位置情報の更新をこれ以上受信したくない場合 stop() は、メソッドを呼び出してエンジンを停止できます。 不要になったリスナーは必ず削除してください。

void stopLocating() {
    _locationEngine.removeLocationStatusListener(this);
    _locationEngine.removeLocationListener(this);
    _locationEngine.stop();
}

一般 的に、アプリの廃棄時に、AppLifecycleStateを聴いてLocationEngineを停止することをお勧めします。 GitHub の例については、positioning_appを参照してください。

iOS デバイスで停止中に更新を一時停止します

iOS デバイスで LocationEngine は、はデフォルトで、位置情報の変更が予期されない場合に位置情報の更新を一時停止します。 これを使用すると、たとえば、デバイスが静止しているときのバッテリー寿命を改善できます。 この機能は、メソッドで制御 LocationEngine.setPauseLocationUpdatesAutomatically()できます。

Android の plaftorms で setPauseLocationUpdatesAutomatically() は、が返さ LocationEngineStatus.notSupportedれます。

バックグラウンド更新を有効化

アプリケーションがバックグラウンドで実行されているときに位置情報の更新を引き続き受信する場合は、まず必要な権限を追加してこの機能を有効にする必要があります。 Android では、 Android 10 ( API レベル 29 )以上を対象とする場合にのみ必要です。 アプリ AndroidManifest.xml のファイルに次の権限を追加します。

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

Android 14 以降をサポートする FOREGROUND_SERVICE_LOCATION には、権限も必要です。

また、 Android API レベル 29 以上の Android デバイスでアプリをバックグラウンドで実行し続ける場合は、フォアグラウンドサービスまたは同等のサービスを開始する必要があります。 バックグラウンド位置情報を要求する Android では、フォアグラウンド位置情報の権限を要求するのとは異なることに注意してください。 詳細については、 Android のドキュメントを参照してください。 アプリ のポジショニング例 では、 Android 29 以降でのバックグラウンドポジショニングのサポート方法はまだ示されていません。

アプリが Android API レベル 28 以下を対象としている場合、前の「必要な権限を追加する」セクションで説明した権限がアプリによってすでに要求されている限り、バックグラウンドでの更新をサポートするために変更を加える必要はありません。

iOS では、アプリ Info.plist のファイルに次のキーを追加することで、バックラウンド更新を有効にできます。

<key>UIBackgroundModes</key>
    <array>
        <string>location</string>
        <string>processing</string>
    </array>

iOS バージョン 13.0 以降では、「処理」モードが必要です。 追加する場合は、次のものも必要です。

<key>BGTaskSchedulerPermittedIdentifiers</key>
    <array>
        <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    </array>

詳細については、 iOS のドキュメントを参照してください。

ユーザーに自動化を要求する必要があることに注意してください。 ユーザーに権限を要求する方法については、 [ 必要な権限を追加 ] セクションを参照してください。

自動化がクリアされると、すべての設定が完了します。 iOS デバイスで LocationEngine.setBackgroundLocationAllowed() は、メソッドを使用してバックグラウンドで位置情報の更新を有効または無効にできます。 また、 iOS デバイスでは、メソッドを使用 LocationEngine.setBackgroundLocationIndicatorVisible()して、アプリケーションのバックグラウンド位置情報インジケータの表示範囲を設定できます。

iOS デバイスの最終確認では、デバイスが停止しているときに、 LocationEngine.setPauseLocationUpdatesAutomatically() メソッドに渡された false 位置情報の更新が一時停止しないようにします。

setBackgroundLocationAllowed()setBackgroundLocationIndicatorVisible()は、アプリケーションでバックグラウンド位置情報フィーチャーが有効になっていない場合には、LocationEngineStatus.notAllowed が戻ります。 それ以外の場合は 、LocationEngineStatus.ok が返されます。

Android プラットフォームでは setBackgroundLocationAllowed()setBackgroundLocationIndicatorVisible() および setPauseLocationUpdatesAutomatically()LocationEngineStatus.notSupported 返されます。

AppLifecycleState また、バックグラウンド更新が有効になっている場合は、を聴くことをお勧めします。

Android デバイスで位置情報オプションを指定します

Android デバイスをターゲットにしている場合に、場所の生成時に考慮するオプションをより細かく制御するには、 LocationOptions オブジェクトを作成し、好みに合わせて設定してから、 startWithLocationOptions(locationOptions) メソッドを呼び出してエンジンを開始します。

// ...

// Create a new LocationOptions object. By default all options are enabled.
LocationOptions locationOptions = LocationOptions();

// Use WiFi and satellite (GNSS) positioning only.
locationOptions.wifiPositioningOptions.enabled = true;
locationOptions.satellitePositioningOptions.enabled = true;
locationOptions.sensorOptions.enabled = false;
locationOptions.cellularPositioningOptions.enabled = false;

// Receive a location approximately every minute, but not more often than every 30 seconds.
locationOptions.notificationOptions.smallestIntervalMilliseconds = 30000;
locationOptions.notificationOptions.desiredIntervalMilliseconds = 60000;

_locationEngine.startWithLocationOptions(locationOptions);

// ...

iOS plaftorms では startWithLocationOptions() 、が返さ LocationEngineStatus.notSupportedれます。

次の表に、使用可能 LocationAccuracy なモードの概要、 LocationOptions および Android での内部変換方法、 CLLocationAccuracy および iOS でのモードへの内部変換方法を示します。

位置精度 位置情報オプション( Android ) CLLocationAccuracy ( iOS )
Best_Available cellularPositioningOptions.enabled=true
satellitePositioningOptions.enabled=true
wifiPositioningOptions.enabled=true
sensorOptions.enabled=true
notificationOptions.desired_interval_millisec =30000 (30s)
notificationOptions.small_interval_millisec=1000 (11)
kCLLocationAccuracyBest
NAVIGATION cellularPositioningOptions.enabled=false
satellitePositioningOptions.enabled=true
wifiPositioningOptions.enabled=true
sensorOptions.enabled=true
notificationOptions.desired_interval_millisec =1000 (1s)
notificationOptions.small_interval_millisec=1000 (11)
kCLLocationAccuracyBestForNavigation
sub_meter_navigation cellularPositioningOptions.enabled=false
satellitePositioningOptions.enabled=true
satellitePositioningOptions.hdEnabled=true
wifiPositioningOptions.enabled=true
sensorOptions.enabled=true
notificationOptions.desired_interval_millisec =1000 (1s)notificationOptions.small_interval_millisec=1000
(1s)
該当なし
TENS_OF_METERS cellularPositioningOptions.enabled=false
satellitePositioningOptions.enabled=false
wifiPositioningOptions.enabled=true
sensorOptions.enabled=true
notificationOptions.desired_interval_millisec =30000 (30s)
notificationOptions.small_interval_millisec=1000 (1s)
kCLLocationAccuracyNearestTenMeters
HUNDREDS_OF_METERS cellularPositioningOptions.enabled=true
satellitePositioningOptions.enabled=false
wifiPositioningOptions.enabled=true
sensorOptions.enabled=false
notificationOptions.desired_interval_millisec =30000 (30s)
notificationOptions.small_interval_millisec=1000 (11)
kCLLocationAccuracyHundredMeters
KILOMETERS cellularPositioningOptions.enabled=true
satellitePositioningOptions.enabled=false
wifiPositioningOptions.enabled=false
sensorOptions.enabled=false
notificationOptions.desired_interval_millisec =30000 (30s)
notificationOptions.small_interval_millisec=1000 (11)
kCLLocationAccuracyThreeKilometers

希望する間隔は LocationEngineによって保証されないため、場所が多かれ少なかれ配信される可能性があります。一方、最小の間隔では、定義された値を超える頻度で場所が提供されないことが保証されます。

Android デバイスでのサブメーターナビゲーション

Android デバイスをターゲットにしている場合 、LocationEngine with LocationAccuracy.subMeterNavigationモードを開始すると HERE HD GNSS Positioning が有効になります。 HD GNSS(像度ローバルビゲーションステム)機能を使用すると、レーンアシスタンス、ターンバイターンガイダンス、拡張現実など、さまざまな用途に高解像度のポジショニングを行うことができます。 HD GNSS はクラウドベースのソリューションで、マスマーケットのデバイスが世界中でサブメートルの精度を達成できるようにします。

HD GNSS には、使用されている Android デバイスに特別な要件があります。 この機能が動作するには、 Android バージョンのデバイスが 12 ( API 31 )以上である必要があります。 具体的には、デバイスが以下をサポートしている必要があります。

  • 生の GNSS 測定値
  • GNSS キャリア位相測定( ADR )
  • デュアル周波数 GNSS 受信機( L5 )

詳細については、Android のドキュメントも参照してください。

使用しているデバイスで上記の条件が満たされていることを確認する責任はユーザーにあります。 そうでない場合は、目的の精度レベルに達していない可能性があります。

上記の条件は、古いバージョンの一部の Android デバイスでも保持されます。 LocationAccuracy.SUB_METER_NAVIGATION これらのバージョンの一部ではモードを正常に使用できますが、この操作は開発およびテストの目的でのみ行う必要があります。

従来の GNSS ソリューション(左)と HERE HD GNSS ソリューション(右)のグラウンドトラック精度の比較例。

この機能はデフォルトでは使用できませんが、個別にアクティブ化する必要があります。 HERE HD GNSS 補正データにアクセスするには、資格情報 が必要です。 詳細については、HEREにお問い合わせください。

LocationAccuracy.SUB_METER_NAVIGATION モードを使用しても、どのような場合にも確実に使用されるわけではありませんが、他のポジショニングソースおよびテクノロジーにフォールバックする可能性があります。 この理由としては、デバイスに必要な機能がない、 GNSS 測定の品質が低い都市部と見なされる可能性のある環境、または資格情報 がこの機能で有効になっていない場合などが挙げられます。

位置情報から正確性情報にアクセスできます

Locationオブジェクト内に存在する horizontalAccuracyInMetersフィールドは、「不確実性の半径」とも呼ばれ、68% の確率で真の地理座標が存在する可能性が高いエリアの推定値を提供します。これは、現在の位置の周囲にハローインジケータを描画するために使用されます。 下の図は、内側の緑色の円location.coordinatesに 、周囲の円を半径の精度の円horizontalAccuracyInMetersとして示し ています。 正確な地理座標は、精度円の内側(68%)または外側(32%)にあります。

図: 水平方向の不確実性と垂直方向の不確実性の半径。

同様に、高度の場合、 verticalAccuracyInMeters 値が10メートルの場合、実際の高度は 、 68%の確率で、高度-10mから高度+10mの範囲内にあると予想されます。 bearingAccuracyInDegrees およびspeedAccuracyInMetersPerSecondなどの他の精度値も同じ規則に従います。不確実性が小さいほど精度が向上します。

Android デバイスで coordinates.altitude は、 WGS 84 参照楕円体に関連して値が指定されます。 iOS デバイスで coordinates.altitude は、その値は平均海面レベルを基準にして代わりに指定されます。

68% を超える確率で達成 (CEP68)

68% の確率 (CEP68) では不十分な場合、 99% の精度を達成できますか ? はい、次のとおりです。 与えられた円形誤差確率 (CEP) は自由度が 2 つのカイ (χ)2乗分布に続くため、次の式に基づいて望ましい確率を簡単に計算できます。

確率 不確実性の半径
50% CEP50 = 0.78 x CEP68
60% CEP60 = 0.90 x CEP68
70% CEP70 = 1.03 x CEP68
80% CEP80 = 1.19 x CEP68
90% CEP90 = 1.42 x CEP68
95% CEP95 = 1.62 x CEP68
99% CEP99 = 2.01 x CEP68

上の表を使用して、マップ上のハローインジケータのさまざまな確率レベルを表示できます。 たとえば、水平方向の精度が 20 メートルの場合、半径のほぼ 2 倍の確率で 99 %を達成できます。 精度値は常に CEP68 として指定されます。つまり、次のことを意味します。

CEP99 = 2.01 x CEP68 = 2.01 x 20m = 40.2m

発見された場所の周囲に 40.2 メートルの半径を描画できるようになり ました。確率は 99% で、実際の場所はその円の内側にあります。 一方、半径 0 メートルの確率は 0% です。

HERE SDK の位置情報機能を使用するには、前述のように、アプリケーションで HERE SDK の同意ダイアログを表示する必要があります。 ユーザーは、現在の承諾の決定を参照し、以前の承諾の決定を取り消すことができる必要があります。そうしないと、 HERE SDK の位置情報機能を使用できなくなり、代わりにプラットフォームの位置情報 API を参照する必要があります。

この要件は、現在 iOS にデータ収集がないため、 Android アプリケーションにのみ適用されます。 これは今後変更される可能性があります。

チュートリアル : 現在地を地図に表示

LocationIndicatorは 、マップ上のデバイスの現在位置を表すために使用されます。 インジケータが現在の位置の値で更新される前に、デフォルト Location が設定されます。デフォルトは、最後に確認された場所、または最初の位置更新が到着する前にユーザが表示する必要がある場所です。 デフォルトでは、水平精度は半径horizontalAccuracyInMetersMapCircle で表示されます。

//Default start-up location.
static final GeoCoordinates _defaultGeoCoordinates = GeoCoordinates(52.530932, 13.384915);

// LocationIndicator object to represent device's current location.
LocationIndicator _locationIndicator;

// ...

void _addMyLocationToMap(Location myLocation) {
  if (_locationIndicator != null) {
    return;
  }
  // Set-up location indicator.
  _locationIndicator = LocationIndicator();
  // Enable a halo to indicate the horizontal accuracy.
  _locationIndicator!.isAccuracyVisualized = true;
  _locationIndicator!.locationIndicatorStyle = LocationIndicatorIndicatorStyle.pedestrian;
  _locationIndicator!.updateLocation(myLocation);
  _locationIndicator!.enable(_hereMapController!);

  // Point camera at given location.
  MapMeasure mapMeasureZoom = MapMeasure(MapMeasureKind.distance, _cameraDistanceInMeters);
  _hereMapController!.camera.lookAtPointWithMeasure(
    myLocation.coordinates,
    mapMeasureZoom,
  );

  // Update state's location.
  setState(() {
    _location = myLocation;
  });
}

// ...

    Location? location = _locationEngine.lastKnownLocation;

    if (location == null) {
        // No last known location, use default instead.
        location = Location.withCoordinates(_defaultGeoCoordinates);
        location.time = DateTime.now();
    }

    _addMyLocationToMap(location);

// ...

void _updateMyLocationOnMap(Location myLocation) {
    if (_locationIndicator == null) {
      return;
    }

    // Update location indicator's location.
    _locationIndicator?.updateLocation(myLocation);

    // Point camera at given location.
    _hereMapController?.camera.lookAtPoint(myLocation.coordinates);

    // Update state's location.
    setState(() {
        _location = myLocation;
    });
}

スクリーンショット: マップ上の現在の位置を示す位置情報インジケータ。

上記の実装に示されているように、updateLocation()を呼び出して、Locationオブジェクトを位置情報インジケータに渡すことができます。 この例では、ユーザーの現在の位置を追跡することを目的としています。そのため、マップビューポートの中心位置も更新されます。

」に一致する結果は 件です

    」に一致する結果はありません