PhoneGap 3.3.0でiOS開発する
PhoneGapとは
HTML5+CSS+JavaScriptのみでさまざまなスマートフォンプラットフォーム、例えばAndroid、iOS、Windows Phone7/8、BlackBerryに対応できるフレームワークです。
なんでこんなもん使おうと思ったのか
html5で本来ネイティブアプリケーションでないと操作が難しかった、ファイル、カメラ、GPS、近接センサ、電池残量検出といった機能を実装できる様になってきました。
もし、ブラウザで完結できるようなアプリであれば、わざわざXcodeをつかう開発しなくていいので、ブログやプレゼンでjsのコードだけ貼付けておけば手軽に試してもらえるかな、と思った訳です。
具体的にはマイクで音声信号を広い、デコードした内容に応じて結果をスピーカから音声で返すモデムの実装です。(一時期流行ったAudio Hi-Jackです)
でも、現実はそんなに甘くなく
ブラウザ経由でマイクからの音声を取得するのにgetUserMedia() APIを使いますが、これは2014年1月現在iOS Safariでは対応していないわけです。
というわけで、(Xcodeで開発しなきゃならないのは仕方ないですが)マイクの取得=ネイティブ or それに準ずる環境、それ以外=HTML5 + JSで実行する事になります。このような理由からPhoneGapを使いました。
導入まで
導入方法が書いてある書籍やブログに当たったんですが、3.3.0ではかなり変わっちゃったみたいで少し苦労しました。
以下はそのメモ。
まずPhoneGap本家サイト:
PhoneGap | Home
※ Xcodeの導入、iOSデバイスのプロビジョニング関連は完了しているものとする。またnode.jsは導入済みのものとする
本体のインストール
$ sudo npm install -g phonegap
作りたいアプリケーションをCompany Identifierとともに指定します。自分の場合はVoiceCoderと言う名前で、Identifierはcom.lynxeyed.voicecoderとしました。
$ phonegap create voicecoder com.lynxeyed.voicecoder "VoiceCoder"
ディレクトリに移動
$ cd voicecoder/
使用するプラグインを導入します。今回はMedia API、Media Capture APIを使うのでこちらを導入しました
$ phonegap plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-media.git $ phonegap plugin add https://git-wip-us.apache.org/repos/asf/cordova-plugin-media-capture.git
iOS用にビルドします。
$ phonegap build ios
すると、XCode用プロジェクトが、[アプリケーション名]/platform/ios/ 配下に作成されます。
とりあえず、このプロジェクトファイルをダブルクリックして、Xcodeを起動します。
実行します。
実機を指定している場合はiOSデバイス本体、そうでない場合はシミュレータが立ち上がって
こんな感じになれば動作確認は終了です
とりあえずマイクから録音できるか確認する
Audio Hi-Jackネタではマイクが使えないといけないので、ここだけ確認します。
使うのはPhoneGapのMedia APIです。
以下のサイトのコードをほぼそのまま使っています。が、3.3.0ではiOS、AndroidでMedia APIの呼び出すメソッドの差異は無い模様なので修正しました。
ASCII.jp:JavaScriptで作れるiPhone用ボイスレコーダー (1/5)|古籏一浩のJavaScriptラボ
画面はこんな感じ。
以下を/www配下のindex.htmlに記述します。iOS以外でも動作するはずですがwebkit系のブラウザ以外ではスタイルが崩れるはずなので各自修正を。
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no;" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <style> .btn { font-family: Arial, Helvetica, sans-serif; font-size: 28px; color: #fff; padding: 12px 18px; background: #8893da; background: -webkit-gradient( linear, left top, left bottom, from(#8893da), to(#344c77) ); border-radius: 10px; -webkit-box-shadow: 12px 12px 12px rgba(000, 000, 000, 0.3), inset 0px 0px 0px rgba(255, 255, 255, 0); text-shadow: 10px 10px 10px rgba(000, 000, 000, 1), } </style> <script type="text/javascript" charset="utf-8" src="phonegap.js"></script> <script type="text/javascript" charset="utf-8"> var rec = null; var src = null; document.addEventListener("deviceready", init(), false); function init(){ src = "test.wav"; } function startRec(){ rec = new Media(src, // success callback function() { console.log("Audio Success"); }, // error callback function(err) { console.log("Audio Error: "+ err.code); }); // Record audio rec.startRecord(); document.getElementById("stat").innerHTML = "recording..."; } function stopRec(){ rec.stopRecord(); document.getElementById("stat").innerHTML = "stop recording"; } function playRec(){ rec.play(); document.getElementById("stat").innerHTML = "play..."; } function playStop(){ rec.stop(); document.getElementById("stat").innerHTML = "stop playing"; } </script> </head> <body> <h1>Using Media APIs</h1> <div> <button class="btn" onclick="startRec()">REC</button> <button class="btn" onclick="stopRec()">STOP REC</button> <button class="btn" onclick="playRec()">PLY</button> <button class="btn" onclick="playStop()">STOP PLAY</button> </div> <div id="stat"></div> </body> </html>