Apache Cordova(PhoneGap) を導入して iOS と Android で Hello World してみた

Apache Cordova とは

PhoneGap がいつの間にか Apache 傘下にはいって Cordova という名前になってた。ざっくりとした理解としては HTML5+CSS+JS でつくったアプリを iOS Android 両方にビルドしてくれる便利環境*1。Titanium と似ているという感覚でとらえているし、だいたいそういう感じだと思っている*2
導入の参考::PhoneGap(Apache Cordova)を触ってみた - aoki_pの日記
技評の連載::第1回 PhoneGap/Cordovaとは:もっと使おうPhoneGap/Cordova 2.0.0|gihyo.jp … 技術評論社
PhoneGap 日本語情報::PhoneGap Fan - PhoneGap (Cordova) の日本語コミュニティ
スライド::PhoneGapの始め方
スライド::PhoneGapで作るハイブリッドアプリケーション
スライド::jQuery MobileとPhoneGapでスマートフォンアプリ楽々クッキング

経緯がわかりづらい

参考::AdobeがPhoneGapブランドでCordovaを提供
参考::Apache cordova
Nitobi という会社が PhoneGap をつくる→OSS化して Apache に寄贈→AAdobe が買収→apache は Cordova という名前で配布。ただし、PhoneGap という名前自体は商標っぽくなんかつかわれてるっぽくて、なんだかよくわからない。

とりあえず導入する

公式ページからダウンロード PhoneGap | Download & Archives
DLしたバージョンは現時点の最新版 2.1.0
PhoneGap と Cordova 両方あるけど、とりあえず PhoneGap を落とした。どうやら最近まで Cordova では配布してなかったらしい。 Cordova で配布しているのはまさに OSS で開発したソース的な感じで、実際に開発につかうのは PhoneGap から落とせばいいような温度感?

とりあえず iOS で Hello World する

落としてきた PhoneGap から解凍して create で土台を作成

# create への path, つくるプロジェクトの path, プロジェクトのユニークなドメイン, プロジェクトの名前
phonegap/lib/ios/bin/create ~/work/HogeProject net.hogeproject HogeProject

とりあえず Xcode で Run しておけば Hello World できる

とりあえず AndroidHello World する

!!! 公式チュートリアルを参考にする !!!

参考::Apache Cordova API Documentation

Eclipse をいれる

なんか完全版じゃなくて Classic なるものでいいらしいのでそれをいれる
Eclipse JUNO なるバージョンがはいった。前は日本語化とかしたけど今回は面倒なのでパス。

ADT をいれる

ひさびさすぎるし Ecpilce に慣れないので迷った
ADT とは Android Development Tools です
参考::Mac OS X 10.7 Lion にAndroid SDKとEclipse ADT PluginをインストールしてAndroidアプリ開発環境を構築する - プログラム作成メモメモ
とりあえず下記 URL を入力して必要そうなのをいれた。というか全部必要そうなので全部いれた。

https://dl-ssl.google.com/android/eclipse/

いれたら再起動

Android SDK の path を通す

再起動したら SDK の path を求められる。あらかじめチュートリアルでいれておいた SDK を解凍してそこの path を指定しておく。
AndroidAPI バージョンが聞かれるので、適宜チェックを入れてインストールする。今回は 2.3, 4.x のものをいれた。(クッソ時間がかかります。マミさんティーを飲みましょう)

Android プロジェクトを作成する

新規プロジェクト作成からそれっぽい感じでつくってください。わからなかったらひたすらググる

必要なディレクトリをつくる & ファイルをコピーする
  • 上記で作成した新規 root ディレクトリに libs assets/www を作成する(今回は libs と assets はあったけど assets/www はなかったので作成した)。
  • cordova-2.1.0.js を assets/www に、 cordova-2.1.0.jar を libs にコピーする。
  • import org.apache.cordova.*
  • extends Activity (Androidの標準的なやつ) から DroidGap に変更
  • setContentView を super.loadUrl("file:///android_asset/www/index.html") に変更
  • manifest.xml and の間に以下を追記
<supports-screens
    android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:resizeable="true"
    android:anyDensity="true" />
<uses-permission android:name="android.permission.VIBRATE" />
<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_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
  • Activity の部分に以下を追記
android:configChanges="orientation|keyboardHidden"
  • PhoneGap/ から xml/ ディレクトリを res/ 以下にコピー
  • なんかライブラリあたりをおもむろに右クリックして Build Paths に cordova-2.1.0.jar をなんかこう追加
  • assets/www/ に index.html をおいて完成
Run!!

おもむろに Run してあげてエミュレータ(重い)を立ち上げればそれっぽいものが立ち上がります

便利ツール

PhoneGap Builder というバイナリ生成便利サイトがある

