2007年12月24日

引っ越します

このブログを個人ドメイン(kazhik.net)のほうに移すことにしました。livedoorの無料版は無条件で広告が入るようになってしまったためです。引越先はhttp://kazhik.net/tech/です。


2007年12月13日

Android覚え書き・キーイベントとマウスイベントの取得

前回のコードは動画と「再生」「停止」ボタンが重なってしまっているのがイマイチだった。携帯端末の場合はハードキーに機能を割り当てるのが普通だと思うので、SurfaceViewを拡張したクラスを作ってみた。

public class MovieView extends SurfaceView {
	private MediaPlayer mMediaPlayer;

	MovieView(Context context) {
		super(context);

		setFocusable(true);

		mMediaPlayer = new MediaPlayer();
		Surface sPlay = getHolder().getSurface();
		mMediaPlayer.setDisplay(sPlay);

		mMediaPlayer
				.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
					public void onCompletion(MediaPlayer mp) {
						mp.reset();
					}
				});
	}
	public void setDataSource(String path) {
		try {
			mMediaPlayer.setDataSource(path);
		} catch (IOException e) {
			Log.e("", e.getMessage());
		}

	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		int currPos = mMediaPlayer.getCurrentPosition();
		if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
			if (currPos <= 0) {
				mMediaPlayer.prepare();
				mMediaPlayer.start();
			} else {
				mMediaPlayer.stop();
				mMediaPlayer.reset();
			}
		}
		return true;
	}

	@Override
	public boolean onMotionEvent(MotionEvent event) {
		int currPos = mMediaPlayer.getCurrentPosition();
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			if (currPos <= 0) {
				mMediaPlayer.prepare();
				mMediaPlayer.start();
			} else {
				mMediaPlayer.stop();
				mMediaPlayer.reset();
			}
		}
		return true;
	}
}

デフォルトの状態だと、キーイベントはActivityのOnKeyDown()やOnKeyUp()、マウスイベントはView.OnMotionEvent()で取得する。フルスクリーンで動画を再生する場合はキーイベントもViewで取ることにしたほうが分かりやすくなるので、そうしてみた。setFocusable(true)でフォーカスを取れるようにすればキーイベントも取れるようになる。上の例では、四つの方向キーの真ん中にあるキーの押下、またはマウスクリックで再生したり停止したりできるようにした。

OnMotionEvent()で取れるマウスイベントはUP, DOWN, MOVE, CANCEL。iPhoneのマルチタッチはAndroidでは実現できないようだ。ダブルクリックも自前で実装しなきゃいけないらしい

画面のレイアウトを定義するXMLファイルで拡張したクラスを使う方法はBuilding Custom Componentsというページに解説されているが、まだうまくいっていない。


2007年12月05日

Android覚え書き・動画ファイル再生

動画ファイルを再生してみた。

音楽ファイルと同様にandroid.media.MediaPlayerを使う。表示領域はSurfaceViewで作っておいてMediaPlayer.setDisplay()で関連づける。Content Providerを使う方法はしばらくできそうもないので直接ファイルを指定する方法にした。

getWindow().setFormat(PixelFormat.TRANSLUCENT);
setContentView(R.layout.main);

mMediaPlayer = new MediaPlayer();
try {
	mMediaPlayer
		.setDataSource("/data/data/net.kazhik.android.secondplayer/video002.3gp");

	SurfaceView svPlay = (SurfaceView) findViewById(R.id.play_view);
	Surface sPlay = svPlay.getHolder().getSurface();
	mMediaPlayer.setDisplay(sPlay);
} catch (IOException e) {
}

SurfaceViewを機能させるためにはActivityが持っているウィンドウを半透明にしなければならないようだ。上のコードの一行目。これがないと音声だけで映像は出ない。サンプルコードのコメントに書かれているのだが、気がつかなくて何時間も悩むことになってしまった。

ソースファイル:SecondPlayer20071205.zip


2007年11月30日

Android覚え書き・音楽ファイル再生はまだ無理かも?

