JP::HSJ::Junknews::HatenaSide このページをアンテナに追加 RSSフィード

新ブログに移転気味です

はてなブログに新しいブログ MUTEを作ってそちらのほうを中心に更新していますので、併せてご覧下さい。技術系のはこっちに残りそうな気配デス。

Information

TitaniumMobile関連ニュースを扱うブログTitanium Newsを開設しました
titanium-mobile-doc-ja(開店休業中です…ごめんなさい)
▼好評発売中:Titanium Mobileで開発するiPhone/Androidアプリ(翔泳社刊)
 ※Titanium Studio等、刊行後の新機能について補完するPDFを公開しています
  →(http://bit.ly/tsinstall)

Titanium Mobileリンク集

2012年04月01日

Titanium Mobile with TiShadowで転送時間(ほぼ)ゼロのスマートフォン実機開発をしよう!!(Draft)

今回Titanium Mobileでの開発を一変させるプロダクトを紹介したいと思います。その名もTiShadow*1です。

https://github.com/dbankier/TiShadow

リリース直後にAppceleratorの公式ブログで紹介されたり、先日

moongiftでも紹介記事がありました。

上記の記事でも紹介されているようTiShadowは、David Bankierさんが開発された、node.jsで動作するサーバを介して、各シミュレータや実機にインストールされたTiShadowクライアントアプリケーションを配信するというもの…といっても、言葉ではなかなか伝わりませんね。

いわゆる百聞は一見に如かずで、次の動画を見て頂くのが早いかもしれません。

TiShadowサーバにはWebコンソールがあり、ここにCommonJSベースのコードを記述する事で、接続しているTiShadowクライアントに対して即座に配信されます。

準備

まずはgithubからTiShadowの一式をcloneするかzipで取得するかしてください。

あとnode.jsの実行環境も必要になります。お手軽に済ませるにはビルドバイナリをさくっとゲットしましょう。

TiShadowフォルダ構成

TiShadowをここでは~/Documents/TiShadow/に設置したと仮定します。

レポジトリの中のフォルダ構成は次のようになっています。

  • app/
  • build/
  • ruble/
  • server/
  • mobilesdk-tishadow-osx.zip
app

TiShadowクライアントアプリケーション(Titanium Mobileで記述されています)のフォルダです。

このフォルダを新規プロジェクトとして流し込むか、Importしたりして実行できるようにしましょう。

build

あとで説明する局面で用いるtishadowコマンドシェルスクリプト(bash)が格納されています。

ruble

今のところ無視しておきましょう:-P

server

node.jsで開発されたTiShadowの配信サーバアプリです。

mobilesdk-tishadow-osx.zip

TiShadowの挙動のためには配布されているTitanium Mobile SDKパッチを当てた状態のものが必要となり、それがこのファイルの中身になります。

展開後面倒なのですが/Library/Application Support/Titanium/mobilesdk/osx/にTiShadowフォルダを作成して、流し込んでください。

まずは実行してみる

すでにTiShadow/appの中身は先ほど展開したパッチ適用版のSDKを設定したのち、Titanium Studioなどでビルドして、iOSシミュレータなどで実行し、サーバ接続先のIPアドレス入力欄が表示されている状態になっていると仮定します。*2

f:id:donayama:20120401210840p:image

TiShadowサーバの起動

ターミナルでTiShadow/serverをカレントディレクトリにしてから以下のコマンドを入力してください。

$cd ~/Documents/TiShadow/server/
$node app.js

もし各種パッケージが足りないと言われた場合、以下のような感じでインストールしてください。(適当)

$sudo  npm install -d
$sudo  npm install -d express
$sudo  npm install -d socket.io

起動に成功すると3000/tcpでExpress serverが立ち上がります。

$ node app.js
Express server listening on port 3000 in development mode

お手持ちのブラウザでhttp://localhost:3000にアクセスしましょう。

そうするとこんな画面が出たはずですね。

f:id:donayama:20120401210848p:image

出てないときはいろいろエラーがコンソールに出てるはずなので、がんばって手直ししましょう。

以下は正常なときの表示です。

A socket connected!
CONTROLLER IS HERE

クライアントに配信してみる

クライアントIPアドレスサーバIPアドレスを入力します。

f:id:donayama:20120401210841p:image

シミュレータ上ならlocalhost(or 127.0.0.1)でも通りますが、実機ならキチンとIPアドレス入力してくださいね。(Ti.App.Propertyに登録されるので、次回からは入力不要です)

サーバに接続できると、クライアント側にはConnected、サーバ側にはDevices欄に接続したクライアントの表示がされます。

A socket connected!
iphone, 5.1, 192.168.100.101 ARRIVED

f:id:donayama:20120401210842p:image

f:id:donayama:20120401210849p:image

このままでは真っ白な画面なので、次のコードを"Enter your Titanium Code"欄に入れちゃってください。

(function(){
    var win = Ti.UI.createWindow();
    win.backgroundColor = 'blue';
    return win;
}());

f:id:donayama:20120401210850p:image

そして、"Send Code"をクリックすると、すぐさま実機/シミュレータにて青画面が表示されたと思います。

f:id:donayama:20120401210843p:image

さらにここで以下の部分を修正して、もう一度Send Codeすると、これまたすぐに反映することが分かると思います。

win.backgroundColor = 'red'; // blueから変更

f:id:donayama:20120401210844p:image

もちろん色だけではなく、UI部品の配置なども含めて出来ます。

(function(){
    var win = Ti.UI.createWindow();
    var btnTest = Ti.UI.createButton({
        title: 'Test', width: 100, height:50
    });
    btnTest.addEventListener('click', function(){
        alert('テスト!!');
    });
    win.add(btnTest);
    win.backgroundColor = 'blue';
    return win;
}());

f:id:donayama:20120401210845p:image

f:id:donayama:20120401210846p:image

サポートされているTiAPIについて

実は(いまのところ標準では)すべてのAPIがサポートされている訳ではありません。

たとえばカメラを動かそうとしても(いまのところ標準では)動きません。

そこでいじるのが/app/Resources/api/includes.jsです。

非常に分かりやすいリストなので、この末尾にTi.Media.showCameraを追加します(直前のお尻にカンマを足すように!)。

  Ti.UI.create2DMatrix,
  Ti.UI.create3DMatrix,
  /* 略 */
  Ti.UI.createWindow,
  Ti.Media.showCamera  // この1行を足した
];

