Hatena::ブログ(Diary)

naoyaのはてなダイアリー

ウェブのこと、技術のこと、日々の出来事。

February 02, 2012

創造性の高い仕事をしたい人におすすめしたい1冊

100人が選ぶソフトウェア開発の名著選 デブサミ10周年を記念して2月21日に刊行:CodeZine が出版されます。私も一冊推薦しました。id:secondlife:20120202:1328168076 でセコンさんが公開してるのにならって、私も原稿を公開しようかなと思います。推薦したのは以下の本です。

モチベーション3.0 持続する「やる気!」をいかに引き出すか

モチベーション3.0 持続する「やる気!」をいかに引き出すか

邦題があまり好きじゃない。原著は『DRiVE ─ The Suprising Truth About What Motivates Us』です。本文の訳は良かったです。『フリーエージェント社会の到来』や『ハイ・コンセプト』の Daniel Pink さんの本です。

あの github も読んでいる本

かつてマイクロソフトがプロのライターや編集者に報酬を払って作ろうとした百科事典があります。MSNエンカルタ、という電子百科事典です。2009年3月に同製品は打ち切りとなりました。一方、ウェブの世界には、ボランティアが無報酬で作り上げた百科事典ウィキペディアがあります。至上もっとも成功したオンライン百科事典。みなさんも幾度となくお世話になっていることでしょう。

金銭的報酬によって働くプロが作ったものより、無報酬のボランティアが作ったものが勝ってしまう。インターネットが世界に広まってからそんな事例が多数見られるようになりました。MSNエンカルタではなくウィキペディア。Sun OSではなく Linux。商用データベースではなくMySQLプロプライエタリ・プロジェクトではなくオープンソース・プロジェクト。

なぜプロよりボランティアが作るそれが上回るのか。

『モチベーション3.0 持続する「やる気!」をいかに引き出すか 』は行動科学分野の研究成果をベースに、金銭的報酬のような外部から与えられる刺激 ・・・ Extrinsic Motivation によって為されるものではなく、使命感や夢中になれるほど好きという内側からの刺激 ・・・ Intrinsic Motivation によって為された成果がより良い品質のものを生み出す可能性・・・などなどについて論じた書籍です。

つまりは、アメとムチによる管理は過去の遺物で、二十一世紀の今は内的な衝動によってプロジェクトを成功に導く新しいやり方が求められていると、そんな話。

題名はいかにも自己啓発本的な微妙な雰囲気を醸し出している本書ですが、実際には、科学的前提に基づきビジネスの有り様を分析するという冷静な内容になっていますのでご安心を。原著は 『DRiVE ー The Surprising Truth About What Motivates Us』 でして、そこに関して言えばこちらのほうがまだマシかな、という気もします。

もとい、なぜこの本を紹介しようと思ったか。ソフトウェア開発者が生産性高く仕事を為すためには、いかに自分の集中力を高められるか、それにかかっています。その集中力を引き出すのに必要な要素について自覚的になりたければこの本を読みなさい・・・というのが私からのメッセージです。

エンジニアという人種はひとたびそれに集中し始めると、やがて周囲の雑音はきこえなくなり、完全にそこにのめり込んだ、異様に活性化された精神状態となります。みなさんも過去にコーディング中に、あるいはエンジニアリングでなくとも、物作りをしたり、読書をしたり、あるいは受験勉強に没頭したりという課程でそんな精神状態を味わったことがあることでしょう。著名な心理学者のミハイ・チクセントミハイはそんな精神状態を「フロー」と名付けました。

創造力の必要とされる仕事 ー 近年のソフトウェア開発がその代表的なひとつ ー においては、それに従事するひとびとがフロー状態を体験できるかどうか、それが成果の善し悪しに直結していると、科学が証明しています。人がフロー状態に入るには、Extrinsic Motivation ではなく Intrinsic Motivation に突き動かされている、ということが必要不可欠な要素です。

かつて、先進国のソフトウェア開発者はオフショア開発などによってその職業価値を失うといったような主張が幅をきかせていた頃がありました。しかし、結果的には、先進国においてもソフトウェア開発者の需要は減るどころかが益々増えて、またその価値は以前よりもっと重要になってきています。ソフトウェア開発者の平均年俸推移という経済指標がそれを端的に表していることでしょう。

