 
Xamarin逆引きTips
Xamarin.Formsで地図を表示するには?(Xamarin.Forms.Maps使用)
Android/iOSアプリで各プラットフォーム標準の地図を表示するには、Xamarin.Forms.Mapsコントロールを使う。その基本的な使い方を説明する。
 スマートフォンの各プラットフォームでは、標準の地図機能が提供されており、Androidでは「Google Maps Android API v2」、iOSでは「MapKit」がそれである。Xamarin.Formsでは、この各プラットフォームの標準マップAPIを共通的に扱えるようにXamarin.Forms.Mapsコントロールが提供されている。
 今回は、このXamarin.Forms.Mapsコントロールの利用方法について解説する*1。
- *1 なお本Tipsは、Windows上でVisual Studio 2013を使用してXamarin.Forms開発をすることを前提としている(※編集部注: Mac上のXamarin Studioでも同様の手順で、本稿の内容が実現できることは確認している)。使用しているXamarin.Formsのバージョンは、プロジェクト作成時に利用されている「1.3.1.6296」である。
1. シナリオ
 Xamarin.Forms.Mapsコントロールを使用して地図を表示するためには、最初に、プラットフォーム側での初期化処理が必要である。そして、プラットフォームごとにパーミッションなどのいくつかの設定も必要になる。