http://build.phonegap.com/
参考::【レポート】「PhoneGap Build」で一層手軽になったモバイルアプリ開発 | クリエイティブ | マイナビニュース
ただし Adobe アカウントか github アカウントが必要。github はいいけど、エンタープライズで使うとなるとプライベートリポジトリ登録が必要だし、どのくらい便利かはわからない。

weinre (JavaScript デバッガ)

リモートデバッガ。PhoneGap アプリにデバッガをしこんでおいて、 Node のモジュールである weinre を起動すると、 localhost でデバッガが起動する。

さて、iOS と Android で共通のアプリを作ろうと思うのだが

どういったやりかたがベストプラクティスなのかはイマイチよくみえなかった。

iOSの場合

自動生成されたプロジェクトディレクトリは以下

HogeProjectIOS/
├── HogeProjectIOS
│   ├── Classes
│   │   ├── AppDelegate.h
│   │   ├── AppDelegate.m
│   │   ├── MainViewController.h
│   │   ├── MainViewController.m
│   │   └── MainViewController.xib
│   ├── Cordova.plist
│   ├── CordovaBuildSettings.xcconfig
│   ├── HogeProjectIOS-Info.plist
│   ├── HogeProjectIOS-Prefix.pch
│   ├── Plugins
│   │   └── README
│   ├── Resources
│   │   ├── Capture.bundle
│   │   │   ├── controls_bg.png
│   │   │   ├── controls_bg@2x.png
│   │   │   ├── controls_bg@2x~ipad.png
│   │   │   ├── controls_bg~ipad.png
│   │   │   ├── microphone.png
│   │   │   ├── microphone@2x.png
│   │   │   ├── microphone@2x~ipad.png
│   │   │   ├── microphone~ipad.png
│   │   │   ├── record_button.png
│   │   │   ├── record_button@2x.png
│   │   │   ├── record_button@2x~ipad.png
│   │   │   ├── record_button~ipad.png
│   │   │   ├── recording_bg.png
│   │   │   ├── recording_bg@2x.png
│   │   │   ├── recording_bg@2x~ipad.png
│   │   │   ├── recording_bg~ipad.png
│   │   │   ├── stop_button.png
│   │   │   ├── stop_button@2x.png
│   │   │   ├── stop_button@2x~ipad.png
│   │   │   └── stop_button~ipad.png
│   │   ├── de.lproj
│   │   │   └── Localizable.strings
│   │   ├── en.lproj
│   │   │   └── Localizable.strings
│   │   ├── es.lproj
│   │   │   └── Localizable.strings
│   │   ├── icons
│   │   │   ├── icon-72.png
│   │   │   ├── icon-72@2x.png
│   │   │   ├── icon.png
│   │   │   └── icon@2x.png
│   │   ├── se.lproj
│   │   │   └── Localizable.strings
│   │   └── splash
│   │       ├── Default-Landscape@2x~ipad.png
│   │       ├── Default-Landscape~ipad.png
│   │       ├── Default-Portrait@2x~ipad.png
│   │       ├── Default-Portrait~ipad.png
│   │       ├── Default@2x~iphone.png
│   │       └── Default~iphone.png
│   └── main.m
├── HogeProjectIOS.xcodeproj
│   └── project.pbxproj
├── cordova
│   ├── debug
│   ├── emulate
│   └── log
└── www
    ├── cordova-2.1.0.js
    ├── css
    │   └── index.css
    ├── img
    │   └── logo.png
    ├── index.html
    ├── js
    │   └── index.js
    ├── res
    │   ├── icon
    │   │   └── ios
    │   │       ├── icon-57-2x.png
    │   │       ├── icon-57.png
    │   │       ├── icon-72-2x.png
    │   │       └── icon-72.png
    │   └── screen
    │       └── ios
    │           ├── screen-ipad-landscape-2x.png
    │           ├── screen-ipad-landscape.png
    │           ├── screen-ipad-portrait-2x.png
    │           ├── screen-ipad-portrait.png
    │           ├── screen-iphone-landscape-2x.png
    │           ├── screen-iphone-landscape.png
    │           ├── screen-iphone-portrait-2x.png
    │           └── screen-iphone-portrait.png
    ├── spec
    │   ├── helper.js
    │   ├── index.js
    │   └── lib
    │       └── jasmine-1.2.0
    │           ├── MIT.LICENSE
    │           ├── jasmine-html.js
    │           ├── jasmine.css
    │           └── jasmine.js
    └── spec.html

iOS アプリには詳しくないがなんとなくそれっぽく書く。 HogeProjectIOS 以下に展開されているのが、iOS 特有のいろいろなリソースなのかな?Classes とかヘッダファイルだし、 xcconfig や plist とかの設定ファイル、 Plugins でプラグイン管理、 Resources 以下で各種言語設定やアイコンの設定ファイルが置かれている。今回 PhoneGap で使う実体となるのは www 以下のファイルで、 cordova-2.1.0.js が起点となっててまあ普通に css img js が切られている。プロジェクトが複雑になったらhtml とかいろいろディレクトリを切っていくんだろう。ただ、 www/index.html が起点となっているっぽいので、スタートはおそらくそこ。 spec とかで jasmine とかあるのが親切設計なのかな。