サーチ、SNS、ソーシャルメディア・・・ウェブが秘める可能性がまた一つと明らかになるにつれて、既存の多数のビジネスがインターネットによって再構成されてきました。Netscape を開発した Marc Andreessen が書いた "Why Software Is Eating The World" という記事が話題になる昨今です。

ソフトウェア産業がなぜコモディティにはならなかったのか。それはソフトウェア開発がもたらす「創造的価値」という言葉に集約されると考えます。創造性が成果を左右する領域ほど、コモディティになりにくい、そんな直感がみなさんにもあるでしょう。

逆に言えば、独創的かつ創造的な価値を発揮できることが今後エンジニアであることの必須条件になっていく、とも言えるでしょう。そして創造性高く仕事をするにはフローに入ること ─ そこで、本書です。

ソフトウェア開発者としての価値は創造性の高さにあるとして、では自分の創造力をどうやって引き出すか。それはフロー時間をいかに作り出せるかにかかっています。そしてそのフロー時間を生み出すエネルギーの源泉こそが内発的動機付け ー Intrisic Motivation です。オープンソース・プロジェクトに従事するハッカーがなぜあれほど高い生産性や情熱をそこに傾けられるのか、その秘訣。

推薦図書を読んだからといって、簡単に集中人間になれる、なんてことはありません。しかし、フロー時間を生み出す要素が何かについて自覚的であれば、日々の習慣を変える指針にはなるでしょう。あるいは自分が管理する組織を、アメとムチ型から自律型に変えるのに必要な指針は何か、ということが明確になるかもしれません。

技術書ではありません。でもソフトウェア開発者が読んでおくべき一冊だと思います。そうそう、みんな大好き github 社は、出社義務もなければ納期もないという先進的な会社運営で知られていますが、本書を組織運営方針のバイブルにしているそうです。

あとがき

November 11, 2011

HBFav というはてなブックマーク iPhone アプリを作りました

ちょこちょこと余暇の時間を使って、HBFav という iPhone アプリを作りました。

f:id:naoya:20111111075034p:image:w240 f:id:naoya:20111111075035p:image:w240 f:id:naoya:20111111075036p:image:w240

HBFav は、はてなブックマークの「お気に入り」機能を閲覧するためのアプリです。はてなブックマークの「お気に入り」は、気に入ったユーザーがブックマークしたブックマークを一覧する機能、つまり、Twitter で言うところのタイムラインです。それを見る専用のアプリがほしかった、ということで作ったものです。

・・・ということで、繰り返すと、HBFav はタイムライン形式でソーシャル・ブックマークを楽しむためのアプリ。はてなブックマークのお気に入り機能を活用しているぜ! という方におすすめです。

HBFav は、App Store からインストールできます。

Kindle とともに

HBFav には、はてなブックマークに追加する機能や、公式のはてなブックマークアプリと連携してブックマークを追加する機能だけでなく、Instapaper と連携する機能をつけました。Instapaper はいわゆる「あとで読む」サービスで、これは後で読みたいなと思ったサイトを登録すると、良い感じに整形してくれ保存しておいてくれるサービスです。

PC や iPad で Instapaper を利用するのも便利ですが、ぼくはこのところ Kindle を使っています。

f:id:naoya:20111111074252j:image:w640

はてなブックマークで follow した人たちが運んで来てくれるニュースを日々眺めつつ、その場で読み切れないものは Instapaper に放り込んでおく。Insapaper の Kindle 連携機能を使うと、Insapaper が未読の記事を一日一回 daily で Kindle に送信してくれます。これを移動時間や食事時などに読んでいます。

最近はスマートフォン開発や Node.js に関心があるのですが、その辺りに詳しい人、いまで言うところのキュレーターを探してきて follow して HBFav を毎日眺める。読み切れないものは Instapaper に放り込んで、Kindle へ。これでだいぶ効率的に、この辺のキャッチアップができるようになりました。

はてなへの要望

