Hatena::ブログ(Diary)

Hacking My Way 〜 itogのhack日記 RSSフィード Twitter

2014-04-23

Maker Faire ShenZhen、そしてbay area

先日、深センのMaker Faireに行ったのだが、行くかどうかものすごく迷っていた、というか直前までは行かないつもりだった。というのも、直近で深センに用事があったわけではないので、ビジネス的には行く必要はなかったし、出展するならまだしも、出展申込期間は過ぎてしまったし、ただ見に行くのもなぁと思っていた。だが、考えてみればMake:のイベントには今まで出展者としてしか行ったことがなく、純粋な見学者として行くのも一度くらいはいいかなと思って行くことにした。

Maker Faire ShenZhenには一昨年、mini Maker Faireとして開催された第一回で展示をした。この頃は深センのことなんてなにも知らずに飛び込みんだものだが、その後深センには何度も通ったため、もう勝手知ったると言った感じだ。Maker Faire ShenZhenは深センの西の玄関、蛇口フェリーターミナルから地下鉄で一駅の「海上世界」という場所で行われた。

f:id:itog:20140406145156j:image

当日日本を早朝に発って、会場には昼過ぎに着いた。その場に行くまで知らなかったのだが、なんと屋外での開催。残念ながら雨に見舞われていたが、それでも人混みが途切れることのない盛況ぶりだった。イベント自体のレポートは他所に譲るが、日本ともbay areaともまた違った独特な雰囲気の中で大きな刺激を受けたのは言うまでもない。

f:id:itog:20140407125818j:image

ただ、見るのは楽しいし刺激も受けるのだが、見てる時間があったら自分でモノを作りたいし、作ったものをより多くの人に楽しんでもらいたい、と思ってしまうのが自分の性分だ。


そんな二日目。知り合いのブースに行ってみると、出展者の一人が体調不良でダウンしたため、店番が足りないというのだ。Makeの神は私に展示をしろと仰っているようだ。それなら仕方ない、と持参したFourBeatを展示。中国の子どもたちにも、FourBeatは大人気、というか今までで一番容赦無く叩かれたと思うw

f:id:itog:20140407145236j:image

FourBeatは今年、2度目のクラウド・ファンディングで300万円という、国内にしては大きな目標を掲げたのだが、成立させることが出来ず、なかなか苦しい状況が続いている。そんな日々の中で私は、少しずつ本質を見失っていたのかもしれない。

FourBeatをガンガン叩いて無邪気に笑う子どもたち、真剣になる大人たちを見ていると、これでいいんだって思う。理屈で説明することよりも、目の前で楽しんでいる人がいる。それが自分の内から湧き出るモチベーションだ。


だから、迷っていたMaker Faire bay areaにも行くことにした。かわりにGoogle I/Oは諦めるし、さすがに西海岸までは深センのような軽い気持ちでは行けないからそれなりの準備をしないといけないけどね!

2014-04-22

香港国際空港から深セン(蛇口)への行き方

日本から深センへはいくつか行き方がありますが、香港経由だと飛行機の本数が多く、香港エクスプレス航空というLLCが飛んでいるためスケジュールや費用面で有利です。

香港空港から深センへは、地下鉄、バス、乗り合いタクシー、などいろいろありますが、以下で説明するフェリーを使った方法のみ、香港に入境することなく直接中国本土に入れるので、面倒な手続きをしなくて済みます。

フェリーが着く深センの蛇口港は地下鉄とも直結なので、その後の移動にも困らず、深センの西側に行くならオススメです。

香港から深センへ

香港国際空港に降りたら案内板を見てフェリーチケット売り場に行きます。

f:id:itog:20140406115542j:image:w400

ここで深セン蛇口行きのチケットを買います。クレジットカードOK。

f:id:itog:20140406115647j:image:w400

チケット、220香港ドル。

f:id:itog:20140406111146j:image:w400

チケットカウンターの裏側の角あたりにフェリー乗り場への入り口がありますが、入れるのは出発の30分前になってから。

f:id:itog:20140406130141j:image:w400

エスカレーターを降りて行って、フェリーポートに移動する地下鉄に乗ります。

f:id:itog:20140406130353j:image:w400

つり革。

f:id:itog:20140406130818j:image:w400

