2016.6.24
2017.5.25

phonegap-googlemaps-pluginの利用

前回の記事でひとまずのデバッグ環境は構築できたので、モバイルアプリを開発するなら一度はやってみたいと思っていた、GoogleマップAPIを利用してみました。

環境構築と同様、自分の経験のなさが原因ですが、動作させるに至るまで結構ハマりました。

目次

  • 「phonegap-googlemaps-plugin」を使う理由
  • インストール・設定
  • 動作確認
  • iOS版のビルドについて
  • まとめ

「phonegap-googlemaps-plugin」を使う理由

ベースがCordovaなので開発でメインとなる言語はHTML/CSS/JavaScript。そうなると、使用するGoogleマップのAPIは「Google Maps JavaScript API」と勝手に思っていましたが、調べていくと、Cordova用にネイティブアプリでの利用を前提とした「Google Maps Android API」と「Google Maps SDK for iOS」が使えるプラグインがありました。JavaScriptのAPIは動作が遅いという話は聞いていたので、そんな便利なプラグインがあるなら使うしかありません。

というわけで、詳しくはこちら(phonegap-googlemaps-pluginを使うべき理由)を参照。

インストール・設定

インストール・設定についてはこちら(Windows向けチュートリアル · mapsplugin/cordova-plugin-googlemaps-ja-doc Wiki · GitHub)を参照。

自分の環境では、事前確認にある「Apache Ant」はインストールしてないので、インストールしなくても大丈夫そう。また、プロジェクトの作成はVisual Studioで行うので、「1. プロジェクトの作成」「2. プラットホームの追加」については行っていません。

「3. SHA1指紋署名の表示」ここで躓きました。最初は「debug.keystore」なんてファイルを作成した覚えがなかったので、自分で作らなきゃいけないと思ってキーの生成をしたりしたのですが、なんのことはなく、Visual Studioのビルド時かなんかで自動で作成されていました。この自動で作られていたキーを使う必要があったので、この辺りを理解するのに2日潰れました。keytoolについてはJavaをインストールすればbin配下に「keytool.exe」という実行ファイルがあるので、これを使います。

SHA1指紋署名とAPIキーについてはこちら(サインアップと API キー  |  Google Maps Android API  |  Google Developers)を参照。

参照した記事のほどんどがAPIの名称を「Google Maps Android API v2」となっていましたが、自分が作業した時は「v2」というバージョン名はついていませんでした。特に問題なく作業は完了したので、バージョン名だけ削除したのかもしれません。

Visual Studioでのプラグインのインストールは、「5. プラグインのインストール」のようなコマンドラインからではなく、プロジェクト作成後、config.xmlがあるはずなのでクリックして表示。下記のように設定することでプラグインの追加(インストール)が可能です。

プラグインのGitのURLはこちら(GitHub - mapsplugin/cordova-plugin-googlemaps: Google Maps plugin for Cordova)。

Visual Studioでのプラグインの追加方法についてはこちら(Visual Studio Tools for Apache Cordova でビルドされたアプリのプラグインの管理)を参照。

動作確認

VSプロジェクト内のwww/index.htmlの変更。

コードはこちら(Windows向けチュートリアル · mapsplugin/cordova-plugin-googlemaps-ja-doc Wiki · GitHub)から抜粋。


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="Content-Security-Policy"/>
    <script type="text/javascript" src="cordova.js"></script>
    <script type="text/javascript">
    var map;
    document.addEventListener("deviceready", function() {
      var div = document.getElementById("map_canvas");
      map = plugin.google.maps.Map.getMap(div);
      map.addEventListener(plugin.google.maps.event.MAP_READY, onMapReady);
    }, false);

    function onMapReady() {
      var button = document.getElementById("button");
      button.addEventListener("click", onBtnClicked, false);
    }

    function onBtnClicked() {
      // 地図をフルスクリーンで表示
      map.showDialog();
    }
    </script>
  </head>
  <body>
    <h3>Cordova-GoogleMaps-Plugin</h3>
    <div style="width:100%;height:400px" id="map_canvas">
      <button>全画面表示</button>
    </div>
    <button id="button">Full Screen</button>
  </body>
</html>

Map上にコマンドを配置する場合、id="map_canvas"の<div>内にコントロールを配置します。

GoogleMapAPIが利用可能かどうかの判定は以下のコードで判断。


plugin.google.maps.Map.isAvailable(function (isAvailable, message) {
    if (isAvailable) {
        alert('利用可能');
    } else {
        alert(message);
    }
});

