2012-02-02
■[Titanium Mobile]どのようにbuildされるのか考察してみた
ここ数日睡眠リズムが良くないから本調子でないことに加えて、根本原因探るのに行き詰まっていることもあって、気分転換にブログ書くことにしました。
どのようにbuildされるのか考察したまとめ
Python&Objective-Cをそんなに理解してないですが、メソッド名頼りに流れを追ってみた結果、おそらくこんな感じでbuildされているんじゃないかと思います
- titanium.pyで実行に必要なパラメータチェックを(たぶん)実行。問題なければiphone/builder.py(もしくはandroid/builder.py)が実行される
- builder.pyが実行されて、main.mが自動生成されているはず(builder.py1500行近くあるので後日がんばって触れたい)
- main.mの情報を参照しつつ、雛形となるファイルをプロジェクト配下の/build/iphone/Classes/以下にファイルを生成していく
※以下はまとめと関係ないですが、ちょっと戯言を※
「そもそもソースコードってどうやって読み進めるんだろう?」という漠然とした疑問がありました。
2,3年位前だとファイルを1行1行くまなく読んでいこうとしていた時期もあったのですが、それだと”木を見て森を見ず”の状態で結局概要がよくわからず、結局嫌になってしまったという苦い思い出が多々ありました。(職業プログラマとしての経験があればこのあたりのコツというのは仕事を通じて得る機会があるのかもしれませんね)
「周囲の人からソースコード嫁!って言われるけど、とっかかりが掴めない」
っていう人もいるんじゃないかと何となく思ったのと、もしかしたらTitanium勉強会を今後も継続していったとして、将来こういう話題も触れても面白いかもしれないので、どのようなことを考え、実践した結果、上記まとめにつながったのか、以下時系列に書いておこうと思います
そもそもコードを読む目的を見失わないようにした
「Titanium Mobileの内部構造理解すれば、どの部分でresourcesDirectoryの設定しているのかわかるんじゃないかなぁ」
という考えに至り、ひとまずTiFileのソースコードを追っかけてみることにしました。
と最後に触れているように、どの部分でresourcesDirectoryの設定しているのかを把握することが今回コードを読む目的として設定しました
まずはTiFile ざっくりと読んでみた
TiFileに着目した理由はファイル名からして、なんか関連ありそうと思ったので、正直根拠ないですww Objective-Cを正確に理解してないですが、ひとまずTi.File.mを開いたら以下のようなメソッドがありました
- (void)dealloc
- (id)initWithPath:(NSString*)path_
- (id)initWithTempFilePath:(NSString*)path_
- (NSString*)path
- (NSInteger)size
- (id)blob
- (id)toBlob:(id)args
- (TiFile*)createTempFile:(NSString*)extension
「メソッド名とかから推測するにdeallocはメモリ管理的な何かっぽい」
「initWithで始まるやつは、引数のpathが渡されてそれに対して何か初期化してるのかな」
「blobやとBlobは読み方がよくわからないけど、バイナリファイルを扱う時の何かかな?」
という感じで眺めてみて、
「あれ、このTi.Fileの中には見る限り、resourcesDirectoryやapplicationDirectoryのパスの情報が埋め込まれているわけじゃないんだ。そうなると、どっかで設定ファイルらしきものがあって、そのファイルを読み込む処理をこのTi.Fileが担ってるのかな」
という妄想を含まらせましたw
設定ファイルらしきものはそもそも何処にあるんだろう
今まであまり考えたことがなかったのですが、きっとそれらしいファイルがあるはずに違いないと思って少し探ってみました。
「そういえば、Titanium Studioでbuild実行するとプロジェクト配下の/build/iphone以下に色々ファイルが生成されるけど、この中のどれかが関連してそう」
と思って、チェックしていき、main.mを開くと
#import <UIKit/UIKit.h> #define _QUOTEME(x) #x #define STRING(x) _QUOTEME(x) NSString * const TI_APPLICATION_DEPLOYTYPE = @"development"; NSString * const TI_APPLICATION_ID = @"jpxxxx"; NSString * const TI_APPLICATION_PUBLISHER = @"xxx"; NSString * const TI_APPLICATION_URL = @"http://"; NSString * const TI_APPLICATION_NAME = @"asunaroViewer"; NSString * const TI_APPLICATION_VERSION = @"1.0"; NSString * const TI_APPLICATION_DESCRIPTION = @"not specified"; NSString * const TI_APPLICATION_COPYRIGHT = @"2012 by xxxx"; NSString * const TI_APPLICATION_GUID = @"03....."; BOOL const TI_APPLICATION_ANALYTICS = true; #ifdef TARGET_IPHONE_SIMULATOR NSString * const TI_APPLICATION_RESOURCE_DIR = @"/Users/xxxxx/project/Resources"; #endif
という感じで、自分が求めていた情報(NSString * const TI_APPLICATION_RESOURCE_DIR = @"/Users/xxxxx/project/Resources";)が見つかりましたー
このmain.mの先頭行に
WARNING: this is a generated file and should not be modified
とあるように、自動生成されてます。
このファイルを生成するスクリプトがどっかにあるはずで、
「あー、日頃ターミナルからtitanium -run ...とやってるわけだし、~/Library/Application Support/Titanium/mobilesdk/osx/1.7.5/titanium.pyが関係あるんだ」
とすぐわかりました。
titanium.pyを開き、自分自身Pythonそんなに知らないけど、ひとまずメソッド名を頼りにまずは全体を眺めました。
「titanium -run実行された際に該当しそうな runというそのものズバリなメソッドはない。def run_project_argsというので、引数チェックして、実際のrunに相当するのはdef dyn_run(args,project_cb,module_cbが該当しそう」
というおおまかな”あたり”をつけてif分がたくさんあるのを無視しつつ眺めていたら
if atype == 'project': script = os.path.join(template_dir,platform,'builder.py') cmdline = project_cb(args,script,project_dir,platform)
という箇所がわかり、ここでbuilder.pyが実行されるというのがわかりました
次回続くかも??
builder.pyでやってることは何となくわかるのですが、ちょっと行数多いので、この部分の処理をどのようにして追っていったのか次回まとめたいと思います。
2012-02-01
■[Titanium Mobile]TiFileのソースコードを読もうと思ったきっかけについて
前置き
前回こんなことを書いてから、しばらく以下2つのことを考えてました
- クローラで収集したデータをJSON化する時に適切な形でエスケープ処理する実装方法
- Ti.Database.openにも関連ありそうなTitanium.Filesystemの内部構造ってどうなってるんだろう
こんなことをつぶやいていたように前者は思った以上に苦戦しながら、ActiveSupport::JSON.encode()を利用することで期待する結果が得られそうな目処が立った気がします。
Ti.Database.openに関連する所でちょっとうまくいってないこともあるのですが実はそれだけではなくって、JSONDBのモジュールが実機ではうまくいってないことも重なって、Titanium.Filesystemの内部構造について把握したくなってきました
ちなみにJSONDBを使ってみたというエントリを読む以前にも、その存在が気になっていたJSONDBなのですが、先日のTitanium新年会のLTの中で取り上げられていてて
「これはもう利用しとかないと!」
と思って、別のモジュールも含めて購入しました(※ちなみに初めてモジュール買いました)
この辺りで少し触れている通りMongoDBをちょっとだけいじっていたこともあり、JSONDBはかなりMongoっぽく馴染み易く、簡単なサンプル作り、エミュレータ上で動作することを確認した上で、実機転送したら、アプリが落ちる・・
念のためTitaniumStudio上で新規にプロジェクト作っても同様の症状になりました。
File I/Oに関する処理がうまくいってない気がしてきた
この段階でふと思ったのは、SQLiteのファイルやJSONDBのファイルそれぞれが存在するパスの指定がなんか怪しい気がしてきました。
Titanium Mobileの機能を使って生成されるファイルの保存先のパスってどっかで指定出来たのかなという素朴な疑問が思いつき、ひとまず、ファイルI/Oに関するTitanium.Filesystemをひとまずいじってみました
var baseDir = Titanium.Filesystem.applicationSupportDirectory; var rootDir = Titanium.Filesystem.applicationDirectory; var resoce = Titanium.Filesystem.resourcesDirectory; Ti.API.info(resoce); Ti.API.info(baseDir); Ti.API.info(rootDir);
上記結果はこうなりましたが、resourcesDirectoryの結果が@donayamaさんがまとめているWikiの情報と違う結果になりました。
/Users/xxxx/production/asunaroViewer/Resources/ /Users/xxxx/Library/Application%20Support/iPhone%20Simulator/4.3.2/Applications/A196F63E-019F-4491-B10B-5B6B79DF5C10/Library/Application%20Support/ /Users/xxxx/Library/Application%20Support/iPhone%20Simulator/4.3.2/Applications/A196F63E-019F-4491-B10B-5B6B79DF5C10/Applications/
「Titanium Mobileの内部構造理解すれば、どの部分でresourcesDirectoryの設定しているのかわかるんじゃないかなぁ」
という考えに至り、ひとまずTiFileのソースコードを追っかけてみることにしました。
ObjectiveC全然わからないけど、メソッド名からなんとなくの処理を推測してコード読んでるので気が向いたら続きを書くかも
2012-01-28
■[Titanium Mobile][あすなろBLOG Reader][javascript]Ti.Database.open使って情報が読み取れない原因がわかりました
まずは現在困っていることのまとめ
うちの会社で運営しているあすなろBLOGのビューワーアプリを作っているのですが、過去エントリについてはRubyで書いたクローラ使って収集済。
そのため過去エントリについては、SQLite上にすべて突っ込んでおき、適宜そこから読み込むような処理にしようと思って実装したのですが、エミュレータでは表示されるものが、なぜか実機に転送すると表示されないという症状に出会ってずっと悩んでます
iPhoneEmulator上の結果
実機へ転送した結果
Ti.Database.open 使わずにTi.Database.installなら動作する
少し前ですが
エミュレータだと動作するのに、実機転送したらno such table:entries..っていうエラー吐いてアプリケーションエラーになる。TiDatabaseProxy.m:136というメッセージがこれ( http://bit.ly/ygU09w )と似た症状っぽいなぁ
Ti.Database.openじゃなくって、代わりにinstall を利用しつつ、念のためdatabase保存先をこちら参考( http://bit.ly/u2seuS )にしてコード書き換えたら実機でも動いた。
ということをつぶやいた通り、install使うと実機でも意図したように表示されます
原因追求になんとなくつながったヒント
TiDatabaseProxy.m:136 でググッていた中で
Problem Solved ! To generate the database I was using Firefox SQLite Manager and this addon was creating a Sqlite2 instead Sqlite3.
I had to create it by the command line (sqlite3 command).
というような一文をみつけて、これは自分とは違うから関係ないなぁーと思って、ひとまず気分転換のために、お風呂に入りました。
そしたら、神のお告げっていうわけじゃないwwけど、ふと
「そういえば、Rubyで書いたクローラからSQLite3にデータ保存したファイルを、/Users/xxxx/Library/Application Support/iPhone Simulator/4.3.2/Applications/xxx/Library/Application Support/database以下にコピペしてるけど、そのファイル形式とかに何か原因あるのかな」
ということを思いつき、ひとまずTitanium 側だけでSQLIteのデータベース生成、データ挿入、読み込み処理をすることができるか試すことにしました
var db = Ti.Database.open('blogData'); var blogData ={ post_date:'2006/07/03 00:51:00', json:'{"permalink":"http://blog.pasonatech.co.jp/kanazawa/202/1686.html","html_body":"<p>先週金曜日、この日は月一度の全体ミーティングだった。<br>\n各事業部からの報告や、新しい動きの発表がある。<br>\n自分の知らないところで、みんながいろんなことをやってる。<br>\n自分もこれから先、いろいろなことをやっていきたい。<br>\nだけど、現在はいまの作業をまだまだ勉強中。<br>\n会社のいろんな動きの中で、自分は何ができるんだろうか…と焦りを感じてしまう。</p>\n\n<p>そして、毎月MVPならぬMDP(Most Drecomtic Person)と言って、<br>\nもっとも\"ドリコムらしい活躍\"をした人が投票で選ばれる。<br>\nこの候補に選ばれる人はいつもすごい人ばかりだ。<br>\n新製品をメインで作った人、企画を成功させた人、営業ですごい結果を残した人、新卒で初めて受注を取った人・・。<br>\n自分はというと、それにはまだまだ程遠い。<br>\nそれがなんとももどかしい。<br>\n自分も早く人に認められる成果を上げたい。</p>\n\n<p>そんなに簡単に成果を上げられる訳ではないこととは知っていても、何か焦りを感じてしまいます。<br>\nだけど、これは周りの人の活躍が良い刺激になっているということでもあると思う。<br>\nそういう人たちをいつも見て、自分の目標も高く持てるというのはいいことだと思っています。</p>","title":"刺激と焦り","post_date":"2006/07/17 22:29:00","blogger":"kanazawa"}' }; db.execute('CREATE TABLE IF NOT EXISTS entries(post_date DATE, jsonData TEXT)'); db.execute( 'INSERT INTO entries (post_date,jsonData) VALUES(?,?)', blogData.post_date,blogData.json); var resultSet = db.execute('SELECT post_date, jsonData FROM entries order by post_date'); var arr = []; while (resultSet.isValidRow()){ arr.push(resultSet.fieldByName("jsonData")); resultSet.next(); } var result = "[" +arr.join(",") + "]"; Ti.API.info(result); db.close(); var list = eval(result);
根本的な原因はJSON文字列をSQLiteに保存する箇所のようでした
上記コード実行すると、
[ERROR] Script Error = { line = 1; message = "Parse error"; name = SyntaxError; sourceId = 150463928; }.
というエラーを吐いて落ちました・・なんで1行目でParse errorになるのか最初意味がわからなかったのですが、blogData.jsonをよくよく見たら、html_bodyの中で、ところどころ改行文字(\n)が含まれてて状態でeval() すればそこで改行されてしまい、結果Parse errorが生じているようでした。
そのため、改行文字(\n)だったり、「\"ドリコムらしい活躍\"」というようなダブルクォーテーションのエスケープ処理の所を編集して
var blogData ={ post_date:'2006/07/03 00:51:00', json:'{"permalink":"http://blog.pasonatech.co.jp/kanazawa/202/1686.html","html_body":"<p>先週金曜日、この日は月一度の全体ミーティングだった。<br>\n各事業部からの報告や、新しい動きの発表がある。<br>\n自分の知らないところで、みんながいろんなことをやってる。<br>\n自分もこれから先、いろいろなことをやっていきたい。<br>\nだけど、現在はいまの作業をまだまだ勉強中。<br>\n会社のいろんな動きの中で、自分は何ができるんだろうか…と焦りを感じてしまう。</p>\n\n<p>そして、毎月MVPならぬMDP(Most Drecomtic Person)と言って、<br>\nもっとも\"ドリコムらしい活躍\"をした人が投票で選ばれる。<br>\nこの候補に選ばれる人はいつもすごい人ばかりだ。<br>\n新製品をメインで作った人、企画を成功させた人、営業ですごい結果を残した人、新卒で初めて受注を取った人・・。<br>\n自分はというと、それにはまだまだ程遠い。<br>\nそれがなんとももどかしい。<br>\n自分も早く人に認められる成果を上げたい。</p>\n\n<p>そんなに簡単に成果を上げられる訳ではないこととは知っていても、何か焦りを感じてしまいます。<br>\nだけど、これは周りの人の活躍が良い刺激になっているということでもあると思う。<br>\nそういう人たちをいつも見て、自分の目標も高く持てるというのはいいことだと思っています。</p>","title":"刺激と焦り","post_date":"2006/07/17 22:29:00","blogger":"kanazawa"}' }; というデータをSQLiteに挿入→読取→TableViewに表示だと意図したように表示されましたー
実は以前に
色々悩んだ挙句、現時点でこういう形にしました。何も考えずにeval()するのって、なんとなく気持ち悪いがするので、入力値チェックしたほうが良さそう
ということを書いていた通りのことが起きてたわけですね(T_T)
今後
クローラで収集したデータをJSON化する時に適切な形でエスケープ処理する形で実装しなおし。それがうまくいけば、アプリリリースに向けてかなり前進しそうです
2012-01-23
■[Titanium Mobile]Ti.tokyo.GIG "Titanium新年会 2012"行って来ました
この週末、Ti.tokyo.GIG ”Titanium新年会 2012”参加しました。
まず最初にイベントの主宰された@kaz_konnoさんにお礼を言いたいと思います。ありがとう&おつかれさまでした!
イベント参加した感想を最初簡単に
Titanium新年会が1年前に行われた時の状況から比べるとこの1年でTitaniumをとりまく環境というか、興味を持って実際に何か作ってる人がどんどん増加しているなぁというのを実感。
自分の本業の仕事(人材派遣)の観点からすると、これだけの人が注目&実際にアプリのリリースをしている実績があるのと、近いうちに日本オフィスが立ち上がる点も考慮すると、今年はTitanium Mobileを使ってiPhone/Androidアプリ開発が出来る人材需要が顕在化するかなと感じてます
そのあたりを視野に入れつつ、今回のイベントの発表内容を聞いて色々刺激を受けたのでこれまで以上に、自分自身でもアプリ開発の趣味を本格化してしていこうかな決心しました
今回の新年会参加する前に読物語というアプリをリリースされた@loopunqoolさんと話が出来ればと思っていて、たまたま声をかけた人が、そうだったのでちょっとビックリしたw
覚えている範囲で当日の発表内容とか振り返る
会社がらみの別のイベントに行かないといけなかったので、発表内容を途中までしか聞けなかったのですが、覚えている範囲で振り返っておこうと思います。(@donayamaさんがもっと詳しいまとめ書いていたのでそちら読んだほうが良いですねw)
最初の挨拶
海外からのスペシャルゲストによるトークが最初ありました。
まず最初はAppcelerator CEO Jeffさん
続けてAppcelerator Titanium Smartphone App Development Cookbookの著者である Boydleeさん
最後にLearning Tiというサイトの運営に関わっているSharryさん。ちょっと前からこのサイトのことは知っていたのですが、上記サイトで、@donayamaさんの書籍が紹介されています
@kaz_konnoさんも最初の乾杯の挨拶された際に海外から日本のTitanium開発者コミュニティが注目されているというお話されていましたが、こういう形でわざわざビデオレターを提供してくださったことを見てもなるほどなぁーと実感
10年以上前だったら、こんなことが出来るとは全然想像もしなかったので、インターネットって凄いねw
@Seasons さん
Photobookというアプリのデモをまじえつつの発表。
これを聞いただけで、
「あー、今日途中までしかいれないけど、こういう話が聞けたし、参加してよかった」
って思いました。Ti.GIG.2012で執筆中&開発中のアプリについて発表してきました - Seasons.NETですでにまとめてくださってますが、このエントリで
JavaScriptオンリーでどこまでネイティブアプリっぽく見せれるか?
と書かれていました。
「TitaniumMobile使ってどんなものが作れるの」っていう人が身近にいた場合にまず最初にこれ紹介すれば、確実にモチベーションあがりそうな気がしますし、当日の発表でソースコード(と解説書籍も?)後日公開してくれるということなので、期待して待ってます!
@mochizさん
何気に一番お会いした方だったので、名刺交換しか出来なかったけど、お話出来てよかったなぁというのが感想。
ご自身が開発してきた中でのGood/Badについてお話されていましたが、結構Android向けの開発案件が多いのが印象に残りました。あとは自分も基本Emacs使って開発してるので開発環境に関する所で、CoffeeScript紹介されてましたが、その部分もうちょっと聞きたかったなぁ。
最近、Titaniumで、iPhone/iPad向けアプリのみ受託開発する会社を知人の方と立ちあげた話も含めて、もう少し色々突っ込んだ所聞いてみたいので、近いうちにランチでもご一緒しながらお話聞けるようにまずはアポ取ろうかと思ってます
@wangzhi さん
今回、静岡からご参加。
自分の会社の求人案件見てると、スマフォ向けのゲーム開発っていうのは割りとよく見かけるのですが、ゲーム開発って正直ピンとこない部分があったのですが、@wangzhi さんの「Titanium MobileでRPG製作」という発表内容を聞いて、とっかかりを掴めた感じがします。
RPG風なゲームアプリ作る上でのTIPSとか、サンプルアプリのソースとか公開してくれたらと密かに期待してます
@k0sukey さん
@wangzhi さんと同じ会社で、Appcelerator CEO Jeff Haynie 来日記念 meetup!!でLTされていた方というのがすぐ思い出せたのですが、ATNDカレンダー作った方だったのは気づかなかった。
発表内容は、上記のATNDカレンダーじゃなく、今作ってるアプリについての話でしたが、その中でjsondb(詳しくはこちら)を紹介されてて、ちょっと前から使おうかどうか迷っていたのですが、今回の話を聞いて、なんとなく背中を押されてポチりましたw
静岡でもTiの勉強会したいって最後お話されていたので、予算的に行けそうなら考えようかな。
※予定では、今朝からこれまでSQLite使っていた処理をjsondbに置き換えようと考えていたのですがこのブログ書いてて時間が無くなった・・
2012-01-07
■[Titanium Mobile]GitHubViewer作ることにしました
前回書いた所から試行錯誤して出来そうなこと・課題について大分わかってきたのでまとめておこうと思います
出来そうな事
- GitHubでフォローしている人の一覧表示
- 自分で用意したサーバでGitHub上のソースをgit cloneした上でctagsでタグ生成
- ctagsのPython wrapperなpyctags使いつつTitaniumMobile上で処理しやすい形式のJSONを生成
- ソースコード上のタグをタッチすると該当行にジャンプ
一番最後に書いたタグジャンプの所ですが前回
Titanium.UI.WebView+google-code-prettifyを使ってソースコードのシンタックスハイライトは出来そうだけど、タグタッチをした時に該当行に飛ぶっていう処理をどうやって実装すればいいんだろう。。
と書いていましたが、サーバ側で以下のようなRubyのスクリプトで処理出来ます
※CodeRayが必要になります。
require 'rubygems' require 'coderay' data = CodeRay.scan(File.read('/path/to/sample.js'),:javascript).page file = File.open('/path/to/output/sample.html','w') file.write(data) file.close
上記RubyスクリプトをひとまずPCのブラウザ上で表示すると↓このような感じになります。
各行の先頭に1からの連番の数字が自動的に割り振られて、数値をクリックするとその行に自動的にスクロールしてくれるJavaScript含めた形のHTML/CSSがCodeRayで生成されます
試しにローカルのMac上にあったmofmof-jsを上記のスクリプトを使ってHTML生成&一部CSSを手作業で修正したものをTitaniumのWebViewにて表示させたのが↓これになります
課題
ここまでの段階でひとまず実機(iPodTouchの第4世代)に転送して、4000行超えるソースコードの表示をさせたのですが、最初に表示されるまでに時間がかかり、表示した後のスクロールもサクサクしているとは言えませんでした。
関数単位でHTMLファイルの生成が出来ればこの問題も解消しそうなのですがその実現方法は全く思いついていません。
細かい課題も他にもありそうですが、ここまで試行錯誤してみてなんとなく作れそうな手応えは得られてきましたので、本格的に作っていくことにします。







