「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を使うべき理由)を参照。
動作確認
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使った方が作りやすいんじゃないだろうか、と思ったこともありますが、今のところは何とも言えない感じです。