利用できなかった場合、以下のようなエラーメッセージが表示されます。

「Google Maps Android API v2 is not available, because this device does not have Google Play Service」

Androidエミュレータ―(AVD Manager.exe)を利用したデバッグで、「CPU/ABI」欄に「Google APIs ~」を設定していない場合も、上記のエラーとなるので注意。

なお、Rippleエミュレータ―では地図が使えない(表示されない)ので、地図関連の動作確認はAndroidエミュレータ―や実機での確認が必要になります。

iOS版のビルドについて

Macでリモートビルドを行うと、以下のようなエラーが出てビルドが失敗します。

CompileC build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/Objects-normal/i386/Geocoder.o ionic-sidemenu/Plugins/cordova-plugin-googlemaps/Geocoder.m normal i386 objective-c com.apple.compilers.llvm.clang.1_0.compiler
    cd /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios
    export LANG=en_US.US-ASCII
    export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/Users/hoge/.taco_home/node_modules/taco-remote-lib/2.2.0/node_modules/taco-remote-lib/node_modules/.bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c -arch i386 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=c99 -fobjc-arc -fmodules -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fbuild-session-file=/var/folders/xf/4408787s1mj43zdt6l676p500000gn/C/org.llvm.clang/ModuleCache/Session.modulevalidation -fmodules-validate-once-per-build-session -Wno-trigraphs -fpascal-strings -O0 -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-implicit-atomic-properties -Wno-arc-repeated-use-of-weak -Wduplicate-method-match -Wno-missing-braces -Wparentheses -Wswitch -Wunused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wempty-body -Wuninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wno-shorten-64-to-32 -Wpointer-sign -Wno-newline-eof -Wno-selector -Wno-strict-selector-match -Wundeclared-selector -Wno-deprecated-implementations -DDEBUG=1 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator9.3.sdk -fasm-blocks -fstrict-aliasing -Wprotocol -Wdeprecated-declarations -mios-simulator-version-min=8.0 -g -fvisibility=hidden -Wno-sign-conversion -fobjc-abi-version=2 -fobjc-legacy-dispatch -iquote /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/ionic-sidemenu-generated-files.hmap -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/ionic-sidemenu-own-target-headers.hmap -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/ionic-sidemenu-all-target-headers.hmap -iquote /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/ionic-sidemenu-project-headers.hmap -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/emulator/include -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/emulator/usr/local/lib/include -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/UninstalledProducts/include -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/UninstalledProducts/iphonesimulator/include -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/emulator -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/DerivedSources/i386 -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/DerivedSources -F/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/emulator -Fionic-sidemenu/Plugins/com.googlemaps.ios -include /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/sharedpch/ionic-sidemenu-Prefix-gchtuabcqpwejqcqebjknrvjpwle/ionic-sidemenu-Prefix.pch -MMD -MT dependencies -MF /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/Objects-normal/i386/Geocoder.d --serialize-diagnostics /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/Objects-normal/i386/Geocoder.dia -c /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/ionic-sidemenu/Plugins/cordova-plugin-googlemaps/Geocoder.m -o /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/Objects-normal/i386/Geocoder.o
In file included from /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/ionic-sidemenu/Plugins/cordova-plugin-googlemaps/Geocoder.m:9:
In file included from /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/ionic-sidemenu/Plugins/cordova-plugin-googlemaps/Geocoder.h:9:
/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/ionic-sidemenu/Plugins/cordova-plugin-googlemaps/GoogleMaps.h:10:9: fatal error: 'GoogleMaps/GoogleMaps.h' file not found
#import <GoogleMaps/GoogleMaps.h>
        ^