あとはCleanビルドをしてから実機/シミュレータインストールします。

そして、先ほどまでのWebコンソールのソースを次のように修正したら、カメラの表示のはいできあがり!

(function() {
    var win = Ti.UI.createWindow();
    var btnTest = Ti.UI.createButton({
        title: 'Test', width: 100, height:50
    });
    btnTest.addEventListener('click', function(){
        Titanium.Media.showCamera({
            success:function(event){
            },
            mediaTypes:[Ti.Media.MEDIA_TYPE_PHOTO],
            saveToPhotoGallery:true
        });
    });
    win.add(btnTest);
    win.backgroundColor = 'blue';
    return win;
}());

すごいすごい!

f:id:donayama:20120401210839p:image

f:id:donayama:20120401210847p:image

しかも、Android実機にもこれをインストールしておく事で、同時配信ができるんですよ!*3

とこれだけでも感動しますが、ここまでは実は前振りで、ここからが本番なのです。

ひとまずプロジェクトを作ります。

Webコンソールでちまちまコーディングなんかやってられないですよね?

適当に新規プロジェクトを作りましょうか。

ここではTitanium Studio 1.0.8以降で選択できるCommonJSテンプレートスタイルアプリケーションを選び、TiShadowSampleと名付けたプロジェクトにします。

f:id:donayama:20120401210852p:image

f:id:donayama:20120401210853p:image

作ったのちTitanium StudioのTerminal ViewもしくはターミナルアプリカレントディレクトリをTiShadowSampleの直下(Resourcesではなくそのひとつ上)に設定します。

