はじめに
こんにちは、東京アプリケーションシステム 第3ソリューション部のH.Tです。
技術者ブログということで、備忘録も兼ねて最近学んだことを共有します。
昨年の秋ぐらいから、スマホアプリの技術検証という形でXamarinに入門しました。
AndroidとiOSでUIをある程度共通化できるため、使われている方も多いと思います。
私も最初はXamarin.Android?Xamarin.iOS?Formsって何?状態でしたが、
技術検証という名目で作りたいものを作ったり、xamarin案件に関わることができたりして、徐々に頭に定着してきました。
ということで、今回はタイトルの通りXamarin.FormsでGoogleMapのAPIを使ってマップを表示してみます。
開発環境
・Microsoft Visual Studio Community 2019 v16.8.4
・Xamarin.Forms v4.8.0.1451
・Xamarin.Forms.GoogleMaps v3.3.0
・Xamarin.Essentials v1.5.3.2
APIキーを取得する
まずGoogleCloudPlatformでプロジェクトを作成します。
プロジェクト名を適当につけて作成します。
できました。
次にライブラリから「Maps」等で検索して、
「Maps SDK for Android」を選択します。
「有効にする」をクリック。
左上の「Ξ」から「APIとサービス」→「認証情報」を選択します。
「認証情報の作成」を選択します。
APIキーが生成されました。
↑の「キーを制限」からMaps SDK for Android のみに制限をつけましょう。
これでAPIキーが用意できました。
Formsプロジェクトの作成
それでは次にプロジェクトを作っていきます。
「モバイル アプリ(Xamarin.Forms)」を選択して、「次へ」をクリック
プロジェクト名と保存先を設定して「作成」をクリック
プロジェクトのテンプレートを選択します。
今回は一番シンプルな「空白」で作成します。
空っぽのアプリができました。
パッケージのインストール
GoogleMapのパッケージをインストールします。
ソリューションを右クリックし「Nugetパッケージの管理」を選択します。
タブを「参照」に切り替えて、「googlemaps」で検索すると、「Xamarin.Forms.GoogleMaps」が出てくるのでインストールします。
Android.Manifestの設定
プラットフォーム固有の設定をします。
今回はAndroidのみなので、Android.Manifestのみ編集します。
内に先ほど取得したAPIキーを<application>設定します。
・<meta-data android:name=”com.google.android.geo.API_KEY” android:value=”ここにさっきのAPIキーをコピペ” />
また、API28以上を対象とする場合は↓も必要です。
・<uses-library android:name=”org.apache.http.legacy” android:required=”false” />
位置情報を渡す必要があるので、<manifest>内にパーミッションを追加します。
・<uses-permission android:name=”android.permission.ACCESS_COARSE_LOCATION” />
・<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION” />
・<uses-permission android:name=”android.permission.INTERNET” />
以下のようになればManifestの設定は完了です。
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.samplegmap"> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" /> <application android:label="SampleGMap.Android" android:theme="@style/MainTheme"> <meta-data android:name="com.google.android.geo.API_KEY" android:value="ここにAPIキー" /> <uses-library android:name="org.apache.http.legacy" android:required="false" /> </application> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.INTERNET" /> </manifest> |
画面設定
画面側を設定していきます。
MainPage.xamlの<ContentPage>に↓を追加します。
・xmlns:map=”clr-namespace:Xamarin.Forms.GoogleMaps;assembly=Xamarin.Forms.GoogleMaps”
いらないテンプレートを消して↓を追加します。
・<map:Map x:Name=”MyMap” HasZoomEnabled=”True” MapType=”Street” />
以下のようになればOKです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:map="clr-namespace:Xamarin.Forms.GoogleMaps;assembly=Xamarin.Forms.GoogleMaps" x:Class="SampleGMap.MainPage"> <StackLayout> <StackLayout VerticalOptions="FillAndExpand"> <map:Map x:Name="MyMap" HasZoomEnabled="True" MapType="Street" /> </StackLayout> </StackLayout> </ContentPage> |
MainActivity
プラットフォームの固有の設定も必要なため、MainActivityのOnCreateに↓を追加します。
・Xamarin.FormsGoogleMaps.Init(this, savedInstanceState);
以下のようになればOK
1 2 3 4 5 6 7 8 9 10 11 12 |
protected override void OnCreate(Bundle savedInstanceState) { TabLayoutResource = Resource.Layout.Tabbar; ToolbarResource = Resource.Layout.Toolbar; base.OnCreate(savedInstanceState); Xamarin.FormsGoogleMaps.Init(this, savedInstanceState); //これを追加 Xamarin.Essentials.Platform.Init(this, savedInstanceState); global::Xamarin.Forms.Forms.Init(this, savedInstanceState); LoadApplication(new App()); } |
コードビハインド
コードビハインドを変更していきます。
TASC本社のあるメディアシップの緯度経度を設定し、幅10km分表示するように設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); } protected async override void OnAppearing() { // メディアシップをフォーカス MyMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(37.91921751961976, 139.05843970159702), Distance.FromKilometers(10))); } } |
実行してみる
それでは実行してみます!
設定通り、メディアシップを中心としてマップが表示されました。
ただ少し遠い気がするのでもう少し近づいてみましょう。
Distance.FromKilometers(10)をDistance.FromKilometers(1)に変更して再度実行します。
表示幅が1kmに変更されました。
マップにピンを立てる
マップが表示できたので、次にメディアシップの場所にマップピンを立ててみます。
コードビハインドを以下のように変更します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); } protected async override void OnAppearing() { // メディアシップをフォーカス MyMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(37.91904824457278, 139.05848261694112), Distance.FromKilometers(1))); // ピンの設定 var pin = new Pin() { Type = PinType.Place, Label = "TASC本社", Address = "新潟県新潟市中央区万代3丁目1−1", Position = new Position(37.91904824457278, 139.05848261694112),//メディアシップ }; MyMap.Pins.Add(pin);// マップにピンを追加 } } |
実行してみましょう。
メディアシップにピンが立ちました。
ピンをタップするとLabelとAddress情報が表示されます。
他にもピンを傾けて表示したり、ドラッグで移動するように設定することもできます。
詳しくはMicrosoftDocsを参考にしてみてください。
GPSから位置情報を設定
最後に端末のGPSから位置情報を取得し、マップ上に表示します。
コードビハインドに緯度経度を取得するメソッドを追加します。
以下のように変更します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
public partial class MainPage : ContentPage { private double latitude; // 緯度 private double longitude; // 経度 public MainPage() { InitializeComponent(); } protected async override void OnAppearing() { // 現在位置取得 await GetLatLong(); // メディアシップをフォーカス MyMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(latitude, longitude), Distance.FromKilometers(1))); // ピンの設定 var pin = new Pin() { Type = PinType.Place, Label = "現在位置", Address = "", Position = new Position(latitude, longitude),//現在位置を設定 }; MyMap.Pins.Add(pin);// マップにピンを追加 } private async Task GetLatLong() { try { //座標取得 var request = new GeolocationRequest(GeolocationAccuracy.Default); var location = await Geolocation.GetLocationAsync(request); latitude = location.Latitude; // 緯度を取得 longitude = location.Longitude; // 経度を取得 } catch (Exception ex) { Console.WriteLine(ex); } } } |
GPSを利用するため、今度は実機デバッグで実行してみましょう。
このように現在位置が表示されます。
私が今上所の支社にいることがまる分かりですね。
他にも逆ジオコーディングを使うと緯度経度を住所に変換することもできます。
まとめ
Xamarin.FormsでMaps SDK for Androidを使ってマップを表示しました。
私と同じくXamarinのマップ機能の実装で困っている方の助けになれば幸いです。