今回は、これらの作業について、順を追って解説する。
2. Xamarin.Formsプロジェクトを作成する
メニューバーの[ファイル]-[新規作成]-[プロジェクト]から表示したダイアログで、[テンプレート]-[Visual C#]-[Mobile Apps]-[Blank App (Xamarin.Forms Portable)]を選択し、名前を「MapsSample」として[OK]ボタンを押す。
3. Xamarin.Forms.Mapsパッケージの追加
 Xamarin.Forms.Mapsを使用するためには、NuGetパッケージのインストールが必要だ。
Visual StudioでのNuGetパッケージのインストールは、メニューバーの[ツール]-[NuGet パッケージマネージャー]-[ソリューションの NuGet パッケージの管理]を選択して表示された[NuGet パッケージの管理]ダイアログから行う。検索欄にXamarin.Forms.Mapsと入力すると、目的のパッケージを簡単に見つけることができる。また、依存関係を見ると分かるように、Xamarin.Formsの最新stableである1.3.5.6337や、Xamarin.GooglePlayServicesも同時にインストールされることになる。
図2の[インストール]ボタンを押した後、続いて表示される[プロジェクトの選択]ダイアログでは、全てのプロジェクトにチェックを入れて[OK]ボタンを押す(図3)。

 実は、ここまでの要領でXamarin.Forms.Mapsパッケージのインストールは完了するはずなのだが、2015年3月9日現在、一部のプロジェクトでエラーが発生してインストールが失敗する(次の画面はその例)。

この問題を回避するためには、先のインストールを行う前に、以下の作業を順に行う必要がある。
- ソリューションエクスプローラーでAndroidプロジェクトを右クリックして表示されるメニューから[プロパティ](=プロジェクトのプロパティ)を選択し、図5のように[Application]の[Compile using Android version]をUse Latest Platform (API Level 21 (Xamarin.Android v5.0 Support))からAPI Level 21 (Xamarin.Android v5.0 Support)に変更する(※この変更の意味は、後述のコラムを参照)
- Visual Studioを再起動する
- もう一度、図2の[NuGet パッケージの管理]ダイアログを表示し、左側のツリーから[インストール済みのパッケージ]-[すべて]を選択し、中央に表示される「Xamarin.Forms.Maps」の[管理]ボタンを押す。これにより図3のダイロアログが表示されるので、チェックボックスが外れている項目をチェックし直して[OK]ボタンを押すと、先ほどエラーが発生したNuGetパッケージがインストールされる(※これでうまくインストールされない場合は、全てのチェックを外してXamarin.Forms.Mapsをアンインストールして、もう一度インストールし直すとよい)
パッケージのインストールが完了すると、各プロジェクトの参照設定に、次のようなライブラリが追加されているのを確認できる。

 
 
【コラム】Xamarin.Forms.Mapsのインストールが失敗する
 2015年3月9日現在、エラーが発生する原因は、依存関係から、Androidプロジェクトで必要となるXamarin.Android.Support.v7.AppCompatアセンブリのVersion 21以降が、MonoAndroid,Version=v2.2の条件下でインストールできないためである。Visual Studioでは、[Compile using Android version]がUse Latest Platform (API Level 21 (Xamarin.Android v5.0 Support))になっていると、MonoAndroid,Version=v2.2となってしまうのである。
 そして、これを回避する方法が、先に紹介したAPI Level 21(Xamarin.Android v5.0 Support)への変更である。
なお、UI上でこの変更を実施すると、プロジェクトを再度読み直すまで、TargetFrameworkVersion(=.csprojファイルで指定されている.NETのターゲットバージョン)の値が正常に処理されない場合がある。手順の中でVisual Studioを再起動したのは、このためである。
4. Xamarin.Forms.Mapsの初期化
 Xamarin.Forms.Mapsを使用するためには、プラットフォームごとに、初期化コードを記述する必要がある。
初期化コードは、iOSプロジェクトでは、AppDelegate.csファイルに追加する。
| ……省略…… namespace MapsSample.iOS {   [Register("AppDelegate")]   public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate {     public override bool FinishedLaunching(UIApplication app, NSDictionary options) {       global::Xamarin.Forms.Forms.Init();       Xamarin.FormsMaps.Init(); // Xamarin.Forms.Mapsの初期化コード       LoadApplication(new App());       return base.FinishedLaunching(app, options);     }   } } | 
また、Androidプロジェクトでは、MainActivity.csファイルに追加する。
| ……省略…… namespace MapsSample.Droid {   [Activity(Label = "MapsSample", Icon = "@drawable/icon", MainLauncher = true,     ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]   public class MainActivity : FormsApplicationActivity {     protected override void OnCreate(Bundle bundle) {       base.OnCreate(bundle);       Forms.Init(this, bundle);       Xamarin.FormsMaps.Init(this, bundle); // Xamarin.Forms.Mapsの初期化コード       LoadApplication(new App());     }   } } | 
5. プラットフォームごとの設定(Android)
 Xamarin.Forms.Mapsを使用するためには、プラットフォームごとに、もう少し作業が必要である。
Androidでは、次の3つがそれである。
(1)パーミッションの追加
 インターネットに接続して地図データをダウンロードするため、INTERNET、ACCESS_FINE_LOCATIONおよびACCESS_NETWORK_STATEのパーミッションが必要だ。
これらを設定するには、プロジェクトのプロパティで[Android Manifest]を開いて、上記の3つのパーミッションをチェックする。
(2)ヒープの最大サイズの設定
ヒープの最大サイズの指定が無い場合、下記のようにエラーとなりコンパイルが失敗する。
| ……省略…… 1>C:\Users\Seishin\AppData\Local\Xamarin\Android.Support.v7.AppCompat\21.0.3\emb……省略…… 1>COMPILETODALVIK : UNEXPECTED TOP-LEVEL error :  ========== ビルド: 0 正常終了、1 失敗、1 更新不要、0 スキップ ========== ========== 配置: 0 正常終了、0 失敗、0 スキップ ========== | 
 プロジェクトのプロパティで[Android Options]を選択し、[Advanced]タブで[Java Max Heap Size]欄に1Gと設定することで(図7)、この問題を回避できる。
(3)アプリケーションキーの設定
Androidでは、「Google Maps API v2」を使用するため、同サービスのAPIキーが必要になる。APIキーの取得方法については、「Tips:Xamarin.Androidで地図を表示するには?(Google Maps使用)」に解説されているので、そちらを参照していただきたい。
取得したAPIキーを追加するためには、([Properties]の中にある)AndroidManifest.xmlファイルは以下のように修正する。
|  1  2  3  4  5  6  7 1  9 10 11 | <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example" android:installLocation="auto">   <uses-sdk android:minSdkVersion="15" />   <application>     <meta-data android:name="com.google.android.maps.v2.API_KEY"        android:value="<取得したAPI Keyをここに書く>" />    </application> </manifest> | 
 <manifest>タグの中の<application>タグに<meta-data>タグを追加し、そのandroid:name属性にはcom.google.android.maps.v2.API_KEYを、android:value属性には取得したAPIキーを設定する(1)。
6. プラットフォームごとの設定(iOS)
iOS 7では、現在位置を取得するアプリの場合、起動時に許可を求めるためのメッセージが自動的に表示された。しかしiOS 8では、このような許可を求めるためには、明示的に設定が必要である。
iOSで「位置情報測位の許可」のメッセージを表示するには、Info.plistファイルを(GUIのPListエディターでは設定できないのでテキストエディターで開いて)以下のように修正する。
|  1  2  3  4  5 1  7 2  9 10 11 | <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict>     ……省略……   <key>NSLocationAlwaysUsageDescription</key>   <string>Can we use your location</string>   <key>NSLocationWhenInUseUsageDescription</key>   <string>We are using your location</string> </dict> </plist> | 
 NSLocationAlwaysUsageDescriptionキーは「常に許可」時のメッセージであり(1)、NSLocationWhenInUseUsageDescriptionキーは「このAppの使用中のみ許可」時のメッセージである(2)。これらのキーを追加すると、アプリ起動時に次のような確認ダイアログが表示される。

7. 地図を表示する(Android/iOS共通のコード)
初期化コードの追加と、プラットフォームごとの設定が完了すると、いよいよ地図の表示が可能である。
地図を表示するためには、App.csファイルを以下のように修正する。
| ……省略…… using Xamarin.Forms.Maps; namespace MapsSample {   public class App : Application {     public App() {       MainPage = new MyPage();     }   ……省略……   }   public class MyPage : ContentPage {     public MyPage() {       var map = new Map(               // <-1         MapSpan.FromCenterAndRadius(   // <-2           new Position(35.71, 139.81), // <-3           Distance.FromMiles(0.2))) {  // <-4             IsShowingUser = true,             VerticalOptions = LayoutOptions.FillAndExpand           };       Content = new StackLayout {         Children = { map }       };     }   } } | 
 1では、Mapクラスのインスタンスを生成しているが、パラメーターに指定されているのは、MapSpanクラスのインスタンスである(2)。
 MapSpanオブジェクトは、FromCenterAndRadiusメソッドを使用して生成されており、パラメーターに中心位置の座標(3)*2と縮尺(4)が指定されている。
 その他、MapオブジェクトのIsShowingUserプロパティ(=現在位置を表示するかどうか)などの設定も行っている。
- *2 設定されている数値は、東京スカイツリーの座標である。
このコードを実行すると、次のような画面になる。
 
 
【コラム】Androidのエミュレーターでは実行できない
通常使用しているAndroidエミュレーターでは、Google Play Servicesが含まれていないため、地図を表示することはできない。
Xamarinから提供されているXamarin Android Playerで、同サービスをインストールする手順が、下記のページで紹介されている。
8. まとめ
今回は、Xamarin.Forms.Mapsで地図を表示するまでの一連の作業を解説した。
Xamarin.Forms.Mapsでは、この他にも、マーカーを表示したり、縮尺を操作したりするなどの機能が提供されているが、それらについては次回解説する。
※以下では、本稿の前後を合わせて5回分(第37回~第41回)のみ表示しています。
 連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
 
37. MvvmCrossのプロジェクトをセットアップするには?
クロスプラットフォーム開発を支援するXamarin用ライブラリの「MvvmCross」を使ってiOS/Androidアプリ開発を行うためのプロジェクトの作成方法を説明する。
 
38. Xamarin.FormsでListViewコントロールを使用するには?
データの一覧を表示できる「リストビュー」はXamarin.Formsでも提供されている。その基本的な使用方法を解説。また、セルの高さ指定/プログラムによるスクロール/画像表示などの方法も説明する。
 
39. 【現在、表示中】≫ Xamarin.Formsで地図を表示するには?(Xamarin.Forms.Maps使用)
Android/iOSアプリで各プラットフォーム標準の地図を表示するには、Xamarin.Forms.Mapsコントロールを使う。その基本的な使い方を説明する。
 
40. Xamarin.Formsで地図の現在位置やピンの表示、縮尺や地図タイプの変更を行うには?(Xamarin.Forms.Maps使用)
Xamarin.Forms.Mapsコントロールで利用可能な機能として、「現在位置」や「衛星写真」「ピン立て」「スライダーコントロールによる地図の拡大・縮小」などを解説する。





 
  
  
  
  
 
