2012/11/07

【7日目】Tabletかどうかの判定

この記事は、@astronaughts が始められた「Titanium mobile “early” Advent Calendar 2012」向けに書いています。11月1日 ~ 30日まで毎日誰かがTitanium Mobileについての記事を書いていくというイベントです。

 ■Tabletかどうかの判定 
マルチデバイスをターゲットにしたアプリを制作する場合に、対象の端末がタブレットかどうかを判定したい場合があると思います。 Titanium Studioで作成されるテンプレートだと、以下のような素敵コードでタブレットかどうかを判定してくれます。
//considering tablet to have one dimension over 900px - this is imperfect, so you should feel free to decide
//yourself what you consider a tablet form factor for android
var isTablet = osname === 'ipad' || (osname === 'android' && (width > 899 || height > 899));
iOSの場合はこれでも問題無いでしょう。Ti.Platform.osnameが'ipad'を返せば、それは間違い無くタブレットなのでしょうから。

でも、Androidの場合はどうでしょう?上記コードだと縦もしくは横の解像度が900ドット以上だとタブレットと判定するようです。 これそのまま使うと、いまなら多くのAndroid端末がタブレットと判定されてしまうでしょう。ましてやauの冬モデルで発表されたHTC J butterflyなんかは5inchサイズながら1920x1080のフルHD解像度です。Nexus10を別にすれば、その辺のタブレットも真っ青な解像度ですよ。

コメントにもあるようにこの判定方法は完璧とはほど遠く(それにしても"feel free to decide yourself"とは何とお気楽な...)、このような解像度で判定するやり方は進化の早いスマートデバイス業界にはとても通用しそうもありません。 

では、どのようにしてタブレットかどうかを判定すれば良いのでしょうか?タブレットをタブレットとして我々が認識するのはやはりその画面サイズだと思われます。Ti.Platform.DisplayCaps以下にスクリーンサイズを得るメソッドが無くても臆することはありません。自分で計算して求めればいいのです。

HTC J butterflyがスマホで、Nexus7がタブレットとして世の中に認知されているなら、5.0 - 7.0inchの間にタブレットかどうかの判断ポイントがあるようです。以下の例では6.5inchサイズより大きければタブレットと判定するようにしてます。
function isTablet() {
  // xdpi, ydpiが未定義のプラットフォームもあるのでその場合はdpiを使用
  var xdpi = Ti.Platform.displayCaps.xdpi == undefined ? Ti.Platform.displayCaps.dpi : Ti.Platform.displayCaps.xdpi;
  var ydpi = Ti.Platform.displayCaps.ydpi == undefined ? Ti.Platform.displayCaps.dpi : Ti.Platform.displayCaps.ydpi;
  var disp_size = Math.sqrt(
    Math.pow(Ti.Platform.displayCaps.platformWidth/xdpi, 2) +
    Math.pow(Ti.Platform.displayCaps.platformHeight/ydpi, 2)
  );
  return (disp_size > 6.5 ? true : false); // 6.5インチ以上ならタブレット
}
え?いまだとスマホとタブレットの間にphabletっていうジャンルがあるって?
知らんがな...

ってことで、明日は@masapla さんです。よろしくお願いします。

Code strong,

2012/09/21

CloudCore VPS

自分で開発したプライベートな非公開のコードをそろそろsvnとかgitなどのVCSでちゃんと管理したいなぁと思ってました。で、QNAPとかDroboとかのNASでsvnやgitのサーバーとして運用できるものがあるので、それの導入を当初は考えていました。

ところが、ひょんなことからCloudCore VPSという仮想専用サーバーの存在を知り、NASの購入に5-6万も費やすくらいなら、こちらを利用した方が安いかもと思い立ち、今回試しに使ってみることにしました。

もちろんこの場合は、自分でちゃんとデータのバックアップを取ることが前提になりますが、まぁそれなりにちゃんとしたサービスなら簡単にトラブルが起きるとも考えにくいと楽観視してます。いずれバックアップのサービスも開始されそうですし。

運用するOSはとりあえず何か不都合があるまでは、デフォルトのCentOS5.xのままでいいかなと思い、ここを参考に必要最低限の設定を行い、svn+SSLのサーバーとして使用できるところまでに関してはここを参考にセットアップを完了しました。

(CloudCoreはデフォルトではほとんど何もインストールされておらず、それゆえ自分の好みに応じてカスタマイズがやりやすいというのを1つの売りにしているよう?です)

これでノマド生活になっても、どこからでもネットにつながってさえいれば自分のコードへのアクセスやコミットができるようになりました。

後はサーバーサイドの勉強にnode.jsでもセットアップしていろいろ実験してみようかなと思っておりますが、そのような個人的なプライベートサーバー的な使用なら、VPSのスペック(CPU物理1Core/RAM 2G/HDD 10GB)もいまのもので充分以上だと思います。

こういうものが年間1万円程度で利用することができるのだから、まったく良い時代になったものだと思います。これからはこのようなプライベートなサーバーに自分専用の環境を構築し、自作のモバイルアプリでスマホからアクセスして仕事に役立てる、というような使い方をする人が増えるのかも知れませんね。

プライベートサーバーゆえ公開はしませんが、何か面白いものでも出来たらここのblogでまたお知らせしたいと思います。

あ、冒頭のそもそものCloudCore VPSを知ったきっかけですが、自分がちょっと関わっているTitanium Mobileユーザー会用のサーバーが、KDDIの開発者支援制度を通じて無償提供されることになり、その環境がCloudCoreだったというわけです。

そのユーザー会の第1回目の会合が9/24にありますので、もしご興味がございましたら是非ご参加してみてください(atnd)。

ではでは。

2012/09/08

最近読んだ本