移動は一駅だけで、フェリーポートにつきます。

f:id:itog:20140406131025j:image:w400

綺麗な建物です。

f:id:itog:20140406131029j:image:w400

案内板でフェリー乗り場を確認します。

f:id:itog:20140406131211j:image:w400

こちらが蛇口行きのフェリー。

f:id:itog:20140406131453j:image:w400

乗り込みましょう。

f:id:itog:20140406133237j:image:w400

f:id:itog:20140406133251j:image:w400

f:id:itog:20140406133306j:image:w400

フェリー船内。これはやけに新しい船だなぁ。

f:id:itog:20140406133511j:image:w400

船内に入出境カードがあるので早めに記入しておきましょう。大きくは揺れないけど苦手な人は移動中書くと酔うかも。

f:id:itog:20140406133658j:image:w400

30分ほどで到着です。

f:id:itog:20140406140937j:image:w400

パスポートコントロールを通って、港のロビーへ。帰るときはここでチケットを買います。両替所やATMもあります。

f:id:itog:20140406142138j:image:w400

おまけ:蛇口港から地下鉄の駅まで。

ロビーに看板がありますがどこ出てもだいたい同じ。

f:id:itog:20140406142153j:image:w400

ロビーを出て左手に進みます。

f:id:itog:20140406142359j:image:w400

地鉄の案内のとおりに進みます。

f:id:itog:20140406142539j:image:w400

このあと看板がなくて一瞬「?」ってなりますが、ここを右に折れたあと歩道を車道に当たるまで進んだら左右どちらにも入り口があります。

f:id:itog:20140406142610j:image:w400

これが地下鉄の入り口。

f:id:itog:20140406142821j:image:w400

2014-03-26

Boltsフレームワークで非同期処理を書く

先日、ParseからBoltsというフレームワークが発表されました。発表された時に機能をさらっと見た感じだとJSのpromiseがJavaで使える!continueで繋げるのね、ふむふむーこれは便利ーって思ったんだけど、実際使おうと思ったらけっこう理解が難しかったのと、Parseのクラスを使った例が多くて汎用的に使う例がおまけっぽくしか書かれてなかったのだ誰でもわかるBoltsの説明をしてみます。

準備

以下からBolts-Android.tar.gzをDLして展開し、bolts.jarを取得したらプロジェクトに追加し、ビルドパスを通しておきます。

https://github.com/BoltsFramework/Bolts-Android/releases


実装

Taskの使い方

タスクというとAsyncTaskのdoInBackground()のように、中にメソッドを持っていそうな気がするのですが、BoltsにおけるTaskは非同期処理の管理をするクラスで、JSのPromisesのJava版という感じです。Promisesって名前にしてくれればよかったのにね!

まずはJavaで普通に非同期処理をするメソッドを作ってみましょう。

public void asyncMethod(final String param) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
  // 実際の処理はここで終了
}
}).start();

return ; // このメソッド自体はすぐにリターン
}

Taskに非同期処理の管理を任せるにはこのメソッド内でTaskのインスタンスを生成してメソッドの戻り値でtaskを返し、処理が終了するところでsetResult()でTaskに通知します。

