読者です 読者をやめる 読者になる 読者になる

Xamarin 日本語情報

Xamarin(ザマリン) の代理店だったエクセルソフト田淵のブログです。主に Xamarin に関するエントリーをアップしていきます。(なるべく正しい有益な情報を掲載していきたいと考えていますが、このブログのエントリーは所属組織の公式見解ではありませんのでご注意ください)

Xamarin.Forms の MapView について

Xamarin Xamarin.Forms

Xamarin.Forms でマップアプリのサンプルを作りました。 結構嵌ってしまいましたので、備忘録として残します。

iOS/Android 両方

  • MapView を実装するには NuGet で各プロジェクトに Xamarin.Forms.Maps を追加します。
    スクリーンショット 2014-06-10 12.04.40.png
  • Xamarin.Forms.Maps の API リファレンス には、AppDelegate.csMainActivity.cs でそれぞれ FormsMaps.Init してね。とありますが、そもそも Forms.Maps.Init じゃないんかい!とツッコミを入れつつ、かつ、using Xamarin.Forms;using Xamarin.Forms.Maps; を しても Xamarin.FormsMaps.Init と呼び出さなければいけないという不思議な現象を軽く乗り越えます。

マップの実装のサンプルです。非常に簡単ですね。 API リファレンスForm Gallery サンプルアプリ などを参考にしてください。

public static Page GetMainPage ()
{   
    Map map = new Map ();
    Position position = new Position (35.681382, 139.766084);
    map.MoveToRegion (new MapSpan (position,0.01,0.01));
    map.Pins.Add (new Pin 
        {
            Label = "東京駅はここです",
            Position = position,
        });
    return new ContentPage { 
        Content = new StackLayout {
            Children = {
                map,
            },
        },
    };
}
public static Page GetMainPage ()
{   
    return new ContentPage { 
        Content = new Map (MapSpan.FromCenterAndRadius (new Position (35.681382, 139.766084), Distance.FromKilometers (0.3)))
    };
}

iOS アプリ

これ以上やることはありません。ビルドすればこんな感じです。 スクリーンショット 2014-06-10 20.36.25.png

Android アプリ

少し大変です。

  • API Key が必要です。Google Developer ConsoleAPI Key を生成します。
  • ちゃんと Xamarin で Android のマップアプリを開発した方なら一度は読んでいるであろう API Key の作り方 を読んで、 正しい debug.keystore から API Key を作りますw
  • API Key は Developer Console さんの指示通り keytool -list -v -keystore debug.keystore -storepass android で表示される SHA1 のハッシュを元に作成します。
  • なお、Xamarin でデバッグする時に使われる debug.keystore は標準では Windows - C:\Users\[USERNAME]\AppData\Local\Xamarin\Mono for Android\debug.keystoreOSX - /Users/[USERNAME]/.local/share/Xamarin/Mono for Android/debug.keystore にあります。eclipse とは違うので半日ほどハマらないように注意してくださいw
  • 生成した API_KEY を利用して一般的な Android アプリと同じように Permission などを設定します。なんか最後の ACCESS_WIFI_STATE も付けとくと Wifi 経由のデバッグの時に救われたりするようです。
<application android:label="XamarinForms_MapView01_Android">
    <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="xxxxxxxxxxAPI_KEYxxxxxxxxxx" />
</application>

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<permission android:name="com.example.XamarinForms_MapView01_Android.permission.MAPS_RECEIVE" android:protectionLevel="signature" />
<uses-permission android:name="com.example.XamarinForms_MapView01_Android.permission.MAPS_RECEIVE" />

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

後は小ネタですが、

  • Xamarin.Forms のソリューションを作成すると、標準で アプリ名.AndroidAndroid プロジェクトが作成されます。パッケージ名も同じく アプリ名.Android になっています。これ、良くないみたいなので、アプリ名_Android とかにした方が良いかもです。 ここに 書いてありました。
  • Mac の Xamarin Studio で開発している場合は、Xamarin.Forms アプリをテンプレートから作成すると、Target Framework が 4.0.3 になっていると思います。この状態で Xamarin.Forms.Maps を追加すると、
    スクリーンショット 2014-06-10 20.51.46.png
    とライブラリがいくつか追加されます。この中のXamarin.Android.Support.v7.MediaRouter が 4.2 以上の Target Framework でないとビルド時に大量の error: No resource identifier found for attribute 'paddingStart' in package 'android' のようなエラーを吐きますので、Target Framework を latest に、Minimum を 4.0.3 などにしておくと良さそうです。Visual Studio で作成した場合は、Latest と Minimum がちゃんと設定されていました。

  • WindowsVisual Studio でビルドした時は出ませんでしたが、Mac の Xamarin Studio でビルドした時に以下のエラーが出ました。Heapsize が足りないそうです。マシンのメモリ状況にもよるかもしれません。

 /Library/Frameworks/Mono.framework/External/xbuild/Xamarin/Android/Xamarin.Android.Common.targets: Error: Tool exited with code: 3. Output: 
UNEXPECTED TOP-LEVEL ERROR:
java.lang.OutOfMemoryError: Java heap space
    at java.util.ArrayList.<init>(ArrayList.java:112)
    at java.util.ArrayList.<init>(ArrayList.java:119)
    at com.android.dx.ssa.SsaBasicBlock.<init>(SsaBasicBlock.java:124)
    at com.android.dx.ssa.SsaBasicBlock.newFromRop(SsaBasicBlock.java:147)
    at com.android.dx.ssa.SsaMethod.convertRopToSsaBlocks(SsaMethod.java:173)
    at com.android.dx.ssa.SsaMethod.newFromRopMethod(SsaMethod.java:103)
    at com.android.dx.ssa.SsaConverter.convertToSsaMethod(SsaConverter.java:44)
    at com.android.dx.ssa.Optimizer.optimize(Optimizer.java:98)
    at com.android.dx.ssa.Optimizer.optimize(Optimizer.java:72)
    at com.android.dx.dex.cf.CfTranslator.processMethods(CfTranslator.java:303)
    at com.android.dx.dex.cf.CfTranslator.translate0(CfTranslator.java:139)
    at com.android.dx.dex.cf.CfTranslator.translate(CfTranslator.java:94)
    at com.android.dx.command.dexer.Main.processClass(Main.java:682)
    at com.android.dx.command.dexer.Main.processFileBytes(Main.java:634)
    at com.android.dx.command.dexer.Main.access$600(Main.java:78)
    at com.android.dx.command.dexer.Main$1.processFileBytes(Main.java:572)
    at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:284)
    at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)
    at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
    at com.android.dx.command.dexer.Main.processOne(Main.java:596)
    at com.android.dx.command.dexer.Main.processAllFiles(Main.java:498)
    at com.android.dx.command.dexer.Main.runMonoDex(Main.java:264)
    at com.android.dx.command.dexer.Main.run(Main.java:230)
    at com.android.dx.command.dexer.Main.main(Main.java:199)
    at com.android.dx.command.Main.main(Main.java:103)
 (XamarinForms_MapView01.Android)

適当に スクリーンショット 2014-06-10 16.44.15.png とか設定します。(ビルドのオプションだと思うので、大きくても問題ないですよね?)

多分これくらいで大体のエラーは回避できるのではないかと思います。Android アプリはこんな感じです。
スクリーンショット 2014-06-10 21.17.21.png

以上です。