はつねの日記

Kinect, Windows 10 UWP, Windows Azure, IoT, 電子工作

Xamarin.Androidで地図を使う

Google Maps Android API v2を利用できるようにする
Androidアプリ署名用キーストアからフィンガープリントを取得

コマンドプロンプトでkeytoolを起動しAndroidアプリ署名用キーストアからフィンガープリントを取得します。以下の説明では、デバッグ用のキーストアであるdebug.keystoreからフィンガープリントを取得する方法を説明しています。

アルファ版やベータ版を含めてストア登録して配布するためにはデバッグ用キーストアではなく、この時点で正式なAndroidアプリ署名用キーストアを指定します【作り方は次回)。

 

"C:\Program Files (x86)\Java\jdk1.6.0_39\bin\keytool.exe" ?list -v -keystore "C:\Users\hatsune\AppData\Local\Xamarin\Mono for Android\debug.keystore" -alias androiddebugkey -storepass android
-keypass android
別名: androiddebugkey
作成日: 2014/03/02
エントリタイプ: PrivateKeyEntry
証明連鎖の長さ: 1
証明書[1]:
所有者: CN=Android Debug, O=Android, C=US
発行者: CN=Android Debug, O=Android, C=US
シリアル番号: 5312ba0d
有効期間の開始日: Sun Mar 02 13:56:45 JST 2014 終了日: Fri May 29 13:56:45 JST 2
043
証明書のフィンガープリント:
         MD5:  A7:DC:■■:■■:■■:■■:■■:■■:■■:■■:■■:■■:■■:■■:■■:01
         SHA1: 67:5A:■■:■■:■■:■■:■■:■■:■■:■■:■■:■■:■■:■■:■■:■■:■■:■■:■■:0F
         署名アルゴリズム名: SHA1withRSA
         バージョン: 3
Google Developers Centerに作成するアプリ用のProjectを作成

image

Google Developers Consoleにログインして、[Create Project]ボタンをクリックします。

 

image

Project名を指定します。Project IDは自動的に生成されます。

image

 

APIの有効化

プロジェクト名をクリックしてoverviewを表示します。

image

[Enable an API]ボタンをクリックしてAPIリストを表示します。

 

「Maps」で絞り込んで、「Google Maps Android API v2」の行を見つけたら[OFF]ボタンをクリックしてSTATUSを[ON]にします。これでGoogle Maps Android API v2が有効になりました。

image

 

APIキーを取得する

[APIs & auth]-[Credentials]メニューを選択し、[Publis API access]にある[Create new Key]ボタンをクリックします。

image

 

Create a new key画面で[Android key]ボタンをクリックしてAndroid Keyの作成を開始します。

image

 

「keytoolで作成したSHA1フィンガープリント」+「;」+「パッケージ名」を入力してから[Create]ボタンをクリックします。

image

APIキーが表示されるので、これをAndroidManifest.xmlに転記します。

AndroidManifest.xmlの設定

image

Required Permissionsで次のものを選択します。

  • ACCESS_COARSE_LOCATION (GPS非利用時は指定不要)
  • ACCESS_FINE_LOCATION(GPS非利用時は指定不要)
  • ACCESS_MOCK_LOCATION(GPS非利用時は指定不要)
  • ACCESS_NETWORK_STATE
  • ACCESS_WIFI_STATE
  • INTERNET
  • WRITE_EXTERNAL_STORAGE

この状態でAndroidManifest.xamlは次のような内容になっています。

<?xml version="1.0" encoding="utf-8"?>
<manifest package="jp.hatsunejournal.AEDSearch" xmlns:android="http://schemas.android.com/apk/res/android" android:installlocation="auto" android:versioncode="1" android:versionname="1.0.1">
  <uses-sdk android:targetsdkversion="19" />
  <application android:icon="@drawable/Icon" android:label="AED検索">
  </application>
  <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_MOCK_LOCATION" />
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>

あとは直接ファイルを開いて変更します。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto" package="jp.hatsunejournal.AEDSearch" android:versionCode="1" android:versionName="1.0.1">
  <uses-sdk android:targetSdkVersion="19" />
  <application android:label="AED検索" android:icon="@drawable/Icon">
    <!-- APIキーの設定 -->
    <meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="AIzaSyCbwVTZ_mpWOVvnI3vke75QD9ZnheiMfCA" />
    <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
    <!-- -->
  </application>
  <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_MOCK_LOCATION" />
  <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  
  <!-- 権限の追加 -->
  <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
  
  <!-- OpenGL ESの設定-->
  <uses-feature android:glEsVersion="0x00020000" android:required="true"/>
</manifest>

 

必要なAndroid SDKのインストール確認

今回はAndroid 4.2.2 (API17)をターゲットとしてアプリを作成します。4.2.2以外に、Google Play servicesなど必要なライブラリをAndroid SDK Mangerで導入しておきましょう。

image

Xamarin.Forms.Mapsコンポーネントの環境設定
Nugetでの導入

NugetでXamarin.Forms.Mapsを追加したら、必ず更新プログラムを確認して必要なライブラリを最新化します。

image

app.configの設定(2014年11月現在)

2014年11月現在の状況では、Xamarin.Forms.Maps導入後にapp.configにバージョン互換性の設定を行う必要があります。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Primitives" culture="neutral" publicKeyToken="b03f5f7f11d50a3a" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
       <dependentAssembly>
        <assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.28.0" newVersion="4.2.28.0" />
      </dependentAssembly>
    </assemblyBinding>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>
コンパイルエラーの解消

ドキュメントやネット上の情報ではここまでやれば環境整備が完了と思っていましたが、実際にビルドすると

Unzipping failed. Please download 
https://dl-ssl.google.com/android/repository/google_play_services_5089000_r19.zip
 and extract it to the 
C:\User\Project\dotNET2013\WinRT\AEDSearchXamarin\packages\Xamarin.GooglePlayServices.19.0.0.1\lib\MonoAndroid23\19\content
 directory.

というようにunzipできないというエラーが発生して、unzipできないためにzipファイルの中身が電解できずに「google-play-services_lib/libs/google-play-services.jar」がないというビルドエラーが発生してしまい、ビルドできません。

これはzipファイルには実際に必要なjarファイル以外にもjavaファイルなど必須ではないファイルも含まれているのですが、この必須ではないファイルのフォルダ構造が深いためにパス名が長くなってしまいunzipできないという状態になっています。

 

そこで、zipファイルを取得して、それを所定の位置「<プロジェクトルート>\packages\Xamarin.GooglePlayServices.19.0.0.1\lib\MonoAndroid23\19\content」フォルダにフォルダ構造を維持して手作業で展開します。このときも同様にエラーが発生しますが、jarファイルだけ展開できればいいので、不必要なファイルの展開エラーは無視します。

 

これで再度ビルドすれば無事ビルド完了となります。

エミュレーターでの地図表示

image

現在、Android SDK、Genymotion、Xamarin Android Playerなどのエミュレーターのそれぞれの最新版の中でGoogle Play Serviceまで導入できて地図も表示できるのはXamarin Android Playerのようです。このあたりは、エクセルソフトの田淵さんのblogに詳しく載っています。

AED検索 for Androidもちゃんと地図が表示できます。

image

image

 

こんな感じでXamarin Formsで地図表示となるととても大変で、まだ本家のXAMLと比べると足りない点も多いのですが、ベータやアルファの状態を見るとこれからもXamarin Formsは拡充が続くようですので、最新動向に今後も注目していきたいと思います。