CompileC build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/Objects-normal/i386/GoogleMaps.o ionic-sidemenu/Plugins/cordova-plugin-googlemaps/GoogleMaps.m normal i386 objective-c com.apple.compilers.llvm.clang.1_0.compiler
    cd /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios
    export LANG=en_US.US-ASCII
    export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/Users/hoge/.taco_home/node_modules/taco-remote-lib/2.2.0/node_modules/taco-remote-lib/node_modules/.bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c -arch i386 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=c99 -fobjc-arc -fmodules -fmodules-prune-interval=86400 -fmodules-prune-after=345600 -fbuild-session-file=/var/folders/xf/4408787s1mj43zdt6l676p500000gn/C/org.llvm.clang/ModuleCache/Session.modulevalidation -fmodules-validate-once-per-build-session -Wno-trigraphs -fpascal-strings -O0 -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-implicit-atomic-properties -Wno-arc-repeated-use-of-weak -Wduplicate-method-match -Wno-missing-braces -Wparentheses -Wswitch -Wunused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wempty-body -Wuninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wconstant-conversion -Wint-conversion -Wbool-conversion -Wenum-conversion -Wno-shorten-64-to-32 -Wpointer-sign -Wno-newline-eof -Wno-selector -Wno-strict-selector-match -Wundeclared-selector -Wno-deprecated-implementations -DDEBUG=1 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator9.3.sdk -fasm-blocks -fstrict-aliasing -Wprotocol -Wdeprecated-declarations -mios-simulator-version-min=8.0 -g -fvisibility=hidden -Wno-sign-conversion -fobjc-abi-version=2 -fobjc-legacy-dispatch -iquote /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/ionic-sidemenu-generated-files.hmap -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/ionic-sidemenu-own-target-headers.hmap -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/ionic-sidemenu-all-target-headers.hmap -iquote /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/ionic-sidemenu-project-headers.hmap -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/emulator/include -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/emulator/usr/local/lib/include -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/UninstalledProducts/include -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/UninstalledProducts/iphonesimulator/include -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/emulator -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/DerivedSources/i386 -I/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/DerivedSources -F/Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/emulator -Fionic-sidemenu/Plugins/com.googlemaps.ios -include /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/sharedpch/ionic-sidemenu-Prefix-gchtuabcqpwejqcqebjknrvjpwle/ionic-sidemenu-Prefix.pch -MMD -MT dependencies -MF /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/Objects-normal/i386/GoogleMaps.d --serialize-diagnostics /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/Objects-normal/i386/GoogleMaps.dia -c /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/ionic-sidemenu/Plugins/cordova-plugin-googlemaps/GoogleMaps.m -o /Users/hoge/.taco_home/remote-builds/taco-remote/builds/4299/cordovaApp/platforms/ios/build/ionic-sidemenu.build/Debug-iphonesimulator/ionic-sidemenu.build/Objects-normal/i386/GoogleMaps.o

このエラーは意味が分からなくて非常に困りましたが、以下のサイトに解決策が載っていました。

File not found GoogleMaps/GoogleMaps.h · Issue #719 · mapsplugin/cordova-plugin-googlemaps · GitHub

<GoogleMaps/GoogleMaps.h> file not found Google Maps SDK for iOS - Stack Overflow

最初は関係ないだろうと検索に引っかかってもあまり詳しくは見ていませんでしだが、他に該当する解決方法もなく、ちゃんと英語を翻訳して対応することでリモートビルドが正常に行われるようになりました。

拙い英語力で解読すると、どうやら、リモートビルド時にVisual Studioソース内のシンボリックリンクがMac側にコピーされない?のが問題のようで、それが原因でビルドに失敗していたようです。

対応方法は、「plugins/com.googlemaps.ios/GoogleMaps.framework/」直下の「GoogleMaps」「Headers」「Modules」「Resources」ファイルを削除して、「Versions/A/」配下のすべてのファイルとディレクトリを「GoogleMaps.framework/」直下にコピペし、以下のような構成にします。

変更前)



変更後)



さらに「plugins/com.googlemaps.ios/」直下の「plugin.xml」を開いて、以下のように修正する。


<!-- 変更前 -->
<resource-file src="GoogleMaps.framework/Versions/A/Resources/GoogleMaps.bundle"/>

<!-- 変更後 -->
<resource-file src="GoogleMaps.framework/Resources/GoogleMaps.bundle"/>

この問題で3日くらい悩んでたので、Macでデバッグできた時はちょっと感動しました。

まとめ

そんなこんなでようやくGoogleMap APIを利用したアプリの開発環境が整ったわけですが、正直に言って、今のところCordovaの恩恵はまったく受けておらず、本当にネイティブアプリ作るよりも工数少なくなるんだろうかと懐疑的です。

ハイブリッドアプリの利点を感じるのは実際に作り始めてからだと思うので、今後に期待したいところですね。ただ、エラーの内容を見ていると分かると思いますが、この時点ですでにionicフレームワークに手を出していて、Androidベースで開発した後にiOSで確認すると結構デザインが崩れていたりしました。UIについては両方に対応した書き方があるのか別々に定義しないいけないのか、その辺りを今後見極めたいです。GoogleMapを表示したらデザインが崩れたりとかもしたので、もしかしたらXamalin使った方が作りやすいんじゃないだろうか、と思ったこともありますが、今のところは何とも言えない感じです。

Cordova】関連記事