もぎゃろぐで“TitaniumMobile”タグの付いているブログ記事

この記事は、Titanium mobile "early" Advent Calendar 2012の提供でお送りしております。

Titanium Mobileのおかげで、iPhoneとAndroid両にらみでアプリ開発することが現実的になったのはいいのですけど、どちらも機種が増える一方なので、画像ファイルの準備が洒落にならなくなりつつあります。
最低限必須となるアイコンとスプラッシュスクリーンだけで50種類!

Titaniumで用意する画像のサイズ - Sawalog

とはいえ、実際にはほとんど同じ画像がサイズの違うキャンバスに貼り付けてあるだけなので、自動化することにしました。 tiqiita.png

最大で1024pxの画像を57pxまで圧縮することになるので、ビットマップやpng画像をそのまま縮小すると目も当てられない画像になってしまいます。そこで、デザイナさんにはillustratorのベクター画像で納品をお願いすることにしました。
illustratorの「Webおよびデバイス用に保存」機能を使うと、作成していただいた画像をSVGフォーマットで出力することが出来ます。 illustrator.png

SVGは、ベクターグラフィックスなので縮小してもつぶれない、たいていのブラウザでも開くことが出来るなど、期待される要素がたくさんある割にはちっとも日の目を見ないフォーマットですが、それはさておき、プログラマ御用達の画像処理ツールImageMagickやそのRubyバインディングであるRMagickで扱うことが出来ます。

というわけでRubyで書いたコードがこちら。icon.svgとsplash_screen.svgを元に、必要なサイズに拡大縮小、背景は指定した色で塗りつぶした画像を一気に生成します。

こういうのを用意しておけば、「iPhone6が発売されたので新しい解像度の画像が必要」というときでも、プログラマレベルで片付けることが出来るので便利ですよね。

ただこの手法にはちょっと難点があって。ドロップシャドウとか非表示レイヤーなんかはImageMagickがついてこれないのでぐちゃぐちゃになってしまうことがあります。パスで描かれた単純な画像しか適用できないのが辛いので、最近はPhotoShopのアクション機能で出力するほうがいいのかなーとか考えています。そのへんも手法が確立したらそのうちブログで書こうと思います。