$ ~/Documents/TiShadow/build/tishadow

と実行すると、以下のようなログが流れ、すぐさま実機/シミュレータアプリが転送されていると思います。

Begining Build Process
Performing full build.
BUILDING FILE: ./build/tishadow/src/app.js
BUILDING FILE: ./build/tishadow/src/ui/common/DetailView.js
BUILDING FILE: ./build/tishadow/src/ui/common/MasterView.js
BUILDING FILE: ./build/tishadow/src/ui/handheld/android/ApplicationWindow.js
BUILDING FILE: ./build/tishadow/src/ui/handheld/ios/ApplicationWindow.js
BUILDING FILE: ./build/tishadow/src/ui/handheld/mobileweb/ApplicationWindow.js
BUILDING FILE: ./build/tishadow/src/ui/tablet/ApplicationWindow.js
  adding: android/ (stored 0%)
  adding: android/appicon.png (deflated 0%)
  adding: android/default.png (deflated 2%)
  adding: android/images/ (stored 0%)
  adding: android/images/res-long-land-hdpi/ (stored 0%)
  adding: android/images/res-long-land-hdpi/default.png (deflated 1%)
  adding: android/images/res-long-land-ldpi/ (stored 0%)
  adding: android/images/res-long-land-ldpi/default.png (deflated 1%)
  adding: android/images/res-long-port-hdpi/ (stored 0%)
  adding: android/images/res-long-port-hdpi/default.png (deflated 1%)
  adding: android/images/res-long-port-ldpi/ (stored 0%)
  adding: android/images/res-long-port-ldpi/default.png (deflated 0%)
  adding: android/images/res-notlong-land-hdpi/ (stored 0%)
  adding: android/images/res-notlong-land-hdpi/default.png (deflated 1%)
  adding: android/images/res-notlong-land-ldpi/ (stored 0%)
  adding: android/images/res-notlong-land-ldpi/default.png (deflated 0%)
  adding: android/images/res-notlong-land-mdpi/ (stored 0%)
  adding: android/images/res-notlong-land-mdpi/default.png (deflated 1%)
  adding: android/images/res-notlong-port-hdpi/ (stored 0%)
  adding: android/images/res-notlong-port-hdpi/default.png (deflated 1%)
  adding: android/images/res-notlong-port-ldpi/ (stored 0%)
  adding: android/images/res-notlong-port-ldpi/default.png (deflated 1%)
  adding: android/images/res-notlong-port-mdpi/ (stored 0%)
  adding: android/images/res-notlong-port-mdpi/default.png (deflated 2%)
  adding: app.js (deflated 54%)
  adding: iphone/ (stored 0%)
  adding: iphone/appicon.png (stored 0%)
  adding: iphone/Default-Landscape.png (deflated 0%)
  adding: iphone/Default-Portrait.png (deflated 0%)
  adding: iphone/Default.png (deflated 0%)
  adding: iphone/Default@2x.png (deflated 0%)
  adding: KS_nav_ui.png (stored 0%)
  adding: KS_nav_views.png (stored 0%)
  adding: ui/ (stored 0%)
  adding: ui/common/ (stored 0%)
  adding: ui/common/DetailView.js (deflated 37%)
  adding: ui/common/MasterView.js (deflated 53%)
  adding: ui/handheld/ (stored 0%)
  adding: ui/handheld/android/ (stored 0%)
  adding: ui/handheld/android/ApplicationWindow.js (deflated 55%)
  adding: ui/handheld/ios/ (stored 0%)
  adding: ui/handheld/ios/ApplicationWindow.js (deflated 59%)
  adding: ui/handheld/mobileweb/ (stored 0%)
  adding: ui/handheld/mobileweb/ApplicationWindow.js (deflated 59%)
  adding: ui/tablet/ (stored 0%)
  adding: ui/tablet/ApplicationWindow.js (deflated 57%)