API周りで要望がいくつかあるので、駄目もとで書いておく。

  • はてなブックマークへの要望
    • /naoya/favorite.rss に自分のブックマークを含めて欲しい
    • /naoya/favorite.rss にキャッシュが効き過ぎている
    • RSSフィードのレスポンスが良くなると嬉しい
    • offset ベースの paging ではなく時刻ベース(?)の paging 機能があると嬉しい
    • ユーザをお気に入りに add / remove できる API が欲しい
    • 特定の URL をブックマークしてる自分の follower 一覧が取れる API が欲しい
    • そのほか、公式アプリ用の undocumented な API をもし可能なら公開して欲しい
    • 時折 Atom API の WSSE 認証に失敗する不具合があるっぽい

以下、戯言です

Mark Zuckerberg は、いずれみんな、ニュースは友人知人経由で知ることになるだろうと言っていました。自分もそうなるだろうと思います。

2004年ころに、自分は新聞や大手のニュースをあまり見なくなっていて、情報ソースがほとんど個人の blog になっていることに気づいた時のことをよく覚えています。当時、知人に「最近自分は blog しか見ていない」ということを言ったら、少し怪訝な顔をされましたが、今、同じことを言ったら少しは違う反応が返ってくるのではないかと思います。

情報を取得するメディアがソーシャル・ネットワークにシフトしていくのは間違いないと思うし止められないと思います。おそらく Mark Zuckerberg はそれを facebook が成し遂げるという文脈でそのようなことを言ったのではないかと思いますが、ぼくは、彼らがそれを成し遂げるにはもう少し時間がかかるように感じます。

Stanley Millgram の「六次の隔たり」について触れた 新ネットワーク思考を読んだとき強く印象に残ったのは、6人を介せば友人知人に繋がるという話し・・・ではなく、いつも自分に重要な人生の転換期を与えるのは、強いつながりの人たちではなく弱いつながりの人達である・・・という「弱い絆の強み」のくだりでした。

親しい友人や会社の同僚は同じような生活様式あるいは同じような価値観/時間軸で日々暮らしている。一方、少し離れたつながりにいる人々は、異なる価値観、時間軸、生活様式に暮らしているから、そのどちらが自分にとって非連続な価値をもたらすかと言えば、後者だと、そういう話です。

情報は、そこに既知の事実が含まれれば含まれるほど、そこに情報量はないとみなされます。ただ、あまりにも自分の知らないことだらけでは、その情報には関心が持てません。関心のある情報のうち、情報的価値の高いものが自分にとって良い情報。そんな情報を持っているのは、強い絆の人たちではなく弱い絆の人たちではないだろうか、とそんな仮説を持っています。

そういう意味で facebook が表現するリアルグラフは、自分にとって重要なニュースを知るための情報源としてのグラフとしては、うまく機能しません。そのグラフは強い絆に偏りすぎています。Twitter のように弱い絆を実現できるグラフの方が有利でしょう。有事の際に Twitter がより(コミュニケーションインフラではなく)メディアインフラとして機能するのには、そういう側面があると思いました。

しかし、TwitterTwitter で、URL を伝搬させるインフラとしての機能には特化できていない。日々のコミュニケーションに必要なグラフつまりは強い絆と、情報源としてのグラフである弱い絆、これを切り離すことは容易にはできない。彼らはいずれ、そういう部分も包含しにくるのだとは思いますが。

何が言いたいかというと、この分野においてはソーシャル・ブックマークがいまもまだ有力なメディアないしインフラだと思っている、ということです。弱い絆のグラフを容易に構築できて、日々のコミュニケーションのような雑事によってそのグラフが乱されたりはしない。実際いまも自分にとって一番重要な情報源はソーシャル・ブックマークにおいて follow しているユーザーが作るコンテンツ。つまりはてなブックマークにおける「お気に入り」機能です。

お気に入り機能は、follow したユーザーがブックマークしたものを見る、つまり follow したユーザーのソーシャル・ブックマーク上におけるアクティビティを眺める機能です。今風に言えば、ソーシャル・ブックマークにおける個人のタイムライン、ということになります。facebookTwitter によって一般的になった News Feed / Timeline という概念をもって整理すれば、わかりやすいのではないでしょうか。