去年の年末にオフィスが引越しになり、往復約4時間も通勤にかかるようになってしまいました(涙。まぁ、どうせ寝てるんだろうと思っていたら、もう若く無いせいか、あまり電車では寝られなくなってしまってました・・。

暇だし、時間勿体無いし、積ん読を消化するのにちょうどいいやと思ってたら、意外と読書が面白くなってしまって、最近では月に2−3冊くらい読んでます。

ということで、整理の意味も込めて最近読んだ本をここに列挙してみます。一応、順番は読んだ順番じゃなくて、自分が参考になった/役立った/面白かったと思った順番です。詳しい書評はネタバレになるので1行コメントだけ添えますが、ご興味が湧きましたらご参考に読んでみてください。

特に上から5つめくらいまでは、自分的には結構お薦めです。

■夢をかなえるゾウ
 自己啓発本はこの1冊だけ読めばOK
1分仮眠法
 睡眠の大切さを再認識
ウェブはグループで進化する
 fladdictさんもお薦め
Think Simple
 iMacの名称を考案した広告代理店の方が見たアップルとは?
トレードオフ
 上質か手軽か
FREE
 ご存知フリーミアムの話し
ソーシャルリスク
 炎上しない為にどう対処するのか
世界を歩いて考えよう!(ちきりんさん)
 旅行に行きたくなりました
ゆるく考えよう(ちきりんさん)
 人生がんばらなくてもいいんです
■東電OL殺人事件
 いまだ裁判は係争中
スマホで世界をねらうために知っておきたい3つのこと
 その前に売るアプリを作らないと...
フリーで働く!と決めたら読む本
 別に決めてないけどね
特定の人としかうまく付き合えないのは、結局、あなたの心が冷めているからだ
 まぁ、そう何だけどね
TREASURE MAP 成功への大航海
 買って大後悔?
グーグルで必要なことは、みんなソニーが教えてくれた
 何を学んだのかよくわからなかった
サムスン式仕事の流儀
 サムスンの社員は上下関係が厳しくて大変そうだなぁ

最初は自己啓発やビジネス成功の秘訣みたいな本を選んでましたが、まぁ3冊くらい読めば、大体書いてある内容は同じだな、と気づきました。なので、最近は実用系的な本に手を出し始めてます(笑

2012/09/02

Amazon SIM

いままで、SIMフリーの海外Android端末はb-mobileのfairで運用してました。これは、1GBの通信量を4ヶ月間内に約8000円で使用できるものです。

私の通常のユースケースでは通勤時に電車でちょっとtwitterとかfacebookとかを見る程度なので、これでも充分に余るくらいで運用できていました。

で、Amazon SIMというものが発売になり、こちらの場合は500MBを1ヶ月で約2000円で運用でき、端末が対応していれば更に高速なLTE網が使えるというものです。いま所持している端末はLTEに対応したものは無いのですが、fairで使い続けた場合、1ヶ月で約250MB/2000円となりますので、同じコストでざっと2倍の通信量を使えることになります。

fairでも充分だった私に2倍のデータ通信量も必要無いかとは思いましたが、コストが同程度ということと、将来的なLTE対応端末の入手も見据えて乗り換えることにしました。それで使い始めて、ちょうど1ヶ月経ちましたが、データ通信が思ったよりいってしまい、8月は500MBギリギリでした(汗

通信量が以前よりも大幅に増加した原因のひとつはJelly Beanから導入されたGoogle Nowだと思われます。これがどれくらい使い物になるのかをいま実験してますが、位置情報に基づいて交通機関やら天気予報やらのデータを裏で入手しているので、通信量は確実に増えているでしょう。

しかし、それよりも多大な影響がありそうなのは、Google+とfacebookで、Beautiful Planet EarthとAnimalsというアカウントのフォローを始めたことです。これらのアカウントは美しい地球の風景や動物の写真を頻繁に投稿しますので、これまでのテキスト中心の知人達の投稿よりも確実にデータ量が増えていることは間違いありません。

ただ、画面サイズが大きく、発色の良い有機ELのGalaxy Nexusでこれらの写真を見ると、本当に美して思わず時間を忘れて見入ってしまうほどで、フォローをヤメることはなかなか難しそうです。

後は無頓着にアプリの更新を自動アップデートにしてたので、それで消費される通信も少なくは無かったでしょう。なので、手間はかかりますけど、自動更新はほとんどヤメました。自動更新にしてても、繋がっているネットワークがwifiなら自動ダウンロードするけど、3Gだとダウンロードしないとかまで設定できれば便利だと思うんですけどね。

まぁそんなわけで、キャリアの定額プランよりも気を使って考えながら使う必要は多少ありますけど、その分、値段は3分の1程で運用できますので、使用状況によってはかなりお得かと思います。

ってか、日本のキャリアの通信費用は高過ぎやろ!アホか。

2012/08/15

QuickTiGame2d UI Firstlook

Titanium Mobile用に2D GameエンジンモジュールのQuickTiGame2dってのがあるのですが、自分はゲームとかはちょっと作れません。

でも、UIのアニメーションに使えると面白いと思いたち、作者の方にSpriteのテクスチャーにblobを突っ込めるようにお願いしてみたところ、v.1.3でサポートされましたので早速試してみました。

仕組みは簡単で、通常のTiのViewでUIを作成すると、.toImage()メソッドでViewのイメージのblobを作成できるので、それをSpriteのテクスチャーとして指定します。

で、通常はUIのViewを表示しておいて、UIをアニメーションさせる時だけGameViewを前面に表示させて、アニメーションが終了するとまたUIのViewに切り替えるだけです。

以下がそのサンプルですが、これは2つのViewをフリックで行き来し、行けない方向にフリックするとViewが少し傾くというAndroidではお馴染みの動きです。使っているのはiPodなのですが(笑)


このように簡単に2D効果を使ったUIを作れそうなのですが、いま流行りの折り紙みたいなUIに応用するにはやはり3Dのサポートが必要なので、QuickTiGame3dの登場が待たれます(笑)

とりあえず、短い時間でやっつけで作ったので、コードの整理とサンプルのUIをもう少し追加してからソースコードは公開したいと思います。

Code strong,

2012/07/25

何にお金を払うのか

きっかけは朝に見かけたこの記事だったのです。詳細は記事を読んでいただくとして、要は電子書籍が日本で一向に普及しないのは、メーカーの囲い込み戦略により、Aという端末ではAストアのコンテンツしか読めず、他のストアとの相互利用ができないからだと言うのである。

本当だろうか?もちろん、心理的な妨げの一因であることは間違いないし、誰もが自分の端末で様々なコンテンツを読みたいであろうことは間違い無いけれど、出版社からすればそこに市場があるのならば、様々なストアにコンテンツを提供すれば良いだけの話しである。

記事中にもあるように、マンガまでを書籍に含めれば実は日本は電子書籍大国なのである。結局のところ、日本人はマンガばっかり読んで、その他の書物のニーズがそもそもそんなに多く無いのではないのか?というのが自分の持論です。

囲い込みに関してもう少し言及すると、例えば、家庭用ゲーム機は対応ソフトじゃないと遊べないわけだけど、それが普及の妨げになっているという話はあまり声高には聞かないし、むしろ競争原理が働いて消費者は非常に安くゲーム機を手に入れられるなどのメリットを享受しているように思う。

電子書籍もいまはまだ様々なメーカーに競争してもらった方がメリットは大きいのではないのだろうか?また、記事中にあるiTunesストア待望論も囲い込みという意味では他のストアと同等である。だから、これが決定的な理由になるとは思えない。

(ただ日本人は外圧が無いとなかなか変わることのできない国民性なので、そういう意味で黒船としてのiTunesやアマゾンのKindleに期待するのもよくわかる)

もうひとつ普及を妨げる要因として、電子書籍なのに値段が高いというのがある。電子書籍なんて、紙に比べてコストかかっていないんだから、もっと安くて当然だろうということだ。にも関わらず、電子書籍の値段をあまり下げることが出来ないのは、書店や印刷業者が潰れるからだ。

というようなことが誠しやかに言われるが、そういう都市伝説(と勝手に私は思っている)を恐れすぎず、業界は勇気を持って電子書籍でこれまで本をあまり読まなかった層を開拓できれば、むしろ紙の書籍の売上もあがるんじゃないかというような気がする。

また私たち消費者も、コストにお金を払うというの感覚では無く、もっと価値にお金を払うという風にマインドを少しづつでも変えてった方が良いのではないだろうか?

紙だろうが電子書籍だろうが、そこから得られるもの(= 価値)は基本的には同じものであるはずだ。であるならば、紙も電子書籍も同じ値段でも構わないと私は思う。

(もちろん、現時点で電子書籍から得られるユーザー体験は(私の価値基準でも)紙の書籍に遠く及ばないので、そういう観点からは電子書籍の値段をもう少し下げてもらいたいなーとは私も確かに思うのだが)

そうしないと、際限の無いコスト削減の圧力にメーカーは疲弊してしまうわ、デフレスパイラルもいつまで経っても止まらないわで、景気も良くならないし明るい未来も来ないような気がしてならないんだぜ?w

2012/06/30

パーソナルアシスタントの未来

AppleのWWDC、MicrosoftのWindows Phone Summit、GoogleのGoogle I/Oと、ここのところ立て続けにイベントが開催されて、興味深いニュースが沢山出てきました。

順番は前後して、まずMicrosoftからですが、Windows Phone8でカーネルがWindows 8系に刷新されることが発表されました。Windows Phoneではいままでマルチコアがサポートされてなかった為にハードウェアスペック的にはかなり見劣りしたものとなってましたので、これでようやくiOSやAndroidと戦えるものになりました。

MicrosoftがOSカーネルの基本機能で出遅れるというのも何だか意外な感じもしますが、逆にここはいつでもキャッチアップできるからUXの開発を優先したとも言えます。

ただ、後述しますがAppleやGoogleは既に次のフェーズへと戦いの舞台を移しているので、周回遅れを挽回したとまではまだ言いがたい状況です。

Appleは、今回のWWDCの目玉はRetina Macbook Proで、iOSに関しては控えめな発表のように思いました。これはiPhone5の登場に向けてまだ何か隠し玉があるような気がしてますが、どうでしょうか?

影響の大きそうなところと言えば、Mapを従来のGoogle Mapから独自のものに切り替えたことでしょう。GoogleのAndroidとは競争が熾烈になってきているので、コアな機能を他社に握られたままでいることは好ましくない為、ある意味当然と言えば当然の戦略ですが、まだ地図の完成度が低いので正式版に向けてどう仕上げてくるのか楽しみではあります。

独自のMapを強力な武器に仕上げられなかった場合は、逆に足かせとなる可能性もあり、そういう点では諸刃の剣と言えるでしょう。ただ、GoogleはiOS向けにMapアプリを提供し続けるでしょうから、ユーザーとしては実用的な方を単に使えば良いだけなのかも知れません。

Googleは、Jelly Beanで着実にAndroidの完成度を高めました。特に画面遷移の滑らかさやタッチのレスポンスでこれまで遠くiOSに及びませんでしたので、額面通りに改善されたのであれば、Androidもいよいよ死角が無くなってきたのかも知れません。

もとより、OSの機能としてはAndroidの方が上だと個人的には考えており、ICSでUIのデザインもかなり洗練されたと思ってます。iOSは始めの完成度が高かったことから見栄えはほとんど変わっておらず、そのせいもあってか、情報量の少ないホームスクリーンもいまとなっては何だか古臭く感じるくらいです。

しかしAppleやGoogleはOSの機能よりはスマートフォンの今後のあり方や使われ方、特にパーソナルアシスタントとしての機能向上に開発のフェーズを移しているような気がするのです。

というわけで相変わらず前置きが長いですが、ここからが本題です。

パーソナルアシスタントとしての機能は、AppleがSiriで先鞭をつけた感があるのですが、Androidは従来からある音声検索の機能を改善するという手で来ました。AppleのSiriのように特別なネーミングを付けなかったのは、もしかしたらAndroidという名称自体が既にそのような性格を持ち合わせているからなのかも知れません。

Siriや音声検索はユーザーからの能動的な問いかけに対するものですが、パーソナルアシスタントとしてより重要なのは、Google NowのようなユーザーのTPOに応じてスマートフォンが自律的にユーザーに取って有用な、あるいは利便性の高い情報を提供/提案するような機能でしょう。

しかしこのようなパーソナルアシスタントが有効に機能するには、ユーザーのかなり詳細な行動(スケジュールや位置情報など)やプライベートな情報(交友関係や趣味、趣向など)を情報としてインプットしなければならないので、セキュリティがこれまで以上に重要になります。

極私的な情報がいつネットに流出するかも知れないという不安がある中では、誰も安心して使えないですものね。それにこういうユーザーの行動が広告などに二次利用されることへの嫌悪感をどう払拭できるか?というのも大きな課題だと思われます。

本来、行動ターゲッティング広告というものはユーザーに取ってもメリットのあるものであるはずなのですがね。

また要人におかれましては、自分の位置情報がプライバシーの侵害や犯罪に利用される可能性も否定できないので、こういう技術が単に便利だからと、すぐに世の中で受け入れられて使われるようになるまでは、まだまだ時間がかかるものと思われます。

そういう意味では、ユーザーが機能をコントロールできるon{X}のようなものの方が、始めは受け入れられやすいのかも知れません。ただ、一般ユーザーがJavaScriptでコーディングするというのもハードルが高いし、最終的にはGoogle Nowのような検索履歴等から自動で機械学習するようなシステムじゃないと普及しないでしょう。

パーソナルアシスタントの機能が、ユーザーからの膨大なインプットから、ユーザーがもっとも欲するデータを引き出すものであるとすると、ユーザーからの大量のインプットを処理するには、データを格納する器となるデータセンターやクラウドコンピューティングなどのシステムが欠かせません。

Appleは沢山のアクティブユーザーを抱えていることから、インプットに関しては申し分無いと思われるけど、器を作る能力にはやや不安がある。Microsoftはりっぱな器を用意する力はありそうだけども、如何せんインプットが少なそう?

そういう意味ではこの分野は、いまのところGoogleが一番うまくやれそうな気がします。検索市場を独占していることから、Androidユーザー以外からの膨大な検索クエリーのデータもアルゴリズムの改善に活用できることも有利に働くでしょうし、データマイニングも研究者集団たるGoogleの得意とするところのような気がします。

しかし、AppleのUXデザインの巧みさや、短い時間でキャッチアップしてくるMicrosoftの開発力も侮れないので、実際の人間のように三者三様にそれぞれに性格の違うパーソナルアシスタントとして発展して行けば面白いのではないか?と思います。

例えば、Appleのはクールビューティで的確な回答を示すが扱いが少々気難しいところがあるとか、Googleのはほとんどの場面で完璧な答えを出すけど、稀に重要な情報をうっかり外に漏らしてしまうドジっ娘だったりとか、で、Microsoftのは何でも卒なくこなして実用性では一番なんだけど、なぜだか一般受けが悪かったり?とか。

そんな近未来を妄想する今日この頃です。

2012/05/05

xib2js & TiMockをリリースしました

frogonmobileのサイトにxib2jsの新版とTiMockをリリースしましたので、ご案内すると同時に簡単なQuick startガイドをここに記したいと思います。

基本的に、frogonmobileのサイトで公開している英語版のQuick Start Guideの和訳+αみたいな感じにしたいと思います。

ここのサイトに来ていただいている方ならばxib2jsに関してはもうご存知だと思われますが、前回のエントリーで述べた通り今回はこれのバージョンアップと共にTiMockというTitanium Mobileアプリを併用することで、モックアップを簡単に作成し実機で確認できる環境を構築することができるようになったのが大きな売りとなっております。

ワークフロー的には、下図のようにXcodeでUIのコンポーネントを並べて.xibファイルを作成し、それをxib2jsでJavaScriptに変換した後にTiMockを使って実機やシミュレータ上で確認しながらコンポーネントの位置や大きななどをコードを改変して微調整するという感じになります。


1. XcodeでUIを作成
XcodeでFileメニューからNew Fileを選択し、iOSのUser Interfaceのテンプレートを選択します(ここではEmptyを選択してます)。


後は、コンポーネントを並べてUIを構築していけば良いのですが、ここでの注意点としましては、ファイルの形式を"Interface Builder3.1"を選択しておくことです。それ以外のバージョンではxib2jsが正常にコードを生成できないことを確認してます。


2. xib2jsで.xibファイルをJavaScriptに変換
UIが出来たら、毎度お馴染み.xibファイルをxib2jsにドラッグ&ドロップすると、いつもの通りにJavaScriptのコードが生成されます。


今回のバージョンから生成されるJavaScriptがCommonJSのスタイルに則っていることが確認できると思います。

3. TiMockと連携してUIのカット&トライを行う
さて、ここからが今回の売りであります、TiMockを併用したUIのカット&トライです。まず、TiMockを実機かシミュレータで起動できるようにまずはビルドから始めます。

Githubからコードをダウンロードしたら、Titanium Studioで適当な新規モバイルプロジェクトを作って(Titanium Mobile SDKは2.0を選択する)コードや画像ファイル等をコピーし、ビルドします。

特に難しい部分は無いと思いますが、実機用にビルドする時にはui/ApplicationWindow.jsファイルの31行目のコードのコメントを外してください。
//require("api/Includes");
シミュレータで実行する場合は、そのままビルドして問題ありません。

ビルドが完了しましたら、TiMockを起動してください。TiMockは起動するとBonjourで_timock._tcpサービスをサーチします。xib2jsが起動していれば、xib2jsがこのサービスを提供しますので、TiMockアプリ上に"TiMock Service"というボタンが見えていると思います。


このボタンをタップすると、xib2jsとTiMockの通信が確立されます。xib2js上のSyncボタンが有効になるのと、TiMock上のボタンもConnectedとなったことが確認できると思います。


試しに、この状態でSyncボタンをクリックすると、変換されたJavaScriptのコードがTiMock側に転送されて、UIを実機上で確認できます。


後はxib2js上で微妙なレイアウトの崩れなどを、コード上でコンポーネントの位置やサイズのプロパティ値を調整しながらカット&トライしてUIのモックを仕上げていきます。コードを編集したら、都度Syncボタンをクリックすることで実機上で修正内容が反映され確認できます。

尚、コードの編集に関しては、TiMock上で正常に動作させるには、かなり制約されたものになります。

まず、関数とexportsの定義は変更できません。また、self変数に何らかのUIコンポーネントのインスタンスを格納し、それを返り値として返す形を取る必要があります。
function ApplicationWindow() {             // この行は編集してはダメ
  var self = Ti.UI.createWindow();           // self変数にインスタンス化した
                                                              // UIを格納する
  // ここの中はわりと自由に書ける

  return self;                                          // 必ずselfを返すようにする
}                                                           // この行は編集してはダメ
module.exports = ApplicationWindow; // この行は編集してはダメ
このルールを守れば、逆に関数の中身に関してはわりと自由に書けますが、あくまでも目的はUIのモック作成なので、あまり本格的なアプリケーションロジックをここでコーディングすることはお薦めできません。

とは言え、どんなコードなら動くのかはある程度試行錯誤が必要だと思いますので、いろいろ試してみて自分なりの答えをみつけてください。

また、xib2jsは拡張子が.xib以外のファイルを受け取った場合は、そのファイルをTiMockに転送します。TiMock側は受け取ったファイルをTi.Filesystem.applicationDataDirectoryに保存しますので、コード上でパスを適切に設定することで、画像をUIにはめ込むことが可能です。


ここで指定するパスは、実際のアプリを作成する際にリソースが置かれる位置とは違うものと思われますが、画像がどのような位置・サイズで表示されるのかを確認するには便利に使えるのでは無いかと思います。

また、xib2jsにはファイルをまとめて複数ドラッグ&ドロップしても、同時には1つのファイルしか処理できませんので、お手数でも1つずつドラッグ&ドロップしてください。

4. コードの保存
さて、最後にここまで調整してきたモックのコードを保存します。Saveボタンをクリックするとファイルの保存先を選択するダイアログが表示されますので、Titianium Studio上の適切なプロジェクトのResourceフォルダーを選択してください。


尚、いつもの注意点ですが、保存の際にxib2jsはファイルの存在の有無を確認しませんので誤ってファイルを上書きしないようにお気をつけください。これ、いい加減にちゃんと対応しないといけませんね。。

ここまで来たら、後はTitanium Studioに引き継いでアプリケーションの開発を継続しましょう。

Code Strong,

2012/04/23

xib2js 2.0 preview

久々の更新ですね(^_^;

Titanium Mobile 2.0 ローンチ記念イベント in Tokyo!!が開催されましたので、参加してきました。イベントの詳細レポートはTitanium Newsをどうぞご参照ください。

イベントの中でLTの枠がありましたので、長らく放置してましたxib2jsの新しいバージョンを発表させていただきました。ちなみに、デモがメインだったのでスライドの公開予定は特にありません。

xib2jsで生成するJavascriptは当時のKitchenSinkを参考にしましたので、現在は推奨されていない所謂マルチコンテキストと呼ばれていたスタイルのコードを生成していましたが、今回のバージョンアップで、CommonJSスタイルのコードを生成するように変更しました。

まぁそれだけでは面白くないので、TiShadowを真似て変換したJavascriptを実機やシミュレーターに転送して実行できる機能を組み入れました。

TiShadowでは、HTTPのサーバーと接続するのにIPアドレスをいちいち打ち込む必要がありますが、xib2jsはMac + iOSでの利用を前提にしているので(なぜならXcodeで作成した画面レイアウトをJavascriptに変換するツールなので)、簡単に接続できるようにBonjourを使うようにしました。

後は、画面のレイアウトを作った後に画像データを貼り込むケースを想定して、.xibファイル以外をドロップした時は、端末のアプリケーションデータディレクトリーにファイルを転送して保存する機能も追加しました。

実際のアプリを作成する時は、違うディレクトリーにアセットやリソースを置かれるとは思いますが、実機上で画像の位置やサイズとかを簡単に確認・調整するには便利に使えるかなと思ってます。

正式に公開するまでには、まだじゃっかんコード整理以外にもやることがありますので、もうしばらくご辛抱くださいまし。

Code Strong,

2012/02/24

gumroad考察

gumroadというサービスが注目を集めてますね。自分はちょっとしたトラウマがあって、Paypalのアカウントをまだ作っていないので試していないのですが、これまでとは比較にならないほど簡単に自分のデジタルコンテンツを世界に向けて販売できることが注目を集めている理由みたいです。

と同時に、いやこれは違法コンテンツの温床になるのでは無いか?とか、リンクが漏洩したら誰でも無制限にダウンロードできるのは問題だとか、負の面も報じられてます。

中には、gumroadだけに限った話では無いものもあるし、お手軽さ故にそういうことがより容易に出来てしまうということもあるのでしょうが、個人的には(まだ売れるものなんて何も無いけど)自分のコンテンツを売る販路のひとつとして、こういったサービスがうまく立ち上がってくれればいいなと思っているので、大きな問題が起きないよう、陰ながら応援しています。

で、今回はそういうことを話題にしたいんじゃなくて、私が個人的にgumroadがすごいと思った点を述べたいと思います。

と、その前にオンラインストアと言ってまず最初に思い浮かべるのは何でしょうか?アマゾンですかね、やっぱり。私がgumroadがすごいと思うのは、これのおおよそ対局を行っているのでは無いかという点です。

gumroadのサイトに行けばわかりますが、まず、ここで何を売っているのか?という情報がほとんどありません。それもそのはずで、gumroadは販売するコンテンツを簡単に紹介するページ及びそのリンクと決裁システムの提供しかしてません。

そのリンクがわからなければ、販売しているコンテンツにたどり着くことさえままならないのです。

アマゾンだったら、ユーザーのレビューとかサジェスト機能とか、あの手この手で訪問者にコンテンツを買わせる仕掛けが用意されているのですが、gumroadではそれがいっさい無くて、コンテンツが売れるかどうかは販売者の努力に強く依存しているのです。

このやり方では、ユーザーにリーチできるプレゼンスの無いひとのコンテンツはほとんど売れないでしょう。

ただ、そこをビジネスチャンスとばかりにgumroadで販売しているコンテンツを紹介するなどの周辺サービスがこの短期間で沢山立ち上がってます。gumad.meとか。

ちなみに、gumroadは販売時に売値の5%+30cの手数料を取ることで収益を上げるのですが、決済システムにStripeを使っているらしく、ここの手数料が2.9%+30cです。なので、そのまま単純に引かれるとgumroadの取り分は売値の2.1%と、かなり少ないことがわかります。

また、サービスの性格上、高額なコンテンツがバンバン売れるということも考えにくく、平均の販売単価もかなり低いのでは無いかと思われます。となれば、本来であれば、薄利多売で沢山コンテンツが売れてくれないと、儲けが出ないビジネスモデルであると考えられます。

にも関わらず、売る為の努力をほとんどしないというのは、一体どういうことなのか?で、ここがgumroadの巧妙なところではないかと「勝手に」思っているのですが、実のところそういった販売の為の努力はサーバーの運営コストに跳ね返ってくるわけです。

(えー、いまさらですが、この話はgumroadがAWSとかGAEとかのサービスを使って運営されているという仮定での考察です・・)

沢山のトラフィックを使って、画像やテキストなどで美辞麗句を並べたところで、ユーザーは商品を買ってくれるとは限りません。となると、その時の通信料は全くの無駄になるわけです。

アマゾンはユーザーにより多くの時間をサイトにとどまってもらって購入の機会を増やすのが戦略ですが、gumroadは恐らく、ユーザーがサイトに訪れるのは購入するその瞬間だけがベストで、買うか買わないかもわからないのに長くとどまってトラフィックを消費されるのはたまったものでは無いのでしょう。

だからこの先も販売しているコンテンツの検索とか、そういう類の機能は実装されないんじゃないかと想像してます。

つまり、商社としての機能を極限までシンプルに実現したのがgumroadではないか?ということです。

恐らく今後、gumroadに類似のサービスが沢山出てくるとは思いますが、gumroadという先駆者に対抗する手前、販売手数料はかなり低額な設定にせざるを得ないでしょう。

その際に、このことを理解しないでアマゾンのような機能てんこ盛りのサイトで対向しようとすると、運営コストに苦しんで足元をすくわれることになるやも知れません。まぁ、広告収入とか別の収益源を確保できれば、その限りでは無いのかも知れませんけどね。

もし、gumroadに死角があるとすれば、Stripeを利用すれば類似のサービスを立ち上げることがわりと簡単にできそうで、顧客へのリーチ力があるひとなら、個人で世界を相手に販売サイトを立ち上げる時代が実はすぐそこにやって来ているのかも知れない、ということでしょうか?

2012/02/03

ActionBarにDrop-downナビゲーションを追加する

ActionBarにCalendarやGmailのようなDrop-downナビゲーションを追加しようと思ったんです。

やり方自体は、SpinnerAdapterをActionBar.setListNavigationCallbacks()の引数に指定すれば良いのですが、公式ドキュメントに書いてあるサンプルは選択できる項目が予め決まっているResourceファイルから作るので、コーディングは最小限で済む代わりに動的に選択項目を作りたい場合などはこの方法は使えません。

で、軽くググって見た限りでは世の中にほとんどサンプルが無くて、ちょっと苦労したのでここに簡単にまとめておこうかと思います。そのうちTechBoosterさんにちゃんとした記事が載るような 気がするので、その時はこんないい加減なblogよりもそちらの方をどうかご参照ください(笑

SpinnerAdapterとして実装しないといけないインターフェースは下記
メソッド名概要
int getCount()選択項目の個数を返す
Object getItem(int position)position位置の要素を返す
long getItemId(int position)position位置の要素のIDを返す
int getItemViewType(int position)getView()で作成されるViewのタイプを返す
View getView(int position, View convertView, ViewGroup parent)position位置のViewを返す
int getViewTypeCount()Viewのタイプ数を返す
boolean hasStableIds()アイテムのIDがデータによらず安定しているか?
boolean isEmpty()リストが空か?
void registerDataSetObserver(DataSetObserver observer)データの変更を検出するオブザーバーを設定
void unregisterDataSetObserver(DataSetObserver observer)データの変更を検出するオブザーバーの設定を解除
View getDropDownView(int position, View convertView, ViewGroup parent)drop-downのpopupに表示されるViewを返す

ListViewなんかでAdapterに馴染みがあればほとんどのメソッドに関してはご存知かと思いますが、ここでの肝はgetView()とgetDropDownView()です。

メソッド名からもわかる?ように、getView()がActionBarに選択項目として描画されるViewを返し、getDropDownView()がdrop-downのポップアップに描画されるViewを返す為のメソッドです。

簡単にテキストだけ描画されるようなメニューならメソッド内でTextViewを作って返してやればいいようなものなんですが、getDropDownView()がどうにもうまく行きませんでした。コンパイルまでは問題無いのですが、ランタイム時にエラーが出てアプリが死にます。

LogCatのログを見てみると、どうもLayoutの型変換でエラーが出ているようなのですが、いろいろ試してもうまく行かないので最終的にはlayoutのxmlファイルを定義して、LayoutInflaterでViewを作成するようにしました。

ということで、最終的に以下のようなコードでうまくいったのですが、何か勘違いしているかも知れませんので、識者の方からアドバイスをいただけると幸いです。

SampleActivity.java
public class SampleActivity extends Activity implements OnNavigationListener {
  private ArrayList menuList = new ArrayList();
  private LayoutInflater mInflater;
  private ActionBar mActionBar;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    mActionBar = getActionBar();
    mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
    mActionBar.setListNavigationCallbacks(new mSpinnerAdapter(), this);
 
    // drop-downメニューのデータを自由に作成
    // ここではコード上の文字列を設定してますが
    // 例えば、IntentのBundleで受け取ったデータ
    // をもとに作成してもいいでしょう
    menuList.add("One");
    menuList.add("Two");
    menuList.add("Three");
  }

  private class mSpinnerAdapter implements SpinnerAdapter {

    @Override
    public int getCount() {
      return menuList.size();
    }

    @Override
    public Object getItem(int position) {
      return menuList.get(position);
    }

    @Override
    public long getItemId(int position) {
      // とりあえずpositionをIDとして返す
      return position;
    }

    @Override
    public int getItemViewType(int position) {
      // 何を設定すればよいのかわからないのでとりあえず
      // IGNORE_ITEM_VIEW_TYPEを返す
      return IGNORE_ITEM_VIEW_TYPE;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {   
      if (convertView == null) {
        // getView()はこれでうまく行く
        convertView = new TextView(mContext);
        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        convertView.setLayoutParams(params);
      }
      ((TextView) convertView).setText(menuList.get(position));
      return convertView;   
    }

    @Override
    public int getViewTypeCount() {
      return 1;
    }

    @Override
    public boolean hasStableIds() {
      return false;
    }

    @Override
    public boolean isEmpty() {
      return false;
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {
      // TODO Auto-generated method stub   
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {
      // TODO Auto-generated method stub
    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
      if (convertView == null) {
        // getDropDownView()はうまくいかないので
        // LayoutInflaterでViewを作成
        convertView = mInflater.inflate(R.layout.dropdown_menu, parent, false);    
      }
      ((TextView) convertView.findViewById(R.id.dropdown_menu_item)).setText(menuList.get(position));
      return convertView;
    } 
  }

  @Override
  public boolean onNavigationItemSelected(int itemPosition, long itemId) {
    // itemPositionの選択に応じた処理
    return true;
  }
}

dropdown_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

 <TextView
        android:id="@+id/dropdown_menu_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

2012/01/29

Android Usability Seminar 2012

日経BP主催のAndroid Usability Seminar 2012というのに参加してきました。ホームページの開催のお知らせから内容を察した限りでは、Androidアプリを作成する際のUX的な内容かと思い参加したのですが、内容的にはちょっと自分の思ってた方向とは違ったものの、かなり面白かったので、簡単に紹介したいと思います。

1. アップルから学ぶユーザビリティ 山中俊治氏
Suicaの自動改札機のデザインを担当。Suicaに限らず電子マネーなど、いまでは常識となっているタッチするという行為を人々にどうデザインの力で認知させるのかという課題を解決する為に、ユーザビリティテストを行い検証を行った。

ユーザビリティテストを行う上で重要なこと
  • 開発の初期段階で行う
  • 少ない人数でも構わない(回数を多く回すことの方が重要)
  • 周到に計画する(ユーザーを疲れさせない)
  •  クライアントを巻き込む
とにかくいままでに無いものを作るのだから、考えすぎても意味が無い。こうあるべきというイメージは人それぞれに違う。そして、何よりもユーザーは予想もしないことを平気でする。なので、沢山の施策を試してみて、結果(事実)を皆でシェアすることが重要。

この仕事が山中さんにとってユーザビリティテストの重要性を認識する転機になったようで、その後の大根おろしの仕事につながったそうです。この話もかなり面白かったのですが発表されてた資料なしに伝えるのは難しいかな?

膨大な大根おろしの刃の試作がなかなか圧巻でした。ポイントは、機械的な規則正しさを廃して、刃の並びにある程度のランダム性を持たせること。そうすると、大根を持ち替えたりおろす方向を変えたりしなくても、最後まで気持よくおろせるものができるそうです。

で、話は変わって山中さんから見たアップル製品の凄さは、「無垢」な塊としてのハードと赤子にもわかるインターフェース。特にハードに関しては、デザインの為に日本メーカーではまず考えられないような高コストなNC切削加工による量産技術を立ち上げたことがスゴイと。

そしてNext Stepとして、次の時代のデザインは生きものらしいデザインが来るのではないか?人間は生きているかどうかに敏感であるので、生命を感じられるもの、そしてコマンドによらないコミュニケーション、など。

2. 最新事例に学ぶユーザーインターフェースの研究 増井俊之氏
増井さんはいまの携帯電話でもはやデファクトとなっている予測漢字変換をソニーPCL時代に考案して、その後アップルに行って、かの有名なフリック入力の漢字変換システムの開発に携わったそうです。

その為か、話しのほとんどが漢字変換システムに関する話だったのですが、面白かったは、いまのスマホの漢字変換システムに全く納得されていないようで、曰く、何故にガラケーと同じようなキー配列や入力システムを採用しているのか?せっかくタッチインターフェースになったのに、新しいチャレンジが何も無いとのこと。

iPhoneの漢字入力に関しても全くお気に召さないご様子(あれ、開発に携わったはずでは?)で、あれを有難がって使っているのは、スティーブ・ジョブスに絶対騙されてるだろうと(笑)。

後は連文節変換なんてものは全く無用の長物で、かな漢字変換というのは本当は簡単で誰でも作れ、自身がRubyで600行程度で書いたかな漢字変換システム(名前失念)とか、Android用に作ったSlimeの紹介とかとか。

そして、増井さんの考えるユーザーI/F開発のタブー
  • 素人の意見を聞く
  • 多くの意見を聞く
  • 古いものを無意味に模倣
逆に正しいユーザーI/Fデザインの方法
  • 有能な人が少人数で作る
  • シンプル
  • 捨てる勇気
  • ユニバーサルのデザイン
  • 素人の感想は聞くが意見は採用しない
まぁ、言わんとするところは何となくわかるような気もします・・(^_^;

で、増井さんによると、GUIに関しては20年前から全く進化していない。スクロールバーなんてあれが使いやすいとは思わないけど、あれ以上のものを何で誰も思いつかないのか?

ということで、ご自身の活動としてGoldfishというAndroidの実世界GUIのフレームワークの開発をされています。どういうものかは、ここの blogで紹介されている記事をご参照いただくのがわかりやすいかと思います。

3. iCloudとSiriに見るサービスデザイン 奥出直人氏
本題であるはずのSiriに関しては、冒頭にかの有名なナレッジナビゲーターのビデオを数秒紹介して終わり(えーっ?)。

で、後はDesign Thinking(デザイン思考)というメソッドでのプロダクトやサービスデザインの話でした。カルボナーラを誰でも美味しく作れるシステムとか、医療関係のサービス開発の話で、個々の内容は興味深かったのですが、デザイン思考とはなんぞや?というところに関しては、頭が悪いのかあまり理解できませんでした(汗。

基本的な考え方として、どういう課題を解決したいのか?どういう付加価値を提供するのか?(Human Value)というところから入るのですが、そのフェーズでの重要な点は、現場が何に困っているのかを理解すること。

だけど、それを現場に行って実際に見させてもらうことが、そもそも非常に難しいこと何だと(これは多分医療用サービスを携わったことから来る経験談だと思われる)。なので、ユーザーとの信頼関係を築くことがとても重要。

そして、ここでも作ったものをユーザーに実際に使ってもらい、そのフィードバックから何度も作り直したという話を聞きました。

後は、その課題を解決する手段のTechnologyとして、いまのクラウド環境やスマートフォン、タブレット端末などは非常に強力で安価なツールになってきているので、プロトタイプがすぐに作れるからチャレンジしてみたらどうか?

そして、それがある程度成功したら、最終的にはそれをどうBusiness(どこで儲けるのか)に結びつけるのかを考えなければならないので、サービスのデザインが重要(だからデザイン思考なの?)。

そのヒントとして、大量のデータをクラウドのパワーで処理した結果を端末のI/Fの面白さにどう結びつけるのかを考えてみればいいのでは無いか?とのことでした。

とまぁ、思ってた内容とは多少違ったけども、話としては面白くて得るものが多かったセミナーでした。

2012/01/24

Hello Android1.0

最近、ネイティブのAndroid SDKを使ってアプリを作ってみているのですが、Androidの複数解像度に対応する仕組みにはほんと関心してしまいます。

1280x720でも480x320の画面でも、同じソースで全く問題が無いように(≠ 全く同じように)表示されます。もちろん、そうなるように作っているわけでしょうが、実際にやってみると、ね。

あと、UIのフレームワークとして、大画面への対応が着実に進んでいるんだなという感じがします。例えば、Androidはタブが画面の上部に表示されますが、端末を片手で操作するにはタブが上部にあると非常に使いづらいわけです。

ただ、iOSのようにタブを下部に配置するとハードキーとの兼ね合いから、それはそれで難しい問題もあるわけです。それに両手で使うタブレットでも同じアプリを使うことを考えた場合には、今度はタブは上部に配置されてた方が使いやすいはずです(持ち方にもよるが、端末下部が体に近くなる為)。

そこで、ViewPagerというものが導入されて、スワイプで画面を切り替えられるようになりました。まぁ、こいつは単にWindows Phoneの真似だろうと言われることもありますが、大画面化が進む端末に対応するには、必然的な対応ではなかったのかな?と。

そういう意味ではWindows PhoneのUIが当初からそこを見越した設計にしてるのは素直にすごいなと思うわけです。動きとしても、演出としても面白いしね。

あと、これは当初から考えてたのかどうかはわかりませんけど、いまになってみるとAndroidのバックキーがハードキーとして画面下部に配置されてるのは非常に使いやすいですね。

そういう意味で、画面の左上にバックボタンが配置されているiOSは画面の大型化には対応しづらいような気もします(あくまでも右利きを基準にした感想ですが)。

まぁ、AndroidのUIは当初からいろいろ叩かれてましたが、未完成だった分、ユースケースや端末の進化に合わせてブラッシュアップできたのが良かったのかな?

そう言えば、最近GoogleがAndroid Designのサイトを公開しましたね。これまでもUser Interface  Guidelinesのページは存在してましたが、こうやって大々的にデザイナーに向けてサイトを立ち上げたってことは、UIは当面はこれで行くよという宣言なのかも知れません。

そういう意味で、長らくオープンβ?(違うw)だったAndroid OSがICSになってようやく製品版になったんだなぁ、という印象です。ICSになってハードキーが廃止されたのも、端末によって並びが違うというのを避ける意味合いもあったのでしょうね。

というわけで、Hello Android 1.0

2012/01/15

書評:Android Security 安全なアプリケーションを作成する為に

ご挨拶が遅れましたが、2012年もどうぞ当ブログをよろしくお願いいたします。

年末くらいからネイティブのJavaでAndroidアプリの開発を始めたのですが、その際に「Android Security 安全なアプリケーションを作成する為に」という書籍が非常に参考になりそうだったので、ご紹介したいと思います。


昨今、スマホアプリのセキュリティー関連がニュースを賑わすなどしておりますが、アプリ開発者の立場としては、そのようなセキュリティ事故を起こさないようにとか、ユーザーに無用な誤解を与えるようなことはなどは、なるべく避けたいわけです。

で、この本にはAndroidアプリを開発する上で、注意すべきポイントが(これで全部では無いのでしょうが)非常によくまとまっていますので、個人的にはAndroidでアプリ開発を行なう全ての方に読んでいただきたい内容だと思いました。

特にAndroid OSは当初からアプリ連携の為の仕組みがよく考えられていて、OSから提供される機能も様々ですが、知識として知っておかないとそこの部分に脆弱性を盛りこんでしまう危険性がかなり高いことが、この書籍を読むとよくわかります。

また付録にセキュリティ対策のチェックリストが付属していますので、アプリをリリースする前にはこれで必ずチェックするなどの工程を入れておけば、うっかりミスを防ぐなどの効果がありそうです。

逆に個人的に少し残念だったのは、アプリケーションにマルウェアなどを仕込まれるなどの改竄をされた場合の検出や対策に関する内容が無かったことでしょうか?

人気の有料アプリが改竄されてGoogle以外のマーケットで無償版として配布されるなどの事例が実際に発生してますので(まぁそこまで責任取れんわという気持ちもありますが)、知識としてどういう防衛策を取り得るのか?というのは知っておきたいような気もします。

最後にこの本を全部読んだ後の感想としましては、現在のAndroidのpermissionの仕組みは細分化され過ぎてて、非常にわかりにくいのと、開発者の自助努力に頼るのだけでは限界があるような気がします。

なので、例えば設定されたpermissionのレベルに応じては、マーケット側できちんと事前審査を行うとか、あるいは端末情報を取得するようなpermissionを設定するアプリを作れるのはGoogleで認可された特定のデベロッパーだけにするとか、もう少し仕組みとして堅牢なものにして行くことを考える必要もあるのではないかと思いました。

ただ、開発者側で最低限出来ることはしっかりやっておくべきですので、この本を参考にご活用させていただきます!

[update]
アプリの改竄に関して、著者の@tao_gakuさんからblog上でご回答いただけました。感謝感激!

http://www.taosoftware.co.jp/blog/2012/01/android_security_2.html