--2012-04-01 20:36:06--  http://localhost:3000/
Resolving localhost... ::1, 127.0.0.1, fe80::1
Connecting to localhost|::1|:3000... failed: Connection refused.
Connecting to localhost|127.0.0.1|:3000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2 [text/html]
Saving to: `index.html'

100%[======================================>] 2           --.-K/s   in 0s      

2012-04-01 20:36:06 (195 KB/s) - `index.html' saved [2/2]

このようにTitanium Studioでbuildアクションをしなくても、アプリケーション自体を複数端末に一気に転送できることになります。*4

ひとまずまとめ

プラットフォーム差や機種間の実装差といったところをベースにしたテストやトライアンドエラーというのがTiでの開発のなかで占める時間も多いと思われますが、そういった作業の中で地味でかつ、一番コストとして跳ね返ってくるのが転送時間の待ちです。

もちろんTiShadowの配下に入れて動かす以上、別のクセに惑わされる部分があることは間違いないのですが、プロトタイプ開発やデモ・レビュー時にその場でUIや色味の調整を実機ベースでしかも複数端末で検証できるというのは夢のようなことではないでしょうか?

いくら迅速に開発できるということがウリのTiでもこの辺りは分単位の待ち時間を避けられない状態でしたが、TiShadowによってこの足枷が外れ、スタートダッシュがより加速するのではないかと考えています。

発展途上ではありますが、Titaniumでこれまでアプリ開発を経験された方にこそ是非一度触って評価して頂きたいプロダクトなので、ご紹介させてもらいました。

5月の購入予定

久々の30冊未満でちょっと一安心(^^;

  • 05/02 バクマン。 18/小畑 健/大場 つぐみ
  • 05/02 ニセコイ 1/古味 直志
  • 05/02 1/11じゅういちぶんのいち 3/中村 尚儁
  • 05/02 ニュースになりたいっ! 2/杜野 亜希
  • 05/02 パラダイス パイレーツ 1/山口 美由紀
  • 05/02 図書館戦争 LOVE&WAR 9/弓 きいろ/有川 浩
  • 05/07 ベツ×バラ 3/曙 はる
  • 05/08 午前3時の不協和音/ねむ ようこ
  • 05/10 失恋ショコラティエ 5/水城 せとな
  • 05/11 君に届け 16/椎名 軽穂
  • 05/11 アオイホノオ 8/島本 和彦
  • 05/11 タケヲちゃん物怪録 1/とよ田 みのる
  • 05/11 よと田みのる短編集 CATCH&THROW/とよ田 みのる
  • 05/14 乙嫁語り 4/森 薫
  • 05/14 新 部活動/西田 理英
  • 05/16 青春しょんぼりクラブ 3/アサダニッキ
  • 05/16 新☆再生縁 4 ―明王朝宮廷物語―/滝口 琳々
  • 05/16 ハルカの陶 3/西崎 泰正/ディスク・ふらい
  • 05/17 四月は君の嘘 3/新川 直司
  • 05/23 少年ノート 3/鎌谷 悠希
  • 05/23 少女ファイト 9/日本橋 ヨヲコ
  • 05/23 きのう何食べた? 6/よしなが ふみ
  • 05/25 ボクラノキセキ 限定版 6/久米田 夏緒
  • 05/25 千歳ヲチコチ 2/D・キッサン
  • 05/25 放浪息子 13/志村 貴子
  • 05/25 ゲノム金/古賀 亮一
  • 05/25 ゲノム銀/古賀 亮一
  • 05/30 あさひなぐ 5/こざき 亜衣
  • 05/下 101人目のアリス 6/かわい 千草

*1:たいしゃどうと読むようです

*2:敷居を上げるため、このあたりの説明を少し端折っています。申し訳ありません

*3:とりあえずiOSシミュレータiPhone4S+003Zでは実験済

*4:部分更新のためにtishadow updateという引数を付けての実行も可能ですが、Titanium Studioの標準フォルダではスペース付きのフォルダ名になるため、(現時点では)動きませんし、そうでないフォルダに置いてもぼくの環境ではうまいこと動かない(^^;