タイムラインあるいはアクティビティフィード、という観点から見ると、Twitter で「何を言ったか」より「誰が言ったか」の方が重要なことと同じように、何がブックマークされたかということより「誰がブックマークしたか」と言うことの方がずっと重要です。それに特化したアプリが欲しかった。

はてなブックマークのお気に入り機能を、タイムライン形式で眺めたかったのはそういう理由がありました。欲しかったけどなかったので、作りました。

ぼくにとってソーシャル・ブックマークで重要なのは人気エントリーでも、注目エントリーでもなく、このタイムラインだしこれから先もしばらくそれは変わらないように思います。いつか facebookTwitter あるいはその他のソーシャル・メディアがこの価値を飲み込む日が来るかもしれないがそれにはまだ時間がかかるだろうし。

はてなブックマークには、その時間の中でインターネット上のニュースメディアのソーシャル・インフラとなり得るチャンスが、facebook/Twitter 時代になった今でもまだあるでしょう。ソーシャル・インフラになるというのは Twitter が目指しているビジョンですが、はてなブックマークもそういうビジョンを持てる、持っても良いサービスだろうと、そんなことを思ったりした昨今です。

October 20, 2010

Titanium Mobile についての勉強会資料

昨日は gumiStudy#5 でした。何か Tech Talk を、ということだったので最近いじっていた Titanium Mobile について整理して、紹介してきました。

