2010年02月27日
Appcelerator Titanium MobileでiPhoneアプリ開発を始めよう!!(改)
(追記:2010/02/28 17:30)http://code.google.com/p/titanium-mobile-doc-ja/wiki/get_started に転記しました。
注意
本稿の記述内容を試すにはMac OSX 10.5以上が動作する端末、iPhone SDK 3.1以上が必要になります。Windowsでは開発はできませんのでご注意ください。
また(本稿ではそこまで行きませんが)実機での動作検証・AppStoreへのアプリケーションの登録配布にはiPhone Developer Programへの参加(有償)が必要となります。
なお、Appcelerator Titanium Mobileは本文中でも触れている通りAndroid向けの開発も可能ですが、iPhone向けの開発にフォーカスして記述されていますので、その点ご容赦ください。
Appcelerator Titanium Mobileについて
Appcelerator Titanium Mobile(以下、Titanium Mobile)*1とはAppcelerator社が提供するモバイルデバイス向けのソフトウェア開発環境です。
プログラミング言語としてはJavaScriptのみを利用します。
それだけでiPhone/Android向けのネイティブアプリケーションを開発できることがウリとなっています。
Objective-CやJavaでコーディングする必要は一切ありません。
もちろんJavaScriptだからといってWebインタフェイスのみをサポートしているわけではありません。
以下に挙げる全ての機能を実現できるようになっています。
- ラベル・テキスト入力・ボタン・スライダーなどの豊富なネイティブUI部品
- 地図表示
- 画像・動画の再生・撮影・録画
- ファイルシステム
- ネットワーク通信
- ハードウェアデバイス(カメラ・GPS・電子コンパス・加速度センサ)の利用
- デバイス内データベース(連絡先など)の操作
- SQLiteデータベースのI/O
プラットフォームに依存した機能を利用しない限り、基本的にサポートされるプラットフォーム全てに対してにコードを転用できると謳われていますので、JavaScriptによる開発効率の向上だけではなくマルチプラットフォーム展開を少ないコストで実現できることも魅力のひとつとなっています。
現時点で対応しているプラットフォームとしては前掲したiPhone OSとAndroidのみになりますが、今後も追加されていく予定があります。*2
また本稿では取り上げませんが、兄弟製品としてTitanium Desktopがあり、こちらはWindows, Mac OSX, Linuxというマルチプラットフォームで動作するデスクトップアプリケーションを開発できる環境も提供されています。*3
前提環境(iPhone SDK)
Titanium Mobile自体はTitanium DeveloperというDesktop, Mobileでそれぞれ共用する開発環境を利用します。TItanium Developerの動作するプラットフォームとして、Windows, Mac OSX, Linuxをサポートしています。
しかし本稿で取り上げるiPhoneアプリケーションの開発に関してはiPhone SDKが必要になります。
そのため必然的に動作する環境としては Mac OSXのみとなってしまいます。
その点、ご注意ください。
iPhone SDKのインストールについて
Titanium Mobileでの開発を始める前に、上記のようにiPhone SDKのインストールを行っておく必要があります。
このSDKのセットアップから開発環境構築については下記記事をご参照ください。
また、本稿では取り上げませんが、実機での動作検証(ならびにAppStoreでの配布)を行うためにはiPhone Developer Programへの登録が必要となります。
それについては次の記事をご参照ください。
エディタの準備
私も最初勘違いしていたのですが、Titanium DeveloperはIDEではありません。
むしろビルド専用環境といってもいいフロントエンドプログラムなので、ソースプログラムの修正すらできません。
なんらかのエディタを準備してください。
Appceleratorの中の人たちはTextMateを使ってるようですが、エディタなら何でも構いません。
手になじんだエディタをご用意ください。
できればJavaScriptの文法ハイライト機能や入力支援があるソフトの方が開発効率もグンとあがると思います。
ちなみに私はCarbon Emacs + JS2環境で開発をしています。
Titanium Developerのインストールと起動
こちらのページを開くと自動的にインストーライメージファイル(Titanium Developer.dmg)をダウンロード開始しますので、完了後インストールしてください。
アプリケーションとしては「Titanium Developer」としてインストールされます。
(註記)0.9.2について
現在リリースされているTitanium Mobile 0.9.2については手動でzip形式で配布されているパッケージを所定のパスにコピーする必要があります。
- mobilesdk-0.9.2-osx.zipをダウンロードします。(7.49MBぐらい)
- ZIPファイルを展開して、Finderなどで/Library/Application Support/Titaniumフォルダにコピーします。
- Titanium Developerを起動すると、Mobile SDKの選択肢として0.9.2が追加されます。(すでに立ち上がっている場合は再起動する)
起動画面
インストール後にTitanium Developer起動すると、次のような画面が表示されます。
Titaniumを使うに当たって、この画面でアカウントを作る必要があります。
登録しないとTitanium Developer環境が利用できませんので必ず登録してください。
入れる情報としてはログインIDとなるメールアドレスとパスワード、姓名といった個人情報です。
(twitter idをいれておくと勝手に公式アカウントがフォローしてくれます)
ここで登録したアカウントでAppceleratorのサポートページなどへのログインにも利用します。
アカウント作成が完了すると、Titanium Developerの新規プロジェクト作成画面を開きます。
ここから、新規プロジェクトを作成したり、既存のプロジェクトをインポートできます。
アプリケーション終了/(Titanium Developer上での)ログアウト後はログインタブに切り替え、登録したメールアドレスとパスワードを入力して、立ち上げる流れになります。
KitchenSinkを触ってみる〜iPhoneシミュレータの起動
さて、いきなりHello, world的なプログラムを始めたい…と言いたいところですが、まずは開発元のAppceleratorから提供されているデモアプリケーション「KitchenSink」を利用して、アプリケーションのビルドから動作確認(iPhoneシミュレータ上で、ですが)の流れを体験したいと思います。
KitchenSinkはTitanium MobileのUI部品、APIのカテゴリ単位に機能を個別に紹介した機能カタログ的なアプリケーションです。
実際にTitanium Mobileで開発を始めると「KitchenSinkのこれと同じようなことをやりたい」ということが多々出てくると思いますが、APIリファレンスをひも解くよりも、KitchenSinkの該当部分のソースをコードスニペットとして利用するほうが早かったりします。実際のソースファイルの中身を見ていくのは本稿の最後にしたいとおもいます。
KitchenSinkをダウンロードする
KitchenSinkだけではなく、Appceleratorの製品はオープンソースソフトウェアとして開発がされており、ソースコードはgithubのレポジトリで公開されています。
KitchenSinkも同様にgithubで公開されています。
http://github.com/appcelerator/KitchenSink
まず上記リンクにアクセスし、githubの右上「Download Source」を選択します。
続いて表示される画面でzipアイコンか、tarアイコンのいずれかを選択し、ダウンロードします。完了後、展開してください。
(註記)0.9.2では個別にダウンロードする必要があります。
以下のアドレスから直接ダウンロードしてください。
http://timobile.appcelerator.com.s3.amazonaws.com/KS-0.9.2.zip
KitchenSinkを動かす
続いて、KitchenSinkプロジェクトをTitanium Developerに取り込みます。
Titanium Developerのツールバー「Import Project」を選択して、先ほど展開した先の /demos/KitchenSink フォルダを選択後「OK」ボタンをクリックすると、KitchenSinkプロジェクトがPROJECTS一覧に追加され、プロジェクト設定の編集画面が表示されます。
続いて、画面上部中央の「Test & Package」を選択すると、処理選択が表示されます。
(Android SDKを登録していないと、Run Android Emulatorは表示されません)
ここで「Run iPhone Emulator」を選択すると、無味乾燥な画面が表示されます。
画面中央を陣取る黒い部分は実行時のログ表示部になります。
ログレベルによって、情報であったりエラーメッセージが表示されたりします。
画面下部には使用するSDKのバージョンやログレベルを選択するコンボボックスとシミュレータの起動と終了をするためのボタンが付いています。
「Launch App」(ウィンドウ下部左側のボタン)をクリックすると、ビルドが開始されます。マシンスペックなどにも依存しますが、初回時(とTitanium Developerの立ち上げ直後)は比較的ビルド時間がかかる傾向があるようです。
表示内容を見ていただけば、内部でXcodeのコンパイラを呼び出しておりiPhoneネイティブのバイナリに変換しているということが分かっていただけのではないでしょうか。
そして、自動的にiPhoneシミュレータが起動し、ビルドされたアプリケーションもまた自動で起動します。
あれこれ言うより実際にシミュレータ上のデモを見て、どのようなことがTitanium Mobileで実現できるかを体感してください。*4
テストプロジェクトの作成からプロジェクト作成後のフォルダ構成
さて、KitchenSinkの体験は一旦終了して、実際にプログラムしていきましょう。
プロジェクトの作成
まずはプロジェクトの新規作成をします。
Titanium Developerのツールバーから「New Project」をクリックすると、New Project画面が立ち上がるので、必ずProject typeをデフォルトの「Desktop」から「Mobile」にするようにしてください。(Mobileに切り替えた後、iPhone SDKとAndroid SDKの検出を行うため、切替え直後、画面の下部のInstalled Mobile Platformsは緑チェックマークではありません)
ここではひとまずサンプルなので次のように入れてみましょう。
項目 | 設定値 | 補足 |
---|---|---|
Project type | Mobile | モバイルデバイス向けの際は必ずMobileを選択します |
Name | GetStarted | アプリケーションの名前です。残念ながら日本語文字を入れると現バージョンではビルド時にエラーになります。また長すぎる名前をつけるとホーム画面で「…」で省略されるので注意しましょう |
App Id | com.yourdomain.applicationname | アプリケーションを一意に判別するためのIDです。Javaの名前空間のようにドメイン名を反転させた名前の付け方をすることが推奨されています。(例:com.twitter.your_id.testapp) |
Directory | /Users/your_account | ソースの生成先フォルダ。このフォルダに上記Nameで指定した名前のフォルダが作られます |
Company / Personal URL | http://www.yourdomain.com/ | Publisher URLという項目に反映されます |
Titanium SDK version | 0.9.2 | 特段の問題がない限り、デフォルトになっている最新バージョンを使います |
JS Libraries (optional) | 何も選択しない | ここでは選択していませんが、jQueryなどを使いたい場合これを選択します。*5 |
そして「Create Project」ボタンをクリックすると、ひな形に基づいたフォルダ・ファイル群が Directory/Name なフォルダに自動生成され、画面もプロジェクト編集画面に遷移します。
このプロジェクト編集画面の上部にあるパス名(終端は省略されてますが)をクリックすると、Finderが起動し、該当フォルダを開いてくれます。
プロジェクトのフォルダ構成
それぞれについて代表的なものをかなり簡単に説明します。
manifest | アプリケーション定義が記述されています。 |
tiapp.xml | こちらもアプリケーション定義がされています。 |
/build | ビルド結果を格納するフォルダ。直接触る事はあまりないはずです |
/Resources | 実際のアプリケーション開発をするソースなどはここに格納します |
/Resources/app.js | アプリケーションのエントリポイントです |
/Resources/andoroid | Andoroid向けに依存したソース・リソースを格納します |
/Resources/iphone | iPhone向けに依存したソース・リソースを格納します |
一部の例外を除き、プロジェクト編集画面で設定できる内容なので、本稿では触れません。
最後のふたつに付いてはビルド時に一時的にiPhone用は/Resourcesに/Resources/iphoneをマージされた(Androidも同様)状態とすることで、機種依存機能を吸収できるようになっています。(上記状態ではiPhone用のスプラッシュスクリーン画像とアプリケーションアイコンが収納されています)
ちなみに実行すると...
次のようなシンプルな画面が立ち上がります。
すでにKitchenSinkの動きを見てる我々にはいささかツライというかツマラナイと感じるかもしれません。
app.jsからすべてはじまる
Titanium MobileのアプリケーションはすべてResources/app.jsから起動されます。
app.jsを見る
実際に生成されたソースコードを見てみましょう。(空行を間引いています)
// this sets the background color of the master UIView (when there are no windows/tab groups on it) Titanium.UI.setBackgroundColor('#000'); // create tab group var tabGroup = Titanium.UI.createTabGroup(); // create base UI tab and root window var win1 = Titanium.UI.createWindow({ title:'Tab 1', backgroundColor:'#fff' }); var tab1 = Titanium.UI.createTab({ icon:'KS_nav_views.png', title:'Tab 1', window:win1 }); var label1 = Titanium.UI.createLabel({ color:'#999', text:'I am Window 1', font:{fontSize:20,fontFamily:'Helvetica Neue'} }); win1.add(label1); // create controls tab and root window var win2 = Titanium.UI.createWindow({ title:'Tab 2', backgroundColor:'#fff' }); var tab2 = Titanium.UI.createTab({ icon:'KS_nav_ui.png', title:'Tab 2', window:win2 }); var label2 = Titanium.UI.createLabel({ color:'#999', text:'I am Window 2', font:{fontSize:20,fontFamily:'Helvetica Neue'} }); win2.add(label2); // add tabs tabGroup.addTab(tab1); tabGroup.addTab(tab2); // open tab group tabGroup.open();
やっていることは次のような流れです。
- ベースの背景色を黒(#000)にする
- TabGroupを生成し、
- TabGroupを表示する
この結果、次のような親子関係になっています。
- app.js(MasterUIView)
- tabGroup
- tab1
- win1
- label1
- win1
- tab2
- win2
- label2
- win2
- tab1
- tabGroup
app.jsからwindow単位のJavaScriptファイルへの分離
このように画面生成・ロジック記述(そしてここには含まれませんがイベント処理)も含めてすべてJavaScriptで記述するというシンプルな思想によってTitanium Mobileアプリケーションは開発していくことになります。
とはいえ、このままではひたすらapp.jsが膨らんでいきますし、スコープ管理も大変ということになります。
そこでJavaScriptのファイルを切り出すことができます。
まず現状のtab1関連を再度抜き出してみます。
var win1 = Titanium.UI.createWindow({ title:'Tab 1', backgroundColor:'#fff' }); var tab1 = Titanium.UI.createTab({ icon:'KS_nav_views.png', title:'Tab 1', window:win1 }); var label1 = Titanium.UI.createLabel({ color:'#999', text:'I am Window 1', font:{fontSize:20,fontFamily:'Helvetica Neue'} }); win1.add(label1);
現在ラベルがひとつだからいいですが、複数のUI部品が混ざってくるとソースの可読性は一気に悪くなります。
そのため、上記ソースを次のように変えます。
var win1 = Titanium.UI.createWindow({ title:'Tab 1', backgroundColor:'#fff', url: 'win1.js' }); var tab1 = Titanium.UI.createTab({ icon:'KS_nav_views.png', title:'Tab 1', window:win1 });
変わったのはcreateWindowの引数にurlプロパティが追加されている部分、label1の定義とwin1への追加部分が削除されている部分です。
これによりwin1の表示時にwin1.jsという外部のJavaScriptファイルをロードし、実行するという流れになります。
呼び出される側のwin1.jsを同じ Resorces フォルダに作成します。内容は次のようになります。
// win1.js var label1 = Titanium.UI.createLabel({ color:'#999', text:'I am Window 1', font:{fontSize:20,fontFamily:'Helvetica Neue'} }); Titanium.UI.currentWindow.add(label1);
win1.jsで新しく登場したのがTitanium.UI.currentWindowというプロパティです。
win1.jsを評価している最中の currentWindow とはすなわち app.js における win1 なので、ここには win1 のオブジェクトがセットされます。
そのため最終的な結果は同じようになります。*6
このようにwindow単位でjsファイルを分割していくと、処理と画面をコンパクトに記述でき、また管理もしやすくなります。
部品配置とイベントリスナへの登録
もう少し win1.js に画面部品を追加してしていこうと思います。
// よく使うのでこのように再定義しておくと便利です。 var win = Titanium.UI.currentWindow; // 一段Viewを間に挟むようにします。 var view = Ti.UI.createView(); // label1に表示位置の指定を追加します。 var label1 = Titanium.UI.createLabel({ color:'#999', text:'I am Window 1', font:{fontSize:20,fontFamily:'Helvetica Neue'}, height: 32, width: 200, top:80 }); // button1を生成します。 var button1 = Ti.UI.createButton({ title: 'touch me', height: 32, width: 120, top: 120 }); // win←viewに部品を追加します view.add(label1); view.add(button1); win.add(view); // ボタンクリック時のイベント button1.addEventListener('click', function(){ Titanium.UI.createAlertDialog({ title: 'タイトル', message: 'クリックされました' }).show(); });
ボタンを一つ追加し、そのクリックイベントを定義してみました。
幅や高さを指定しないと目一杯取られたりする点だけ注意しましょう。
またイベントリスナの登録については(一部の例外をのぞき)次のように記述されます。
object.addEventListener('EVENT_NAME', function(event){ // コールバック無名関数 });
まずはwin2側もjsファイル化してみて、同じようにボタンをいくつか配置してみて慣れてみましょう。
Tinitanium MobileでサポートされているUI部品の紹介
基本的にiPhone SDKのUIKitでサポートされているものがベースとなります。
そこから離れた描画などは現時点ではあまり得意ではなさそうですが、今後OpenGLへの対応がモジュール的にされそうではあります。
ともあれ、どのようなものがサポートされているかを駆け足になりますがご紹介していこうと思います。
BaseUI - TabGroup → Tab → Window
TabGroupとは次の画像で画面下部の黒背景でアイコンが並んでいる部分を総称します。
TabGroupには複数のTabを所属させる事ができます。Tab自体はTabGroup上のアイコンとして表現され、その実態はそれぞれのTabが保有するWindowになるという入れ子構造になっています。
上記の例ではTabGroupには5つのTabがあり、そのうち一番左に位置する"Base UI"というタイトルの付いているTabが選択されており、TabGroupの上方に表示されているのは"Base UI"Tabが保有するWindowであるという状態になります。
ちなみにapp.jsでTabGroupを宣言せず、いきなりWindowを生成し表示する事も可能です。
その場合は画面上にTabGroupはもちろん表示されずにWindowのみが表示されるようになります。
//app.js var win1 = Titanium.UI.createWindow({ title:'Tab 1', backgroundColor:'#fff' }); var label1 = Titanium.UI.createLabel({ color:'#999', text:'I am Window 1', font:{fontSize:20,fontFamily:'Helvetica Neue'} }); win1.add(label1); win1.open();
BaseUI - Dialog
対話式のボタン選択画面としてTitanium Mobileでは2種類のDialogを持っています。
Alert Dialogはこのような表示であり、
Options Dialogはこのような表示になります。
それぞれclickイベントでボタンのindexを返すため処理の分岐を行う事ができます。
また、Email作成用の専用ダイアログが別途用意されています。
Email Dialog
BaseUI - Statusbar, NavBar, Toolbar
まず一番上の電波状態や時刻などが表示されている部分がStatusbarといいます。
Statusbar自体はあまりプログラム的な制御をかけることができません。可能なのは3種類の表示色のいずれかを選択するか、表示させないかの否かの制御だけです。
続いて「Window Constructor」やドクロアイコンなどが並んでいる場所がNavbarといいます。
NavbarにはLeftButton、Title、RightButtonの三つのエリアがあり、それぞれ部品を配置できます。Buttonと称していますがButtonでなくても別に構いません。
そしてTabGroupの上に「Left」「Right」というボタンが並んでいる部分がToolbarです。
ちなみにiPhoneではUIのデザインについて基準を提示しており、それに適していない画面設計をしているとAppStoreの審査でrejectされることがありますので、そういったことも画面作成時に意識する必要があります。
BaseUI - Views
Viewは(原則的に)Windowの内側に配置される表示部です。
場合によってはViewを含む他のコントロールのコンテナ(親)になります。
Views - CoverflowView
画像を左右にスクロールさせながら拡大表示するカバーフローもこのViewを利用すれば、画像の配列を渡すだけで簡単に実現できます。
Views - WebView
純粋にHTMLサイトを表示するためのViewです。
safariアプリで開けるサイト/情報はすべて表示できると考えてください。
また直接HTML文字列を引き渡す事も可能ですので、動的に生成したHTMLによる多彩な表現をすることができます。
Views - TableView
TableViewは出来る事が多岐にわたっているため、大変奥が深いものになっています。
このような端的な行選択だけでなく...
このように各行に対するレイアウトデザインすることも可能です。
また、「設定」画面のようなグループ表示もTableViewの一環としてサポートされていますので、作法もTableViewに則る必要があったりします。
Views - ScrollView
スクロール可能なViewです。スワイプやボタンによるアクションでスクロールさせることが可能になります。
Views - ImageView
画像表示が可能なViewです。画像のアニメーションもさせることができます。
Views - MapView
地図表示が可能なViewです。単体では下の例のようなツールバーはついていません。
Controls - Label
文字を表示するコントロールですが、clickイベントも受け取る事が出来るので疑似的なボタンとしての活用も可能です。
Controls - Button/SystemButtons
ボタンを表示するコントロールです。文字表示だけではなくアイコン表示も可能です。
一部の規定のアイコンを使用する場合はSystemBottons列挙体で宣言されている定数を利用する形になります。(下の例ではNavbarやToolbarに使用されている画像がそれにあたります)
Controls - TextField
テキスト入力(1行)をするためのコントロールです。多岐にわたる初期設定により随分表情の変わるコントロールだと言えるでしょう。
Controls - TextArea
TextFieldに比べると若干設定可能な内容は減ります。
Controls - Switch
ON/OFFの切り替えのみを行うコントロールです。主に設定画面で使う形になるでしょうか。
Controls - TabbedBar
こちらはON/OFFに限らない状態を切り替えるコントロールです。(iPhone依存)
他のOSやWebアプリケーションにおけるラジオボタンと同等の位置づけと考えればよいでしょう。
Controls - ButtonBar(iPhone依存)
見た目はTabbedBarにそっくりですが、こちらは状態を持ちません。
ボタンの集合として利用します。NavbarやToolbarとの相性がよいと思われます。
Controls - Toolbar(iPhone依存)
Windowの直下にあるToolbarとは別に局所的な機能としてのToolbarになります。
キーボードツールバーはTextField/TextAreaでサポートされているので、いまいち使いどころが難しいかもしれませんが。
Controls - Slider
数値をアナログに指定するコントロール。ボリュームや数量などの値を指定するのに利用されます。
Controls - Picker
コンボボックスに相当する複数の候補から項目をドラム式に選択させるコントロールです。
項目が多すぎると正直使い勝手が悪いので、そういうときはTableViewなどで外に出せないか考慮する必要があるかもしれません。
Controls - SearchBar
検索用のツールバーです。大体TableViewなどとセットで登場するかたちになります。
Controls - ActivityIndicator
現在(なんらかの)処理中であることを示すアイコンとメッセージを表示するコントロール。ロード中など何かしているように動きをみせないとフリーズしているようにしか見えないから要注意とかつてログインで木屋さんが言っていた気がします(古すぎる)。
Controls - Progress Bar
進捗表示を行うコントロールです。進捗を返すイベントリスナとセットで利用することになるでしょう。たとえば、ダウンロードやアップロードの状態を返すイベントなどと。
KitchenSinkを覗いてみる
「あのコントロールはどうやって配置するのか?」とか「もっと生成時の引数に指定がいろいろできるんじゃないのか」といった疑問が出てくると思います。
そんなときは初めに触ったKitchenSinkの中身(ソースプログラム)をみるのが一番のお勉強になります。
まずはapp.jsを開き、そこから辿っていってもいいのですが、/Resources/examplesフォルダ内に各jsファイルがそれなりのキーワードで転がっていることが分かると思います。UI部品ならその部品名で見たり、あるいはcameraやnetworkといったキーワードベースで見る事もできるでしょう。
コードサンプルとして積極的に活用しましょう。
*1:ちなみにTitaniumは「チタニウム」ではなく「タイタニウム」と発音するようです
*3:これについては http://d.hatena.ne.jp/yuichi_katahira/searchdiary?word=*[Titanium] の記事群が詳しいですので、興味があればぜひご覧ください
*4:残念ながらデバイスハードウェア系(カメラ・加速度センサ・GPS・電子コンパスなど)を中心にiPhoneシミュレータでの動作がサポートされていない機能は使用できません。実機に転送する必要がありますが、本稿では触れません
*5:prototype.jsはなぜかビルド時にエラーになってしまうので選択しない事を現状おすすめせざるを得ません
- 202 http://fxb.jp/archives/000656.html
- 42 http://www.google.co.jp/search?sourceid=chrome&ie=UTF-8&q=titanium+iphone+sdk
- 36 http://www.google.co.jp/search?hl=ja&q=チタニウム iPhone+android&btnG=検索&lr=&aq=f&oq=
- 34 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rlz=1T4GGIH_jaJP214JP214&q=Titanium+iphone
- 32 http://www.google.co.jp/search?hl=ja&client=safari&rls=en&q=iphone+複数のビューをwindowsのタブのような&btnG=検索&lr=lang_ja&aq=f&oq=
- 32 http://www.google.co.jp/search?q=Titanium+iphone&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja-JP-mac:official&hl=ja&client=firefox-a
- 31 http://www.google.co.jp/search?q=iphone+titanium&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja-JP-mac:official&hl=ja&client=firefox-a
- 28 http://www.google.co.jp/search?q=チタニウム+iphone+android&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja:official&hl=ja&client=firefox-a
- 26 http://www.google.co.jp/search?hl=ja&lr=lang_ja&tbs=lr:lang_1ja&q=Appcelerator+Titanium ダウンロード&aq=f&aqi=&aql=&oq=&gs_rfai=
- 25 http://www.google.co.jp/search?hl=ja&client=firefox-a&rls=org.mozilla:ja:official&q=Titanium+iphone&btnG=検索&lr=lang_ja&aq=f&oq=