Android の場合

プロジェクトを作成した例は以下

hoge/
├── AndroidManifest.xml
├── assets
│   └── www
│       ├── cordova-2.1.0.js
│       └── index.html
├── bin
│   ├── AndroidManifest.xml
│   ├── classes
│   │   └── jp
│   │       └──aproud
│   │           └── hogeproject
│   │               └── android
│   │                   ├── BuildConfig.class
│   │                   ├── MainActivity.class
│   │                   ├── R$attr.class
│   │                   ├── R$drawable.class
│   │                   ├── R$id.class
│   │                   ├── R$layout.class
│   │                   ├── R$menu.class
│   │                   ├── R$string.class
│   │                   ├── R$style.class
│   │                   └── R.class
│   ├── classes.dex
│   ├── hoge.apk
│   ├── jarlist.cache
│   ├── res
│   │   ├── drawable-hdpi
│   │   │   ├── ic_action_search.png
│   │   │   └── ic_launcher.png
│   │   ├── drawable-ldpi
│   │   │   └── ic_launcher.png
│   │   ├── drawable-mdpi
│   │   │   ├── ic_action_search.png
│   │   │   └── ic_launcher.png
│   │   └── drawable-xhdpi
│   │       ├── ic_action_search.png
│   │       └── ic_launcher.png
│   └── resources.ap_
├── gen
│   └── jp
│       └──aproud
│           └── hogeproject
│               └── android
│                   ├── BuildConfig.java
│                   └── R.java
├── ic_launcher-web.png
├── libs
│   ├── android-support-v4.jar
│   └── cordova-2.1.0.jar
├── proguard-project.txt
├── project.properties
├── res
│   ├── drawable-hdpi
│   │   ├── ic_action_search.png
│   │   └── ic_launcher.png
│   ├── drawable-ldpi
│   │   └── ic_launcher.png
│   ├── drawable-mdpi
│   │   ├── ic_action_search.png
│   │   └── ic_launcher.png
│   ├── drawable-xhdpi
│   │   ├── ic_action_search.png
│   │   └── ic_launcher.png
│   ├── layout
│   │   └── activity_main.xml
│   ├── menu
│   │   └── activity_main.xml
│   ├── values
│   │   ├── strings.xml
│   │   └── styles.xml
│   ├── values-v11
│   │   └── styles.xml
│   └── values-v14
│   │   └── styles.xml
│   └── xml
│       └── config.xml
└── src
    └── jp
        └── aproud
            └── hogeproject
                └── android
                    └── MainActivity.java

bin とか gen はまあおいといて、プロジェクト設定ファイルは AndroidManifest.xml ですね。で、src 以下に PhoneGap を使う設定をする。 libs に cordova-2.1.0.jar をおくことでネイティブにアクセスできるようにしているんだと思う。で、実際の中身はやはり assets/www 以下におく感じになりそう?assets/www 以下に cordova-2.1.0.js をおくというところが共通しているのでおそらくそうなる気がする。ちなみに Android アプリとして特有のスプラッシュ画面に使うような画像とかは res 以下に置く感じになるんですかね?

と思ったけど

よく考えたら MainActivity.java に android_asset/www/index.html って指定してるのを android_asset/index.html って指定すれば iOS の場合と同じように階層をつくれることがわかった。というか android_asset で assets ディレクトリにアクセスできるようだ。

で、実際どうよ

わからんす。
とりあえず www 以下に普通のサイトを使うように js css img html を置いていく形になるんですかね。見た目を共通化するという意味では jQuery Mobile を使うと相性がいいかも?あと軽くしたい用途に Zepto.js ?まだ触ってないけど cordova.js を通じてネイティブライブラリにアクセスするっぽい感じらしいので、iOS や Android 固有の設定や画像は専用に用意して、それ以外のものはおそらく www 以下に置く感じになるのかなー。
ちなみに Cordova.js 自体は名前は同じでも iOS 用と Android 用とでは中身は違う。また、「www 以下が同じならシンボリックリンクはればええんやー」ってやってみたけど、そうするとうまく読み込めないっぽい*3。なので www 以下になにかディレクトリ掘ってそこにシンボリックリンク貼って共通のディレクトリを参照したらいいのかなぁ。うーん、どうなんだろう。

*1:ちなみに今 wikipedia みてみたら palm WebOS, Windows Mobile Symbian, BlackBerryにも対応しているようだ。どんだけだよ

*2:たぶん Titanium と同じでこったことをしようと思うと結局ネイティブじゃないとツラい話になりそうだけど、簡単なアプリならそこまでハマらない……はず

*3:って記事かいたときは思ったけど、うまくパスを生成してやれば共通化できるかもしれない。が、確証はない