Androidアプリ with TitaniumMobileに挑戦中。iPhoneだと動くコードが動かない理不尽さを見ていると、HTMLを書いてIE6で見ると崩れまくっていたあの頃を思い出しますね。
さて、そんなandroidでは、解像度の異なる端末に対応するため、数値はdip指定するのが原則です。
  • New Defaults for Android Layouts in 1.7 « Appcelerator Developer Center
  • Y.A.M の 雑記帳: Android multi screen 対応
  • ところが、view.animateとか、scrollView.setContentOffsetのように構造体をとる関数はたいていdp表記に未対応で、pixel単位で指定してあげる必要があります。変換関数が必要!

    このあたりのことはこの記事で解説されていて、
    TitaniumMobileのハマりポイントとお作法メモ at HouseTect, JavaScriptな情報をあなたに
    dpとpixclの変換関数なんかも提案されているのですけど、用途と合わなかったので、俺バージョンを作りました。
    元コードとの違いは
    • View.widthなどで取得できる '100dp'などの記述をそのまま渡せるようにした
    • 同様に、view.widthにそのまま渡すことを意識して、dpは'100dp'みたいな文字列で返すようにした
    というあたりです。


    jhmr.gif

    PHPな人が集まって一晩中開発を行うイベントPHP祭りに行って来ました。

    「mogyaさんPHP祭りは来ないの?」
    「最近PHPは全然書いてないのでノーチェックですねぇ。」
    増井さんを呼んでTitaniumの話をしてもらうよ」
    「今申し込みました(即答)」
    というような経緯です。

    実際行ってみたら、
    masuidrive「この中で、Titaniumをご存知のかた?」(挙手)
    masuidrive「Titaniumでプログラムを書いたことがある方」(挙手)
    masuidrive「Titaniumでアプリを作ってリリースしたことのある方」(挙手)
    masuidrive「今日は初心者向けなので、今挙手された方が聞くような内容はありませんw」
    って言われました。そりゃまあそうですよね。

    ハッカソンでは、電源検索の無料版「電源検索Lite」を開発して「Titanium大賞」をいただきました。

    6253918541_5b2d940be1_o.jpg

    そういうわけで、「電源検索Lite」for iPhoneは今Appleで審査中なので、審査が通ればAppStoreに登場する予定ですので、楽しみにお待ちくださいませ。
    ちなみに、待ち切れない方は、電源がないお店も検索できる有料版がすでにAppStoreに出ております。



    Titaniumで作ったiPhoneアプリに広告を出す場合、モジュールが簡単に手に入るAdMobが人気ですが、AdMaker(MediaAd)は使えないの?という声も多いみたいです。やってみたら簡単に出来たので、やり方をまとめてみます。

    モジュールを使う

    下記を落としてきます。
    tryden/TiAdMaker - GitHub

    titanium.xcconfigを開くと、TitaniumSDKのバージョンが定義されているので、これを自分の好みのものに書き換えます。1.6.1はちょっと微妙ですね。
    titanium.xcconfig.png

    で、build.pyを走らせるとモジュールが出来上がります。
    build.png build2.png

    出来上がったモジュールを解凍して、新しいプロジェクトにこんな感じで配置。
    module-1.png

    example/app.jsにサンプルがあるので、まずはこれを動かしてみるのがいいんじゃないかと思います。

    app.js-1.png

    AD_URL、SITE_ID、ZONE_IDはAdMakerでメディアを作るともらえます。
    medibaad-1.png

    というわけで起動してみるとこんな感じ。
    sample1.png

    めでたしめでたし。

    webviewを使う方法

     ちなみに、AdMakerの公式サイトでは、こんなふうに案内されています。

    TitaniumへSDKを実装できません。どうすればいいですか?
    SDKでの対応はしておりません。
    Web Viewを作って頂き、そこにJavaScriptタグを実装して頂くことで表示して頂くことも可能です。
    (よくあるご質問|スマートフォン広告なら「mediba ad」|iPhone、Androidアプリ・サイト広告)

    JavaScriptと空っぽのbodyタグを書いたHTMLを用意してwebviewで開いたところ、広告はちゃんと表示されたのですけど、クリックしたあとの広告もwebviewの中で開いて、どうしてくれようかという感じになりました(当たり前ですね)。
    webviewのイベントをハンドリングしてあれこれという手も考えられるのですが、あんまりやると広告に手を入れているように見えてしまうことが懸念されます。モジュールが動くのだったら、そのほうがいいんじゃないかな、と思います。

    P.S: Android用はこちら。
    titanium の AdMaker モジュール作ってみました(Android用) #titaniumjp - harukazepcの日記



    個人的なポリシーで、アプリケーションのバージョン番号は、1.0, 1.1, 2.0とかじゃなくて、20110923, 20110925...っていうふうに年月日でつけることにしています。
    どこでマイナーバージョンを上げてどこでメジャーバージョンを上げるかとか悩んでも仕方ないし、ユーザーさんにとってはどっちが新しいかさえ分かればOKなんだから、無理に数字に丸める理由はないよね。

    というような経緯で俺ポリシーを採用していたら、えらい目にあいました。

    理由は知らないんだけど、Titanium MobileはInfo.plistに書いてあるBundleVersionの後ろに、タイムスタンプをくっつけてしまいます。例えばInfo.plistに「1.0」と書いた場合、実際のビルドに使用されるCFBundleVersionは「1.0.1316956026」という具合に。
    普通の人はバージョンなんてせいぜい5文字だから、 日付時刻をつけても弊害はなかったのだけれど、年月日方式だと、「20110925.1316956026」となってしまいます。実はバージョン番号には18桁までという制限があるので、これだとCode SignをするときのVelificationでエラーになってしまうのです。

    厄介なことに、このアプリの旧バージョンはXCodeで開発していたので、年月日方式ですでにリリースしてしまっています。
    しょうがないので、「3.0」にしてみたんだけど、これも「The key CFBundleVersion in the Info.plist file must contain a higher version than that of the previously uploaded version.」ということでどうにもならなくて泣きそうに。Adhoc Buildまで無事通って、最後の最後に発覚するので心理的ダメージがでかいです。

    そういうわけで、このTitanium Mobileの余計な処理を止める方法。
    builder.py ( /Library/Application Support/Titanium/mobilesdk/osx/#{TITANIUM_SDK_VERSION}/iphone/ )をひらいて、この辺をコメントアウトする。

    僕から見たら余計な処理だったけど、書いてあるからには必要な理由があったのだろうから、普通の人はまねしない方がいいと思う。 バージョン番号が長くなって困った方だけ、自己責任でどうぞ。

    おまけ:Distribution Buildのハマリどころ

     iPhoneアプリの開発は、エミュレーターで動いて、AdHocビルドも動いているのに、最後の最後でリリースできない!って苦労することが多い気がする。 自分が今回はまった点と解決策。

    • Distribution Buildした後、Validateするとすっごい長いエラーダイアログが出る
      →キャプチャしておくのを忘れたんだけど、ほぼ画面いっぱいのエラーダイアログ。長すぎて結局何がエラーなのか全然分からなかったんだけど、ダイアログの上でcommand+Cを押すと全文がコピーできるので、エディタに貼り付ければ内容を見ることが出来る。
    • 「Icon specified in the Info.plist not found under the top level app wrapper: icon.png Unable to verify icon dimensions, no icon found」
      →可能性1:info.plistに書いてあるアイコンファイルと実際においてあるアイコンファイルの名前が違う。大文字小文字にも注意。
      →可能性2:アイコンファイルが8bit pngになっている。24bit pngじゃないとダメらしいです。
    • 「a sealed resource is missing or invalid」
      →Resourcesに余計なファイルがあると起きるらしい。.gitとか.gitignoreとかそのへんをひと通り削除したら出なくなった
    • 「CFBundleVersion must be no longer than 18 charactoers」
      →上に書いたとおり。「バージョン番号は18文字以下でないといけません」。

    CodeSignとかMobileProvisioningになってしまえば、もはやTitaniumMobileであることはあまり関係が無いので、「エラー文字列 iPhone」でググるのが王道のような気がしました。



    Ti.Developers.meeting vol 0.3 で、MogSnapのコバヤシトールさんに、アニメーションについてお話していただきました。

    その際の説明用サンプルとして掲示されたTKAnimationSampleがとても素晴らしかったのでご紹介。

    toru0325/TKAnimationSample - GitHub

    TKAnimationSample1.png
    KitchenSinkみたいに、複数のサンプルが見られるようになっています。

    TKAnimationSample2.png
    HelloWorld.js。静止画見ても何のことだか分からないと思いますが、HelloWorldが下から飛び出してくるサンプルです。

    TKAnimationSample4.png
    buttons.js。ボタンが出現するサンプル。よりかっこいいbuttons_with_scale.jsというのもあります。

    TKAnimationSample5.png
    赤いボールが複雑な軌跡を描いて飛び回るredbox.js。「Hint」ボタンを押すことで、どういうふうに実現されているかを見ることが出来ます。

    TKAnimationSample6.png
    AndroidやiPadのように画面上にポップアップを出現させるInfo_view.js。iPhoneではあまりやらないことになってますが、実現させたい人はたくさんいると思うので、そういう方はこのサンプルを参考にすると良いと思います。

    ゲームやかわいいアプリケーションにアニメーションが必須なのはいうまでもないですが、情報系のアプリケーションでも、ちょっとアニメーションを利かせておくことで、 ユーザーさんの目線を誘導することが出来るのでとても役に立ちます。
    APIリファレンスを見て実装してもなかなか上手く動かないのですけど、TKAnimationSampleで動いているサンプルをみて実装するのなら簡単に実装できますよね。
    自分はTKAnimationSampleを見て30分くらいで、今作っているアプリにアニメーションを追加することが出来ました。
    とても勉強になるので、ぜひさわってみてくださいませ。



    sxchu_1011518_50479789_font.jpg

    今すぐフォローすべきTitanium Mobileの人達に名前を上げていただいていることに今更気づいたmogyaです。こんにちは。
    ちなみに明日まで東京滞在中です。顔を見たいという奇特な方は、明日のプログラマーズカフェに遊びに来ていただけると嬉しいです。

    さて、TitaniumMobileのお手本帳、appcelerator/KitchenSink。最近、コマンドラインからビルドすると、こういうエラーで止まってしまいませんか。

    [INFO] Detected custom font: comic_zine_ot.otf
    [ERROR] Error: Traceback (most recent call last):
    File "/Library/Application Support/Titanium/mobilesdk/osx/1.6.2/iphone/builder.py", line 948, in main shutil.copy(f,app_dir)
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/shutil.py", line 88, in copy copyfile(src, dst)
    File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/shutil.py", line 52, in copyfile fsrc = open(src, 'rb')
    IOError: [Errno 2] No such file or directory: u'./Resources/comic_zine_ot.otf'

    どうやら
    /Library/Application\ Support/Titanium/mobilesdk/osx/1.7.1/iphone/builder.py run ./
    と相対パス指定するとダメで、
    /Library/Application\ Support/Titanium/mobilesdk/osx/1.7.1/iphone/builder.py run ~/develop/KitchenSink/
    という具合にプロジェクトフォルダのパスを指定してあげないといけないみたい。

    それとは別に、「Your TARGET_BUILD_DIR is incorrectly set. 」問題もあるんだけど、こっちの原因はわからないw
    昨日Titanium meetup Tokyoで聞いたんだけど、地道にbuild/iphone/以下を削除するとか、project/cleanを試すとかしかないと言われました。
    XCodeで設定をいじっても直らないわりに、一晩寝ると直ってたりするんですよね・・


    sxchu_910074_mirage.jpg

    TitaniumMobileでBASIC認証を通すのに、HTTPCientのsetBasicCredentialsという関数が使える、という記述を時々見かけます。guides_network_httpclient - titanium-mobile-doc-jaとか。Titanium Mobileで開発するiPhone/Androidアプリにも載っています。

    でもこれ、どうも今使えないっぽい。

    var xhr = Titanium.Network.createHTTPClient();
    xhr.setBasicCredentials('username', 'password');
    xhr.onload = function() {
    	Ti.API.info('xhr.onload');
    };
    xhr.onerror = function(e) {
    	Ti.API.info('xhr.onerror '+e.error);
    };
    xhr.open("GET","http://example.com/hoge.html");
    xhr.send();
    

    setBasicCredentialsが使えるのであれば、上記のようなコードでうまくいくはずなのですけど、1.7.1iPhoneで走らせると、

    [ERROR] Script Error = invalid method '(null)' at app.js (line 2).
    
    そんな関数は知らんぜ、と言われます。実際、Titanium.Network.HTTPClientを見ても、そんな名前の関数は存在しません。1.5位まではさかのぼってみたんだけど、その頃からなかったっぽい。

    最初っから存在しなかったらWikiに書かれることもないはずなので、たぶん過去のある時点では存在したのだと思います。バージョンが変わったら関数が一個なくなるくらい、TitaniumMobileの利用者は慣れっこですよね?(涙)

    なお、setBasicCredentialsが使えない状態でどうやってBASIC認証を通すかについては、Antelope Love Fan -- Basic Authentication with Titanium.Network.HTTPClientが参考になりました。

    var xhr = Titanium.Network.createHTTPClient();
    xhr.onload = function() {
    	Ti.API.info('xhr.onload');
    };
    xhr.onerror = function(e) {
    	Ti.API.info('xhr.onerror '+e.error);
    };
    xhr.open("GET","http://example.com/hoge.html");
    var authstr = 'Basic ' +Titanium.Utils.base64encode(username+':'+password);  
    xhr.setRequestHeader('Authorization', authstr);  
    xhr.send();
    

    openしてからsetRequestHeaderを呼び出すのがポイントです。



    購読

    フィードリーダーを利用して検索結果を購読すれば、“ TitaniumMobile”というタグの付けられたブログ記事が公開されたときにすぐにアクセスできます。

    購読する 購読する

    タグ

    Powered by
    Movable Type