Media APIの解説ページには音楽ファイルのパスを指定して再生する方法が書かれているが、どうもAndroidのファイルシステムは一般のOSとは違うらしい。アプリケーションデータの扱い方を解説するページを見ると、ファイルを含めて全てのアプリケーションデータは各アプリケーションに固有のものだ、と書かれている。つまり、音楽ファイルがあって音楽再生アプリがあるのではなくて、音楽再生アプリの一部として音楽ファイルがあるということ。そしてアプリケーションデータを他のアプリケーションでも使えるようにするための仕組みとしてContent Providerがある。

Content Providerが提供するデータにアクセスする際は"content://"で始まるURIの形式で指定する。Media APIの解説ページに三つ目の方法としてWeb上にあるMP3ファイルのURIを指定する方法が書かれているので、この方法でローカルにあるファイルを"content://"の形式で指定する方法もありそうだ。

しかし、アクセス方法の解説ページには写真データのURIとして"content://images/media/128"などという例が出てくるが、音楽ファイルの例はない。「Androidには、音楽ファイル、画像ファイル、電話番号など様々なタイプのデータに対するContent Providerがある。Content Providerの一覧はandroid.providerパッケージにあるクラスを通じて提供されている」と書かれているが、android.providerのリファレンスページを見ても音楽ファイルに関する記述はない。

どうにもならないのでGoogleグループのAndroid Developersで質問しようとしたら、Note About API Documentationという記事が先頭に出ていた。APIのドキュメントに書かれていないものはたぶん実装もされていない、というアナウンスだ。もう少し待て、ということ。


2007年11月27日

Android覚え書き・ファイル入出力

adb pushで転送した音楽ファイルを再生することは可能、ということが分かったので、次は指定したディレクトリにあるファイルのリストを取得できるかどうかを調べてみた。

**********************
public class FirstPlayer extends Activity {
  private ArrayList mFileNameList;
	
  private void getFileNameList(String dirName, String extension) {
    File f = new File(dirName);
    if (!f.isDirectory()) {
      return;
    }
    File files[] = f.listFiles();
    for (int i = 0; i < files.length; i++) {
      if (files[i].getName().endsWith(extension)) {
        mFileNameList.add(files[i].getAbsolutePath());
      }
    }
  }
**********************

指定したディレクトリにある指定した拡張子のファイルをmFileNameListに詰め込むメソッド。ところが、/data以下のディレクトリを指定すると何も取得できない。f.listFiles()の結果がカラッポ。/tmpの下を指定すると問題なく動作する。

/tmpの下はエミュレータを再起動するたびに全部消えてしまうから、音楽ファイルの置き場所は/dataの下にしたい。ところが/dataの下に置くとファイルのリストを取得できない。これは困った。なんとかならないのか?

ついでファイルの書き込みも試してみた。

**********************
  try {
    File newfile = new File("/data/data/testfile1.txt");
    File newfile = new File("/tmp/testfile1.txt");
    newfile.createNewFile();
    FileWriter fw = new FileWriter(newfile);
    fw.write("Hello, world.");
    fw.close();
  } catch (IOException e) {
  }
**********************

Fileクラスのコンストラクタに/data以下のディレクトリを渡すとcreateNewFile()のところで例外が発生してしまう。/tmpの下なら問題ない。どうやら/dataの下で好き勝手なことはできないようだ。

追記:
/data以下だと書き込みが全くできないわけではない。adb pushで転送したファイルを書き換えることはできる。新しいファイルを作れないだけ。


2007年11月25日

Android覚え書き・音楽ファイル再生

Androidで音楽ファイルを再生してみた。すでにやった人がいるのでとても参考になった。とりあえずメモ書き。