(フォントがひどいですね・・・すみません。http://www.slideshare.net/naoya1977/titanium-mobile/download からダウンロードできます)

先日書いたエントリ (http://d.hatena.ne.jp/naoya/20101011/1286799669) のとおり、Titanium Mobile を使うと JavaScript でネイティブアプリを開発することができます。しかも iPhone/Android マルチプラットフォーム対応。最近は BlackBerry への対応も進んでいるようです。

最初はスクリプト言語でネイティブアプリと言ってもいろんな制限があったり、思うようなインタフェースにならないのではないかと半信半疑だったのですが、実際に色々作って見ると、典型的な iPhone アプリケーションであれば何の問題もなく作れてしまいました。これは結構驚きですね。

iPhone/Android でもう少し深い開発をされている方から見ると足りない機能やAPI、あるいは細かい制御が難しいといった側面があるのかもしれませんが、いわゆるクラウド側にデータを置いてそれを表示するビューワー的なものを作るという定番のアプリ開発においては、十分に実用的であると思います。

発表後、質問で PhoneGap など他の類似する SDK とどう異なるのか質問をいただいたので、その辺も後日調べてみようと思います。

October 11, 2010

Titanium - JavaScriptiPhone/Android アプリを作る

Titanium MobileJavaScriptiPhone/Android のアプリ (not Webアプリ) を開発できる開発環境。詳しくは Titaniumで始めるモバイルアプリ作成の基礎知識(1/3) - @IT などに解説があります。

少し時間があったので、JavaScript で作るというのがどんな感じか試してみました。作ったアプリは

f:id:naoya:20101011211616p:image:h300 f:id:naoya:20101011211617p:image:h300 f:id:naoya:20101011211618p:image:h300

こんな感じで TableView があり、選択すると WebView でアプリ内ブラウザが立ち上がる、ブラウザはツールバーで「戻る」や「リロード」が可能。あとはタブコントロールがあったり・・・という単純なもの。初期起動画面のサイトリストは、HTTP でローカルに立てたサーバーから JSON で読み込んでいます。

Web上のドキュメントを見ながら2, 3時間試行錯誤で一応の形になりました。

Titanium での開発の実際

Titanium は開発環境ではありますが、IDE がついてくるわけではありません。今回は Emacs + js2-mode.el でゴリゴリ書きました。個人的には、IDE よりこのスタイルの方が好み。

JavaScript 中で、Titanium.UI.createWindow(...) といった API を呼び出して iPhone/Android の UI を組み立てていきます。コードができたら、"Titanium Developer" という開発ツールでビルド。

f:id:naoya:20101011211619p:image:w480

ビルドが完了するといつもの iPhone エミュレータが立ち上がり、アプリが動きはじめます。ビルドの裏側で何が行われているかまだ把握していないのですが、立ち上がるアプリは JavaScript によるWebアプリではなく、ネイティブUIを持ったネイティブアプリです。

JavaScript で書くコードは、以下のようなコードになります。

app.js が Titanium アプリのエントリポイントになるスクリプトで、アプリを立ち上げるとまずはこのスクリプトが実行されます。

Titanium.UI.setBackgroundColor('#000');
var tabGroup = Titanium.UI.createTabGroup();

var menu = Titanium.UI.createWindow({  
  title :'メニュー',
  backgroundColor :'#fff',
  url : 'menu.js'
});

var tab1 = Titanium.UI.createTab({  
    icon:'KS_nav_ui.png',
    title:'メニュー',
    window:menu
});

var config = Titanium.UI.createWindow({
  title : '設定',
  backgroundColor : '#fff',
  url : 'config.js'
});

var tab2 = Titanium.UI.createTab({  
    icon:'KS_nav_views.png',
    title:'設定',
    window: config
});

tabGroup.addTab(tab1);  
tabGroup.addTab(tab2);  
tabGroup.open();

Window を生成し、タブメニューを組み立てています。これで画面下部のタブメニューが表示されるようになります。各タブをクリックした後に起動するのは url プロパティで指定した menu.js や config.js です。

menu.js は、上記のスクリーンショットGREEFacebook などの一覧が出ているウィンドウを担当する箇所。

var win = Titanium.UI.currentWindow;
var xhr = Titanium.Network.createHTTPClient();

xhr.open('GET', 'http://localhost:3000/menu');
xhr.onload = function () {
  var data = JSON.parse(this.responseText);
  var tv = Titanium.UI.createTableView({ data : data });
  tv.addEventListener('click', function(e) {
    var row = e.rowData;
    var w   = Ti.UI.createWindow();
    var wv  = Ti.UI.createWebView();
        
    var btn_back = Ti.UI.createButton({
      title : '戻る'
    });
    btn_back.addEventListener('click', function () { wv.goBack(); });

    var btn_reload = Ti.UI.createButton({
      systemButton : Ti.UI.iPhone.SystemButton.REFRESH
    });
    btn_reload.addEventListener('click', function () { wv.reload(); });

    wv.url = row.url;
    w.toolbar = [ btn_back, btn_reload ];
    w.add(wv);
    win.tab.open(w);
  });

  win.add(tv);
};
xhr.send();

Titanium.Network.createHTTPClient() で生成した HTTP クライアントで非同期HTTPでJSONを取得し、コールバック中でメニュー (TableView) を組み立てています。テーブルの各項目をクリックすると動的に WebView が生成されて、GREEFacebook がその中に表示される、という具合。

今回は Titanium の組み込みの API だけを使って書いていますが、jQuery などのライブラリを読み込んで使うこともできるそう。

基本的にアプリを作っていく流れはこれだけ。JavaScript を書いては Titanium Developer でビルドしてエミュレータで確認、という感じです。Objective-C 生で書くときに比べてやはり素早く書けるし、コード量も少ない。楽で良いです。各種 API でカメラや位置情報などデバイスが提供する機能もちゃんと使えます。

間に抽象レイヤが入っている分 Objective-C/Java で作るのに比べると細かい制御ができなかったりというところはあるのかもしれません。とはいえ、十分に実用的なアプリを、書き慣れた JavaScript で手軽に(しかもクロスプラットフォームで)作れるというのはなかなかに魅力的・・・というわけで、Titanium++ です。

おまけ

JSON を返すサーバは Mojolisious::Lite で作りました。Mojolicious はこういう Quick Hack の時にも便利。

use utf8;
use Mojolicious::Lite;

app->renderer->default_format('json');

get '/menu' => sub {
    my $self = shift;
    my $menu = [
        {
            title    => 'GREE',
            hasChild => 1,
            url      => 'http://t.gree.jp/',
        },
        {
            title    => 'Google',
            hasChild => 1,
            url      => 'http://google.com/'
        },
        {
            title    => 'Facebook',
            hasChild => 1,
            url      => 'http://touch.facebook.com/',
        },
    ];
    $self->stash(json => $menu);
};

app->start;

Mojolicious::Lite で WebSocket を使ったチャットを作る

WebSocketで目指せ“リアルタイムWeb”! - @IT という記事を読みました。node.js という V8 を用いたサーバーサイド JavaScript フレームワークを使うと簡単にイベント駆動のサーバが書ける、node-websocket-server.js を使うと node.js で WebSocket サーバが実装できる。Ajax による polling や Long Polling などと WebSocket のアーキテクチャ比較といった内容でした。

WebSocket を使うと手軽にサーバプッシュ的なアプリケーションが作れて嬉しいのですが、現時点では、HTTPサーバー側で WebSocket を処理する下地の実装をどう用意するかというところがひとつ課題でしょう。node.js はその回答のひとつとして、なかなか面白いですね。

Perl で WebSocket サーバ ・・・ Mojolicious::Lite

さて、記事に触発されつつサーバー側を JavaScript ではなく Perl で書けたらいいなと言うことで Mojolicious::Lite を使ったサンプルを作ってみました。Mojoliciious には WebSocket を処理できるサーバー実装が同梱されていて、

use Mojolicious::Lite;

websocket '/echo' => sub {
    my $self = shift;
    $self->receive_message(sub {
        my ($self, $message) = @_;
        $self->send_message("echo: $message");
    });
};

app->start;

と書いて

% perl app.pl --daemon

でサーバーが起動、 ws://localhost:3000/echo が WebSocket のエンドポイントになり、receive_message() に渡したコールバックが、クライアント側からメッセージを受信する度にキックされるようになります。ハンドシェイクそのほかは Mojo が適当に処理してくれます。お手軽です。

サンプルの WebSocket チャットのコード

以下、サンプルで作ってみたチャットです。/ でチャット画面をHTMLで返す。/echo が WebSocket のエンドポイント。メッセージを受け取ると時刻と受け取ったテキストを、接続しているすべてのクライアントに送ります。

#!/usr/bin/env perl
use utf8;
use Mojolicious::Lite;
use DateTime;
use Mojo::JSON;

get '/' => 'index';

my $clients = {};

websocket '/echo' => sub {
    my $self = shift;

    app->log->debug(sprintf 'Client connected: %s', $self->tx);
    my $id = sprintf "%s", $self->tx;
    $clients->{$id} = $self->tx;

    $self->receive_message(
        sub {
            my ($self, $msg) = @_;

            my $json = Mojo::JSON->new;
            my $dt   = DateTime->now( time_zone => 'Asia/Tokyo');

            for (keys %$clients) {
                $clients->{$_}->send_message(
                    $json->encode({
                        hms  => $dt->hms,
                        text => $msg,
                    })
                );
            }
        }
    );

    $self->finished(
        sub {
            app->log->debug('Client disconnected');
            delete $clients->{$id};
        }
    );
};

app->start;

__DATA__
@@ index.html.ep
<html>
  <head>
    <title>WebSocket Client</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" ></script>
    <script type="text/javascript" src="/js/ws.js"></script>
    <style type="text/css">
      textarea {
          width: 40em;
          height:10em;
      }
    </style>
  </head>
<body>

<h1>Mojolicious + WebSocket</h1>

<p><input type="text" id="msg" /></p>
<textarea id="log" readonly></textarea>

</body>
</html>

クライアントの js の中身。WebSocket API で /echo に接続して入出力を適当に処理。

$(function () {
  $('#msg').focus();

  var log = function (text) {
    $('#log').val( $('#log').val() + text + "\n");
  };
  
  var ws = new WebSocket('ws://localhost:3000/echo');
  ws.onopen = function () {
    log('Connection opened');
  };
  
  ws.onmessage = function (msg) {
    var res = JSON.parse(msg.data);
    log('[' + res.hms + '] ' + res.text); 
  };

  $('#msg').keydown(function (e) {
    if (e.keyCode == 13 && $('#msg').val()) {
        ws.send($('#msg').val());
        $('#msg').val('');
    }
  });
});

Google Chromelocalhost:3000 にアクセス、ちゃんと動きました。

f:id:naoya:20101011153308p:image

こうして WebSocket のサーバー側を Perl で実装できる、とわかれば後は既存の資産を生かしていろんなことが考えられますね。先の記事の Activity Monitor のようなものを、サーバーで Perl で実装してしまって、リモートのサーバーステータスをグラフィカルに表示するとかアイデアは尽きません。

ほか

September 30, 2010

Scripting Layer for AndroidPerl x Android

Shibuya Perl Mongers テクニカルトーク#14 に行ってきました。諸々面白かったですがパネルディスカッション、LT ともに id:kazuhooku さんの発表が良かったですね。

さて、Scripting Layer for Android (SL4A) を使って、PerlAndroid を hack する話をしてきました。SL4A は jRubyPerlPythonPHP などの言語を Android で使えるようにするアプリ。それぞれの言語からは AndroidFacade API と呼ばれる API で、Android のUIやカメラを操作できるというものです。

発表資料は以下です。

今日の発表では PerlAndroid 上の Toast (通知用のメッセージ領域) に echo を返す echo サーバーを作るという簡単なスクリプトを紹介しました。

で、面白いなと思ってその後も少しウェブを巡っていると http://handasse.blogspot.com/2010/09/pythonandroid5.html で、"Python を使って Android 端末を5分でリモートカメラにする方法" なんて hack が見つかる。これは SL4A で Android 端末上にHTTP サーバーを動かして、そのサーバーに HTTP GET すると、端末が API でキックされて写真を撮影する。その写真は GET を投げたブラウザ側に表示されるという hack。面白い!

というわけで、Perl でもやってみようと試みる。

HTTP サーバは HTTP::Server::Simple::PSGI で書けば数行で書ける。問題は、SL4A で追加の CPAN モジュールを動かすところですが、これは組み込みでは足りないモジュールを SDカード上の site_perl ディレクトリに放り込んでやれば ok。HTTP::Server::Simple::PSGI は依存が少ないので、都合が良い。

エミュレータ上のそれに転送するには

% adb -e push /Library/Perl/5.10.0/HTTP /sdcard/com.googlecode.perlforandroid/extras/perl/site_perl/HTTP

などとする。上記は HTTP 以下のモジュールをすべて丸ごと転送する例。

これで FileHandle.pm、File/* HTTP/* あたりを転送してやった。Pure Perl モジュールのディレクトリ全部を丸ごと放り込んでも良いかもしれない。

カメラ操作の HTTP サーバーの実装は以下。Python のそれを Perl に移植しただけ、簡単。

#!perl
use strict;
use warnings;

use HTTP::Server::Simple::PSGI;
use IO::File;
use Android;

my $pic = '/sdcard/snapshot.jpg';
my $droid = Android->new;

my $app = sub {
    my $env = shift;
    $droid->cameraCapturePicture($pic);
    local $/;
    my $fh = IO::File->new;
    $fh->open($pic) or die $!;
    return [
        200,
        [ 'Content-Type' => 'image/jpeg' ],
        [ $fh->getlines ],
    ];
};

my $server = HTTP::Server::Simple::PSGI->new(10082);
$server->app($app);
$server->run;

試しにエミュレータで動かしてみたら...

f:id:naoya:20101001023444p:image

という感じで getprotobyname() の警告は出ているものの、なんとかバインドできている。CPAN モジュールの問題は解決されたし、echo サーバーが難なく動いたことを考えるとこれでいけるっぽい。

よーし、あとは実機のカメラで動かして・・・と思ったのですが、Xperia では SL4A の Perl (だけでなく Python なども) 動かない。 手元には Xperia しかない、というわけでここで終了。残念。でもまあ、CPAN モジュールを転送してやれば動くことが分かったし、HTTPサーバーも立てられそうだしというので収穫はありました。今日の進捗はここまでです。

SL4A は、まだデバッグが少し面倒ではありますが、本当にちょっとしたネタを実装するだけならすぐに仕上げられるのでなかなか楽しめます。