7日目は、大さん橋を見ながら@mogyaがお送りします。山下公園でコード書くとかかっこよくない?と思ったんだけど、寒くてコードどころじゃない感じでした...さてさて、TitaniumにはMapViewというのがあって、これを使うと簡単に地図アプリが作れるのですが、GoogleMapsSDKのバージョンが上がった関係で、現在Androidでは標準のMapViewではなくてModules.Mapを使うように言われていて、ちょっと混乱期にあります。3.2.0で旧バージョンが削除されるらしいので、来年には落ち着くんじゃないかと思うのですけど。現行だと、こんなかんじで書かないといけません。map_view.jsさらにさらに、MapViewを使って、地図をドラッグした時に発生するregionChangedイベント(これも最近名前がregionchangedイベントに変わりましたw)を契機としてモバイラーズオアシスAPIを呼び出すようにすれば、電源が使えるお店を一覧するアプリを作ることが出来ます。実際作ってみるとわかるのですが、このつくりだと微妙に使い勝手の悪いアプリになります。離れた位置を見ようとして移動を繰り返すと、画面がちょっと動くたびにデータをロードしに行くので、処理がたまってだんだん重くなってしまうのです。ブラウザ上のGoogleMapsSDKで開発する場合には、処理が落ち着いた時に呼び出してくれるidleイベントというのが存在するので、これを使えば綺麗に実装することが出来ます。もぎゃろぐで、idleイベントが存在しないAndroidやiOSのSDKでどうするか、というのがこの記事のテーマです(前置き長すぎだろうw)idleイベントと近そうなイベントとして、completeイベントというのがあって、これを使うのも一つのアイデアです。このイベントは、地図のロードが完全に終わってから呼び出されるので、これで実装すると、「ユーザーがドラッグ→地図がロードされる→(一呼吸)→店舗が表示される」という、これまた使い勝手の微妙なアプリになります。今年リリースした電源検索新バージョンや、iPhone版の電源検索では、regionChangedイベントでそのままAPIを呼び出さずに、キューにイベント情報を積んでおいて、一定時間regionChangedイベントが発生しなくなったら、最後の一回分だけAPIを呼び出す、という実装を行いました。data_task.jsdata_task.js部分が問題のロジックをカプセル化したものです。regionChangeイベントが発生したらとりあえず全部requestでDataTaskにあずけてしまいます。mapview.addEventListener(regionchanged,function(evt){datatask.request(evt);});DataTaskは内部でタイマーを持っていて、一定時間が経つと、最後に呼び出したrequestの引数を使って、actionコールバックを呼び出します。actionコールバックの中でAPI呼び出しを行うようにすれば、おおむね、ユーザーが地図をドラッグしおわったタイミングでAPI呼び出しを行うことが出来ます。DataTask({interval:3000,action:taskAction,caller:this});datatask.start();書きながら「そこまで頑張る必要があったんだろうか。実はcompleteイベントでいいんだったりして」とちょっと不安になってきたのですけど・・・大丈夫なはずだ。神は細部に宿る!明日はryugooさん@ChatWorkです。3.1.3が正式リリースになりました。使おうかと思ったのですが、ひとつ気になることが。TitaniumSDKのバージョンをあげるということは、古いiPhoneやAndroid端末のサポートを切り捨てることになったりしないかな?結論から言うと、3.1.3にあげても市場にある大半の機種で動作するようになっているので、あんまり気にしなくてよかったわけですが、せっかく調べたので一応まとめておきます。SDKの範囲はこの辺に載っています。8.5%2.2は切っていいような気がします。S(SC-02B)がぎりぎり生き残るくらいの目安です。2.3.3以降をサポートすることにすれば、TitaniumSDKは最新の3.1.3でも大丈夫なことになりますね。「最高のタブレット」を求めて!(公式データのコピー)iOS6が93%、iOS5が6%。それ以前は切ってよさそう。iPhone3GSですらiOS6対応ですから、iPhone3Gを切るくらいは十分アリでしょう。5.0-7.0サポートなので、これを使って問題なさそうです。3.1.3を使っても古い機種を切る心配はしなくてよさそう、という調査結果でした。2012、前倒しで参加表明したら、案の定ネタが思い浮かばないうちに当日になってしまいました。いうときは、自作便利関数ライブラリを公開するといいっておじいちゃんが言ってたので、ボクのutil.jsの中身を公開します。前後の空白を削除するとか、改行を落とすとか。ちなみに、見落としがちですが、printfはGlobal.Stringとしてあらかじめ定義されています。var_dumpPHPでいうところのvar_dump、オブジェクトの中身が見たいときは、Ti.API.debug(JSON.stringify(obj));という具合にすれば見られる。見られた牧歌的な時代もあったらしいけど、今試してみたらやっぱりダメだった。速度の計測できあがったアプリがなんか遅いのでチューニングが必要だ、となった場合、「推測するな,計測せよ」の原則に従って、まずどこに時間がかかっているのが鉄則です。いうことで、処理時間を計測するためのコード。いうふうにして使います。handler');そうすると、こういうログが得られます。100ms処理に時間がかかっているのは「時間がかかってそうな処理2」の部分だ!ということが一目瞭然になります。trace.lapをつっこんで犯人を絞り込むもよし、十分にわかったのであれば腕をふるって高速化に着手するもよしですね。明日は@tady_jpさんですね。2012の提供でお送りしております。Mobileのおかげで、iPhoneとAndroid両にらみでアプリ開発することが現実的になったのはいいのですけど、どちらも機種が増える一方なので、画像ファイルの準備が洒落にならなくなりつつあります。Sawalogとはいえ、実際にはほとんど同じ画像がサイズの違うキャンバスに貼り付けてあるだけなので、自動化することにしました。最大で1024pxの画像を57pxまで圧縮することになるので、ビットマップやpng画像をそのまま縮小すると目も当てられない画像になってしまいます。そこで、デザイナさんにはillustratorのベクター画像で納品をお願いすることにしました。illustratorの「Webおよびデバイス用に保存」機能を使うと、作成していただいた画像をSVGフォーマットで出力することが出来ます。SVGは、ベクターグラフィックスなので縮小してもつぶれない、たいていのブラウザでも開くことが出来るなど、期待される要素がたくさんある割にはちっとも日の目を見ないフォーマットですが、それはさておき、プログラマ御用達の画像処理ツールImageMagickやそのRubyバインディングであるRMagickで扱うことが出来ます。いうわけでRubyで書いたコードがこちら。icon.svgとsplash_screen.svgを元に、必要なサイズに拡大縮小、背景は指定した色で塗りつぶした画像を一気に生成します。いうのを用意しておけば、「iPhone6が発売されたので新しい解像度の画像が必要」というときでも、プログラマレベルで片付けることが出来るので便利ですよね。この手法にはちょっと難点があって。ドロップシャドウとか非表示レイヤーなんかはImageMagickがついてこれないのでぐちゃぐちゃになってしまうことがあります。パスで描かれた単純な画像しか適用できないのが辛いので、最近はPhotoShopのアクション機能で出力するほうがいいのかなーとか考えています。そのへんも手法が確立したらそのうちブログで書こうと思います。webviewのリンク先をブラウザで開くWebViewで開いたページに対して、リンクをクリックした時の挙動をコントロールしたい、というのは人類共通の願いで、過去にもたくさんの方がブログ記事を書かれています。ひげろぐ最初の2つは、webviewのbeforeLoadイベントを使う例で、あとの2つは(もぎゃろぐとひげろぐ。)HTMLの中でリンククリックをハンドリングして、Ti.App.fireEventでアプリに飛ばしたイベントを使って何とかしようという例です。前者は、iOSとAndroidの違いやTitaniumSDKのバージョンによって動いたり動かなかったりしているのが難点で、後者は、JavaScriptのコードがバグっているとデバッグが超大変(printfデバッグすらできない!)なのが難点です。ありがちな要求として、ランチャーがわりにローカルのHTMLファイルをwebviewで開いておいて、その後のリンク先は全部ブラウザで開いてほしい、という要望が考えられます。いうかボクが欲しかったのにそういうサンプルが見当たらなかったので、自分で書きました。ポイントとしてはbeforeLoadは最初のローカルHTMLの読み込みに対しても呼び出されますので、urlが’file://’かどうか確認して、ローカルファイルじゃない時だけ処理するようにしています。beforeLoadでブラウザを開いたとしても、webview自体が次のページを読みに行ってしまうことは阻止できません。できるのかもしれないですけど、うまいやり方を思いつかなかったので、stopLoadingで阻止しつつ、念のため、loadイベントで戻れるときはgoBackさせて強引に最初のページを維持させています。これをやっておかないと、特にAndroidでBACKボタンを押してアプリに戻ってきた場合に、次のページを開いているwebviewが見えてしまいます。余談ですが、Ti.Platform.openURLって、Androidだとちゃんとインテントを聞いてくれるのですね。問答無用で標準ブラウザが開くのだと思っていました。TitaniumSDK2.1.2GAだと、AndroidとiPhone両方で動作しています。TitaniumMobileコメントする[Titanium]WebViewの遷移先を横取りする最近まーったくTiを触れていないのですが。書くと役立ちそうな話題を見かけたのでちょっとだけ。特定のドメイン(URL)じゃないページへ遷移する場合は、通常のブラウザアプリ(Safari等)で開くという要件です。2011」向けに書いています。@astronaughtsさんは、この企画もそうですけど、それ以外にも関西で最大規模のTitaniumイベントTi.Developers.meetingの主催者でもあります。Ti.Devs.me、諦めずに開催を繰り返して大きなイベントに育て上げた@astronaughtsに、個人的今年のTitaniumMVPを送りたいです。そんなわけでTitaniumの話題を一つ。Titaniumでは、アプリ内でブラウザが開くwebViewという仕組みを使うことができます。これを使うと、アプリ内でWEBページを見てもらうことができるので、Titanium以外でもよく使われている仕組みです。これ、意外と怖いということはご存知ですか?例えば簡単なアプリを用意してみましょう。このアプリは、起動すると、モバイラーズオアシスというサイトをwebviewで開きます。Gistこのアプリの最後に、ちょっとスパイスをかけてみます。上野駅が蒲田駅に変わってしまいました。これで、モバイラーズオアシスの中の人は、「蒲田駅を検索したら違う位置が表示された」という謎のバグ報告に悩まされることになります。永久に悩み続けるがいい...ご自分のアプリのWebViewに上記を仕掛けるとか、絶対やめてください。やめろってば!冗談はさておき、技術的にこういうことが可能であることは頭においておく必要があります。逆に、この手法をうまく使えば、スマートフォンに最適化されていないHTMLに別のCSSを適用して要素を大きく表示させたり、サイドバーを隠してスマートフォン向けのページに見せるようなこともできるかも。...できるかもしれないのですけど、実際は結構大変です。この記事を書くために色々試したのですけど、evalJSしたJSコードをデバッグする手段が無いので、泣きそうでした。複雑なJSを書くと、なぜか処理が行われなくて途方にくれます。いい思いつきだと思ったんだけどなぁ。明日は@rakiさんかな。iPhoneでAdMaker広告を掲載Titaniumで作ったiPhoneアプリに広告を出す場合、モジュールが簡単に手に入るAdMobが人気ですが、AdMaker(MediaAd)は使えないの?という声も多いみたいです。やってみたら簡単に出来たので、やり方をまとめてみます。モジュールを使う下記を落としてきます。GitHubtitanium.xcconfigを開くと、TitaniumSDKのバージョンが定義されているので、これを自分の好みのものに書き換えます。1.6.1はちょっと微妙ですね。build.pyを走らせるとモジュールが出来上がります。出来上がったモジュールを解凍して、新しいプロジェクトにこんな感じで配置。example/app.jsにサンプルがあるので、まずはこれを動かしてみるのがいいんじゃないかと思います。AD_URL、SITE_ID、ZONE_IDはAdMakerでメディアを作るともらえます。いうわけで起動してみるとこんな感じ。webviewを使う方法ちなみに、AdMakerの公式サイトでは、こんなふうに案内されています。TitaniumへSDKを実装できません。すればいいですか?SDKでの対応はしておりません。Viewを作って頂き、そこにJavaScriptタグを実装して頂くことで表示して頂くことも可能です。ad」|iPhone、Androidアプリ・サイト広告)JavaScriptと空っぽのbodyタグを書いたHTMLを用意してwebviewで開いたところ、広告はちゃんと表示されたのですけど、クリックしたあとの広告もwebviewの中で開いて、どうしてくれようかという感じになりました(当たり前ですね)。webviewのイベントをハンドリングしてあれこれという手も考えられるのですが、あんまりやると広告に手を入れているように見えてしまうことが懸念されます。モジュールが動くのだったら、そのほうがいいんじゃないかな、と思います。Android用はこちら。MogSnapのコバヤシトールさんに、アニメーションについてお話していただきました。その際の説明用サンプルとして掲示されたTKAnimationSampleがとても素晴らしかったのでご紹介。GitHubKitchenSinkみたいに、複数のサンプルが見られるようになっています。HelloWorld.js。静止画見ても何のことだか分からないと思いますが、HelloWorldが下から飛び出してくるサンプルです。buttons.js。ボタンが出現するサンプル。かっこいいbuttons_with_scale.jsというのもあります。赤いボールが複雑な軌跡を描いて飛び回るredbox.js。「Hint」ボタンを押すことで、どういうふうに実現されているかを見ることが出来ます。AndroidやiPadのように画面上にポップアップを出現させるInfo_view.js。iPhoneではあまりやらないことになってますが、実現させたい人はたくさんいると思うので、そういう方はこのサンプルを参考にすると良いと思います。ゲームやかわいいアプリケーションにアニメーションが必須なのはいうまでもないですが、情報系のアプリケーションでも、ちょっとアニメーションを利かせておくことで、ユーザーさんの目線を誘導することが出来るのでとても役に立ちます。APIリファレンスを見て実装してもなかなか上手く動かないのですけど、TKAnimationSampleで動いているサンプルをみて実装するのなら簡単に実装できますよね。自分はTKAnimationSampleを見て30分くらいで、今作っているアプリにアニメーションを追加することが出来ました。勉強になるので、ぜひさわってみてくださいませ。Kyotoで、「window.urlを使わないプログラミング」というテーマでお話させていただきますした。ThemeCountry。