  • 音楽ファイル、動画ファイルはいずれもandroid.media.MediaPlayerを使って再生する。エミュレータにはコマンドラインオプションとして"-useaudio"を付ける必要がある。
  • 再生ファイルを指定する方法が解説ページに三つ紹介されている。このうちプロジェクトフォルダの中のres/rawにファイルを入れる方法では、長いファイルを指定すると起動時にNullPointerExceptionが起こってしまう。30秒だとOK、5分だとNG。この方法はおそらく警告音や効果音のためのものだろう。エミュレータにファイルを転送する方法なら5分のファイルも再生可能。ただ、エミュレータを再起動すると転送したファイルが消えてしまうのが面倒。エミュレータからPCのハードディスクをマウントする方法はないだろうか?
  • ファイルのどこまで再生したかを示す情報はandroid.media.MediaPlayerでは受け取れない。タイマーを張ってgetCurrentPosition()で取るしかない?
  • MP3は再生できたが、Ogg Vorbisはダメ。サポートされているフォーマットがどこかに書かれているはずだが、見つからなかった。
  • MP3のタグ情報を取得する方法は提供されていない。android.media.MediaPlayerは指定されたファイルを再生するだけ。

今のAndroidには日本語の入力や表示の仕組みもなさそうだ。Open Handset AllianceにはドコモやKDDIも入っているからきっと何か考えてくれているだろうとは思うが、日本にAndroid搭載端末が現れるのは当分先かもしれない。

追記:
エミュレータを再起動すると転送したファイルが消えてしまう、というのは誤解だった。/dataの下に置けば消えない。タイマーに関してはAndroid Developers Blogの記事が参考になりそう。


2007年11月18日

Google発の携帯電話向けプラットフォーム「Android」

Googleが携帯電話向けのプラットフォームとしてAndroidを発表した。11月12日にSDKが公開された。

  1. Linuxをベースにしており、ソースコードは公開。
  2. Javaでアプリケーションを作成する。Eclipseでの開発が推奨されている。
  3. 当面実機はないが、エミュレータがある。WebkitベースのブラウザやGoogle Mapが既に使える。

といったところが特徴だろうか。アプリケーション作成のためのクラスリファレンスやサンプルコードも既にある。さっそくSDKに飛びついた人も何人かいるようだ。

  1. Android Review(moratorium)
  2. Android入門(JavaDrive)
  3. Androidメモ(ん・ぱか工房)
  4. AndroidでC言語で書いたネイティブアプリを動かしてみる(daily gimite)
  5. Google Androidに関する情報のまとめwiki

Androidの可能性については批判的な見方もあった。