public Task<String> asyncMethod(final String param) {
	final Task<String>.TaskCompletionSource task = Task.<String> create();
	new Thread(new Runnable() {
		@Override
		public void run() {
			Log.v(TAG, "Running task (" + param + ")");
			try {
				Thread.sleep(1 * 1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			task.setResult(param);
			// エラーの場合はsetError()
			//task.setError(new RuntimeException("An error message."));
		}
	}).start();
	return task.getTask();
}

呼び出し側は返ってきたTaskのcontinueWith()メソッドで終了後の処理を書きます。

asyncMethod("hoge").continueWith(new Continuation<String, Void>() {
    @Override
    public Void then(Task<String> task) throws Exception {
        // 非同期処理の実行が終了した
        Log.v(TAG, task.getResult());
       return null;
    }
});

continueWith()の引数に渡せるのはContinuationというインターフェースを実装したインスタンスです。

JavaだとGenericsとかでどうしても見づらいところはありますが、asyncMethod()が終了したところで then()が呼ばれます。

メソッドチェーンでつなぐ

この場合非同期処理が単発なので、スレッド内に終了後の処理を書くのとそんなに変わらないのですが、この非同期処理を連続させてみるとどうでしょう?

同じメソッドを、パラメータを変えて連続で読んでみます。

public void runChainingTasks() {
	asyncMethod("foo")
			.onSuccessTask(new Continuation<String, Task<String>>() {
				@Override
				public Task<String> then(Task<String> task) throws Exception {
					return asyncMethod(task.getResult() + "bar");
				}
			}).onSuccessTask(new Continuation<String, Task<String>>() {
				@Override
				public Task<String> then(Task<String> task) throws Exception {
					return asyncMethod(task.getResult() + "baz");
				}
			}).continueWith(new Continuation<String, Void>() {
				@Override
				public Void then(Task<String> task) throws Exception {
					Log.v(TAG, "Chain finished : " + task.getResult());
					return null;
				}
			});
}

このようにネストせずに書けます。ネストではなくメソッドチェーンで書けるというところがポイントです。

これをJavaで普通に書こうとすると、以下のようにどんどんネストしていくことになり、書くのも面倒だし可読性も悪くなっていきます。

public void pyramidAsync() {
	new Thread(new Runnable() {
		@Override
		public void run() {
			// do something 1
			new Thread(new Runnable() {
				@Override
				public void run() {
					//do something 2
					new Thread(new Runnable() {
						@Override
						public void run() {
							// do something 3
						}							
					}).start();
				}			
			}).start();
		}
	}).start();
}

複数タスクを連続実行する

非同期処理の数が増えるとこのTaskの利点が活きてきます。

上記のメソッドチェーンと基本は同じですが、forループ内でtaskに.continueWithTask()をつなげていくことで、ある処理をが終わったら次の処理を、それが終わったらまた次を、というように連続して非同期処理を実行できます。

public Task<String> series(List<String> results) {
	Task<String> task = Task.forResult(null);
	for (final String result : results) {
		task = task.continueWithTask(new Continuation<String, Task<String>>() {
			@Override
			public Task<String> then(Task<String> task) throws Exception {
				return asyncMethod(task.getResult() + ", " + result);
			}
		});
	}
	return task;
}
複数タスクを同時実行する

複数の処理を同時実行する場合、whenAll()というメソッドを使えば、すべての処理が終了した時の待ち合わせが出来ます。

Taskのリストを作って、whenAll()に渡します。

public Task<Void> parallel(List<String> results) {
	ArrayList<Task<String>> tasks = new ArrayList<Task<String>>();
	for (String result : results) {
		tasks.add(asyncMethod(result));
	}
	return Task.whenAll(tasks);
}

ソースはこちら

https://github.com/itog/BoltsAndroidSample

2014-03-11

TestFlight買収に見る無料サービスの怖さ

なにかが「無料」ある場合にはなぜそれが無料なのかを十分に考えないといけない。

ケータイ端末が無料なのは、通信料など他の費用でその分を回収しているから、というのは比較的分かりやすいが、これがウェブサービスとなるとけっこう複雑になってくる。

GoogleはGmail, Google Drive, その他さまざまな質の高いサービスを無料で提供しているが、それらにかかる費用は広告によってもたらされた利益で賄われている。GmailはともかくGoogle Driveなどは検索とは直接関係がない。Googleほど有名であれば、彼らが検索連動広告で無尽蔵の収入を得ているから、とわかるのだが、利益構造のわからない会社が無料でこれほどのサービス提供していたとしたら、なにか裏があると思ったほうがいい。

よくあるのが、個人情報を収集されているとかそういった類のものなのだが、スタートアップが提供しているサービスの場合はちょっと状況が違う。

スタートアップ提供しているサービスは、利益は度外視してユーザ数やPVなどを増やし、規模が十分になってからビジネスモデルを考えるという戦略をとっている場合が多い。一定の容量だったり回数まで無料で使え、それ以上を求めるユーザから課金するフリーミアムモデルが定番だ。

利益が出るまでは増資によって資金調達するので、直近で収益がなくても特別裏があるわけではない。

ParseというBaaSサービスがある。2013年4月にFacebookに買収されたが、2011年までに$7Mを調達し、優秀な技術者を多く抱え、REST APIからiOS, Android, JavaScriptなどの各種でほぼ同機能でかつエレガントなクライアントAPIを提供していた。

Parseのビジネスモデルはフリーミアムモデルだ。スケールするビジネスなので最初は赤字でもユーザを獲得していく必要があるので、無料でも充実した機能を提供していたし、有料プランもちゃんと用意されていた。

Facebookに買収された後も、とくにFacebook色に染まることもなく、それまでと変わらずサービスが続いている。


TestFlightを2012/3に買収したBurstlyはそれまでに$7.3Mを調達しているので当面は赤字でも良いサービスを提供しているし、普通に資金調達は出来るだろうと思っていた。

買収から1年後には、サービス拡大路線を示す様に、はAndroid版を公開。

https://twitter.com/itog/status/306253802061848578

ところが、、、TestFlightは、無料プランしか持たなかった。

たとえ売上が小さかったとしても、有料プランあるいは他の収益構造がないというのは不自然だった。有料プランがいつ発表されるのか、どの様に課金されるのかというのはずっと気になっていたのだけれど、まさかの結末を迎えることになる。

突然Android版終了のお知らせ。

この時点では原因がわかってなかったので、ユーザの声が上がれば存続の可能性もあるんじゃないかと思っていたんだけれど、Appleの買収されることが明らかに。

最近は先のParseの例のように、買収をしても元のサービスを継続する例が多い気がしていたのだが、iOSとAndroidのようなドコンペティター関係だと致し方ない。先に有料プランがあれば、少なくとも契約期間内はサービスを継続しなくてはならなかったかもしれないけれど、そんなことを言っても後の祭りだね、、、

無料ツールにはこういった危険があることも意識しておかなくてはいけない。

開発ツールの囲い込みは、競合側の開発者にとってはかなりの嫌がらせ。Appleがこういうことをやってくるということは、逆にGoogleが仕掛ける場合だって考えられちゃうね。これを期に、AppleとGoogleによる開発者支援ツールの奪い合いが始まってしまわないことを願います、、、

2014-03-10

GenymotioでGoogle Play Servicesを使えるようにする

Androidの開発環境の不満の一つにエミュレータの動作が重い、ということがある。iOSのシミュレータが軽快に動くのと比較され、Androidがdisられる要員の一つになっている。

実機がいつも手元にあればいいのだが、端末ごとに挙動の違う問題を解決するために、さまざまな画面サイズやその他スペックの端末を常に手元に持っておくというのは現実的ではない。

そこで導入したいのがGenymotion.

GenymotionはAndroidのX86エミュレータだ。SDKに含まれているARMのエミュレータに比べると格段に動作が機敏で通常の開発マシン上で十分実用出来る。

http://www.genymotion.com/


このGenymotionを使う上で大きな問題が一つある。それは、Genymotionで実行出来るイメージにはGoogle Play Appsが入っていないため、Googleライブラリを使ったアプリをインストールしようとすると以下のエラーが出てインストールできない。

INSTALL_FAILED_MISSING_SHARED_LIBRARY

同様に、X86のためARMを条件としているアプリもインストールできずに下記エラーとなる。

INSTALL_FAILED_CPU_ABI_INCOMPATIBLE

以下手順でこれらのエラーが出なくなる。

ARM Translation, Google Appsインストール手順

  1. ARM Translation Installer v1.1

Google Apps for Android 4.x (必要なバージョン)

  1. 以下のファイルをDLする
  2. Genymotion VMを起動してホーム画面にします
  3. Genymotion-ARM-Translation.zipをGenymotion VMにドラッグアンドドロップします。
  4. “File transfer in progressが表示されたあとダイアログが出るのでOK

f:id:itog:20140310115400p:image:medium

  1. 以下adbコマンドでGenymotion VMを再起動します。

adb reboot

  1. 再びホームスクリーンを開いて今度は先ほどDLしたGoogle AppsのzipをDrag&Dropしてダイアログが出たらOK
  2. 終了したら再起動します

基本これでOK。Google PlayでGoogleアカウントにログインしてアプリを更新しておくほうが良い。


参考)

http://forum.xda-developers.com/showthread.php?t=2528952

あわせて読みたいブログパーツ テクノラティのお気に入りに追加する