Xamarin.Formsマップの初期化と構成
Map
コントロールは、各プラットフォームでネイティブ マップ コントロールを使用します。 これにより、すばやく使い慣れたマップ エクスペリエンスをユーザーに提供しますが、各プラットフォーム API の要件に準拠するために一部の構成手順が必要になります。
マップの初期化
Map
コントロールは、Xamarin.Forms.Maps NuGet パッケージにより提供されます。これは、ソリューション内のすべてのプロジェクトに追加する必要があります。
Xamarin.Forms.Maps NuGet パッケージをインストールしてから、各プラットフォーム プロジェクトで初期化する必要があります。
iOS では、これは Xamarin.Forms.Forms.Init
メソッドの "後" に Xamarin.FormsMaps.Init
メソッドを呼び出して AppDelegate.cs 内で行う必要があります。
Xamarin.FormsMaps.Init();
Android では、これは Xamarin.Forms.Forms.Init
メソッドの "後" に Xamarin.FormsMaps.Init
メソッドを呼び出して、MainActivity.cs 内で行う必要があります。
Xamarin.FormsMaps.Init(this, savedInstanceState);
ユニバーサル Windows プラットフォーム (UWP) では、MainPage
コンストラクターから Xamarin.FormsMaps.Init
メソッドを呼び出すと、MainPage.xaml.cs でこれが発生します。
Xamarin.FormsMaps.Init("INSERT_AUTHENTICATION_TOKEN_HERE");
UWP に必要な認証トークンの詳細については、「ユニバーサル Windows プラットフォーム」を参照してください。
NuGet パッケージが追加され、各アプリケーション内で初期化メソッドが呼び出されたら、Xamarin.Forms.Maps
API を共有コード プロジェクトで使用できます。
プラットフォームの構成
マップが表示される前に、Android とユニバーサル Windows プラットフォーム (UWP) では追加の構成が必要です。 さらに、iOS、Android、UWP ユーザーの場所にアクセスするには、場所のアクセス許可がアプリケーションに付与されている必要があります。
iOS
iOS でのマップの表示と操作には、追加の構成は必要ありません。 ただし、位置情報サービスにアクセスするには、Info.plist で次のキーを設定する必要があります。
- iOS 11 以降
NSLocationWhenInUseUsageDescription
– アプリケーションが使用中の場合に位置情報サービスを使用する場合NSLocationAlwaysAndWhenInUseUsageDescription
– 位置情報サービスを常に使用する場合
- iOS 10 以前
NSLocationWhenInUseUsageDescription
– アプリケーションが使用中の場合に位置情報サービスを使用する場合NSLocationAlwaysUsageDescription
– 位置情報サービスを常に使用する場合
iOS 11 以前をサポートするには、NSLocationWhenInUseUsageDescription
、NSLocationAlwaysAndWhenInUseUsageDescription
、NSLocationAlwaysUsageDescription
の 3 つのキーをすべて含めます。
Info.plist のこれらのキーの XML 表現を次に示します。 アプリケーションで位置情報がどのように使用されているかを反映するように string
値を更新する必要があります。
<key>NSLocationAlwaysUsageDescription</key>
<string>Can we use your location at all times?</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Can we use your location when your application is being used?</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Can we use your location at all times?</string>
Info.plist エントリは、Info.plist ファイルの編集中にソース ビューに追加することもできます。
その後、アプリケーションがユーザーの場所へのアクセスを試み、アクセスを要求すると、プロンプトが表示されます。
Android
Android でマップを表示および操作するための構成プロセスは次のとおりです。
- Google マップ API キーを取得し、マニフェストに追加します。
- マニフェストで Google Play サービスのバージョン番号を指定します。
- マニフェストで Apache HTTP レガシ ライブラリの要件を指定します。
- [オプション] マニフェストで WRITE_EXTERNAL_STORAGE アクセス許可を指定します。
- [オプション] マニフェストで場所のアクセス許可を指定します。
- [省略可能]
MainActivity
クラスのランタイムの場所のアクセス許可を要求します。
正しく構成されたマニフェスト ファイルの例については、サンプル アプリケーションの AndroidManifest.xml を参照してください。
Google Maps API キーを取得する
Android で Google マップ API を使用するには、API キーを生成する必要があります。 これを行うには、「Google マップ API キーを取得する」の手順に従います。
API キーを取得したら、Properties/AndroidManifest.xml ファイルの <application>
要素内に追加する必要があります。
<application ...>
<meta-data android:name="com.google.android.geo.API_KEY" android:value="PASTE-YOUR-API-KEY-HERE" />
</application>
これにより、API キーがマニフェストに埋め込まれます。 有効な API キーがないと、Map
コントロールに空白のグリッドが表示されます。
Note
com.google.android.geo.API_KEY
は、API キーに推奨されるメタデータ名です。 下位互換性のために、com.google.android.maps.v2.API_KEY
メタデータ名を使用できますが、Android マップ API v2 への認証のみが許可されます。
APK が Google マップにアクセスするには、APK の署名に使用するすべてのキーストア (デバッグおよびリリース) の SHA-1 フィンガープリントとパッケージ名を含める必要があります。 たとえば、1 台のコンピューターをデバッグに使用し、別のコンピューターをリリース APK の生成に使用する場合、最初のコンピューターのデバッグ キーストアの SHA-1 証明書フィンガープリントと、2 番目のコンピューターのリリース キーストアの SHA-1 証明書フィンガープリントを含める必要があります。 また、アプリのパッケージ名が変更された場合は、キー資格情報を編集することを忘れないでください。 「Google マップ API キーを取得する」を参照してください。
Google Play サービスのバージョン番号を指定する
AndroidManifest.xml の <application>
要素内に次の宣言を追加します。
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
これにより、アプリケーションがコンパイルされた Google Play サービスのバージョンがマニフェストに埋め込まれます。
Apache HTTP レガシ ライブラリの要件を指定する
Xamarin.Forms アプリケーションが API 28 以上を対象とする場合は、AndroidManifest.xml の <application>
要素内に次の宣言を追加する必要があります。
<uses-library android:name="org.apache.http.legacy" android:required="false" />
これにより、Android 9 の bootclasspath
から削除された Apache Http クライアント ライブラリを使用するようにアプリケーションに指示されます。
WRITE_EXTERNAL_STORAGE 権限を指定する
アプリケーションが API 22 以下を対象とする場合は、<manifest>
要素の子としてマニフェストに WRITE_EXTERNAL_STORAGE
アクセス許可を追加することが必要な場合があります。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
これは、アプリケーションが API 23 以上を対象とする場合は必要ありません。
場所のアクセス許可を指定する
アプリケーションがユーザーの場所にアクセスする必要がある場合は、<manifest>
要素の子として、マニフェストに ACCESS_COARSE_LOCATION
または ACCESS_FINE_LOCATION
(またはその両方) を追加して、アクセス許可を要求する必要があります。
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.myapp">
...
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>
ACCESS_COARSE_LOCATION
アクセス許可により、API は WiFi またはモバイル データまたはその両方を使用して、デバイスの場所を決定できます。 ACCESS_FINE_LOCATION
アクセス許可により、API はグローバル位置情報システム (GPS)、WiFi、またはモバイル データを使用して、正確な場所を可能な限り特定できます。
または、マニフェスト エディターを使用して次のアクセス許可を追加すると、これらのアクセス許可を有効にすることができます。
AccessCoarseLocation
AccessFineLocation
これらは次のスクリーンショットに示されています。
ランタイムの場所のアクセス許可を要求する
アプリケーションが API 23 以降を対象とし、ユーザーの場所にアクセスする必要がある場合は、実行時に必要なアクセス許可があるかどうかを確認し、それがない場合は要求する必要があります。 これは次のようにして実装します。
MainActivity
クラスで、次のフィールドを追加します。const int RequestLocationId = 0; readonly string[] LocationPermissions = { Manifest.Permission.AccessCoarseLocation, Manifest.Permission.AccessFineLocation };
MainActivity
クラスで、次のOnStart
オーバーライドを追加します。protected override void OnStart() { base.OnStart(); if ((int)Build.VERSION.SdkInt >= 23) { if (CheckSelfPermission(Manifest.Permission.AccessFineLocation) != Permission.Granted) { RequestPermissions(LocationPermissions, RequestLocationId); } else { // Permissions already granted - display a message. } } }
アプリケーションが API 23 以上を対象としている限り、このコードは、
AccessFineLocation
アクセス許可の実行時アクセス許可チェックを実行します。 アクセス許可が付与されていない場合は、RequestPermissions
メソッドを呼び出すとアクセス許可要求が行われます。MainActivity
クラスで、次のOnRequestPermissionsResult
オーバーライドを追加します。public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults) { if (requestCode == RequestLocationId) { if ((grantResults.Length == 1) && (grantResults[0] == (int)Permission.Granted)) // Permissions granted - display a message. else // Permissions denied - display a message. } else { base.OnRequestPermissionsResult(requestCode, permissions, grantResults); } }
このオーバーライドは、アクセス許可要求の結果を処理します。
このコードの全体的な効果は、アプリケーションがユーザーの場所を要求するときに、アクセス許可を要求する次のダイアログが表示されることです。
ユニバーサル Windows プラットフォーム
UWP では、マップを表示してマップ サービスを使用する前に、アプリケーションを認証する必要があります。 アプリケーションを認証するには、マップ認証キーを指定する必要があります。 詳細については、「マップ認証キーの要求」を参照してください。 認証トークンは、Bing マップを使用してアプリケーションを認証するために、FormsMaps.Init("AUTHORIZATION_TOKEN")
メソッド呼び出しで指定する必要があります。
Note
UWP では、ジオコーディングなどのマップ サービスを使用するには、MapService.ServiceToken
プロパティを認証キーの値に設定する必要もあります。 これを行うには、次のコード行を使用します: Windows.Services.Maps.MapService.ServiceToken = "INSERT_AUTH_TOKEN_HERE";
。
さらに、アプリケーションがユーザーの場所にアクセスする必要がある場合は、パッケージ マニフェストで場所機能を有効にする必要があります。 これは次のようにして実装します。
ソリューション エクスプローラーで、package.appxmanifest をダブルクリックし、[機能] タブを選びます。
[機能] ボックスの一覧で、[位置情報] チェックボックスをオンにします。 これにより、
location
デバイス機能がパッケージ マニフェスト ファイルに追加されます。<Capabilities> <!-- DeviceCapability elements must follow Capability elements (if present) --> <DeviceCapability Name="location"/> </Capabilities>
リリース ビルド
UWP リリース ビルドでは、.NET ネイティブ コンパイルを使用して、アプリケーションをネイティブ コードに直接コンパイルします。 ただし、その結果、UWP 上の Map
コントロールのレンダラーが実行可能ファイルからリンクされる可能性があります。 これは、App.xaml.cs で Forms.Init
メソッドの UWP 固有のオーバーロードを使用して修正できます。
var assembliesToInclude = new [] { typeof(Xamarin.Forms.Maps.UWP.MapRenderer).GetTypeInfo().Assembly };
Xamarin.Forms.Forms.Init(e, assembliesToInclude);
このコードは、Xamarin.Forms.Maps.UWP.MapRenderer
クラスが存在するアセンブリを Forms.Init
メソッドに渡します。 これにより、.NET ネイティブ コンパイル プロセスで、アセンブリが実行可能ファイルからリンクされないようにします。
重要
これを行わないと、リリース ビルドの実行時に Map
コントロールが表示されなくなります。