  1. Googleからandroid SDKがリリースされたけれど...(Life is beautiful)
  2. グーグルAndroidは「局地戦」と見る、電話屋の見方(Tech Mom from Silicon Valley)
  3. グーグル「Android」はJavaを分断化する--サンが懸念を表明(ZDNet Japan)

二番目の「電話屋の見方」は「OSを搭載している携帯電話は、全体の7%に過ぎない」というシンビアンのCEOの言葉を肯定的に紹介している。AndroidはせいぜいのところOSを搭載している携帯電話、つまりスマートフォンの市場を制覇できるだけではないか、ということだ。エミュレータを動かしてみたときの私の印象も似たようなもの。PC風のキーボードが付いているのを見て、なんだパソコンが小さくなっただけか、と思ってしまった。

しかしLinuxで開発できるというのは私にとって大きい。私が使っているソフトバンクの携帯電話では、アプリケーションの開発環境はWindowsのものしかない。携帯電話向けのアプリに興味があっても入口のところでブロックされていた。LinuxベースでJavaを使って開発なら障壁は低い。

しばらくSDKをいじり回してみようかと思う。


2007年06月27日

もじら組スタッフの除名

もじら組スタッフは、以前からスタッフだったyukichiさんをもじら組から除名することを決めた。彼が昨年11月にOSC沖縄でトラブルを起こしたこと、および、そのことについて誠意ある対応を取らなかったこと、が理由だ。

彼がリードしていた拡張勉強会を今後どうするかは、まだ決まっていない。

除名は最悪の選択肢だった。彼が起こしたトラブルにつりあうものではない。拡張勉強会はもじら組の新しい活動として成功していたのに、存続が危うくなっている。

もじら組ができてから7年。残念だがそろそろ寿命なのかもしれない。今はMozilla Japanがあるので、もじら組の存在意義は以前より小さくなっている。このまま寿命がつきても悪影響はあまりない。

2007年06月09日

受託開発じゃダメ、か。

「中毒性」ある受託開発がソフトウェアベンチャーの躍進を阻むという記事をたまたま見かけ、驚いた。そうか、ベンチャーキャピタルの世界では「受託開発じゃダメ」が常識になっているのか。

私は受託開発の仕事ばかりやってきた。現在の職場では受託開発でさえ遠い夢になっている。月数十万で顧客企業に派遣され、どこかのアホが大昔に書いた汚いコードを保守していくだけ。お客さんの信頼を得てまとまった単位で受託し、自由に設計して美しいシステムを作るのが夢だ。ところが、この記事を書いた大迫正治氏はそんな夢を否定している。受託開発では技術が蓄積しない、人材が蓄積しない、資金が蓄積しない、とのこと。

言われてみれば確かにそうだ。受託開発でたまたま新しい技術を習得できたとしても、そのプロジェクトが終われば終わり。全然違う別のプロジェクトに放りこまれるので一からやりなおしになる。この業界の人間はたしかにみんな働きすぎだし、すぐに辞めてしまう。かく言う私も数年ごとに転職している。MozillaBansheeの開発に首をつっこんだのも、仕事で得られないものを得るためだ。

しかし、受託開発によって自社開発のための力をつけるべきだ、という主張に対し、受託開発はダメだ、最初から自社開発を目指せ、というだけでは何の提案にもなっていないように感じる。それができたら誰も苦労しないんじゃないだろうか。


2006年12月23日

開発者がカネ以上に欲する9つのこと

プログラマのモチベーションを高める9の事項を読んで、元ネタのNine Things Developers Want More Than Money(開発者がカネ以上に欲する9つのこと)を知った。Rob Wallingという人が書いたブログの記事だ。

ベースになっているのはFrederick HerzbergのTwo Factor Theory。Wikipediae研修ネットによれば、アメリカで203人の会計士とエンジニアにインタビューした結果に基づき、仕事に対する不満は「衛生要因」から生じ、満足は「動機付け要因」から生じる、と主張する理論だ。衛生要因は給料や作業環境や人間関係からなり、動機付け要因は仕事の面白さや責任からなる。

この理論に基づき、Rob Wallingは衛生要因のひどさを補ってあまりある動機付け要因を9個挙げている。プロジェクト計画が適切、マネジメントが優秀、新しいことを学べる、挑戦しがいのある課題がある、意見を聞いてもらえる、褒めてもらえる、意味のあるものを作っている、会議や稟議なしにソフトウェアを書ける、過去の制約が少ない。プロジェクトにこれらの要因があればプログラマーは安い給料と最低の作業環境しかなくても嬉々として働くのだという。衛生要因より動機付け要因のほうが重要、と主張しているのだから、Two Factor Theoryの枠組みを借りながら少し違うことを言っていることになる。

私は以前から「労働時間」と「仕事の面白さ」を基準にして勤務先の会社を評価してきた。労働時間が短く、仕事が面白ければ最高。長時間労働だが仕事が面白いか、仕事はつまらないが労働時間が短ければ、とりあえず我慢。つまらない仕事で残業や休日出勤が続いたら、真剣に転職を考える。次の会社ももちろんこの二つの基準で選ぶ。これは何度か転職するうちに身についた基準なのだが、有名な理論で裏付けできる基準だとは今回はじめて知った。

しかし、最近感じ始めてきたのは、転職活動の際にTwo Factor Theoryでいう動機付け要因を重視するのは正しくないんじゃないか、ということだ。Rob Wallingが挙げているような要因で評価できるのはソフトウェア企業ではなく、個々の開発プロジェクトだ。とくに私の場合、開発プロジェクトは顧客企業のものであって自社のものではない。客先に常駐して他社のプロジェクトリーダーの下で作業することがほとんどだ。いわばプロジェクトごとにプチ転職しているようなもの。そうなると、最悪のプロジェクトから逃れようとして会社を移り、新しい会社で最高のプロジェクトに入れても、それが終われば次は再び最悪のプロジェクトに出会ってしまうかもしれないわけだ。したがって、転職先を決める場合は衛生要因を重視するのが無難に思える。Rob Wallingが言っていることとは逆になる。

プロジェクト管理の観点で考えるならRob Wallingが言っていることは正しいと思う。動機付け要因を常に気にかけているプロジェクト管理者の下で働ける、という要因を10個目として付け足せば、彼の主張は会社を評価する場合にも使えるかもしれない。