1.Intentで端末のカメラアプリを呼び出す
2.SurfaceViewを使って、カメラスルー画面を直接呼び出す。
どちらもWebをちょっと調べると、サンプルコードが出てきます。
が。
Camera機能は、機種依存動作が強すぎるようで、結構はまりどころです。
やろうとしていたのは、カメラで写真をとって、FaceDetectorで顔認識をするアプリ。
まず、Intentでカメラアプリを呼び出す方法。
カメラにIntentを投げて、onActivityResult()で、結果を受け取る、というのが大体の流れです。
この、結果を受けとる、ところがクセモノで、機種によって受け取れ方が違います。
1.intent.getData()でUriを取得する。HTC Desire/Xperia acroなんかはこれっぽい。
protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_CANCELED) { return; } Uri uri = data.getData(); getImage(uri); }
2. 事前に、IntentのputExtraで書き出し先のUriを指定して、Intentを発行する。SHARP製のAndroidはこの動作。
public void launchCamera() { // Create your own image Uri ... Intent intent = new Intent(); intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri); startActivityForResult(intent, 2); } protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_CANCELED) { if (mImageUri == null) //delete file at mImageUri return; } getImage(mImageUri); }
このmImageUriに、画像が書きだされてますので、onActivityResult()が呼ばれれば、mImageUriからそのまま取得できます。
3. 1も2もしてくれない・・・Galaxy Sがこのパターン
えっと・・・これが一番困りました。
intent.getData()はnullだし、2をやると、違うUriに書きだしてくるし、、、
結局、画像の中で最新の画像を取得するコードを書いています。
protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == RESULT_CANCELED) { return; } Uri uri = data.getData(); if (uri == null) { ContentResolver cr = getContentResolver(); Cursor c = MediaStore.Images.Media.query(cr, MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null,null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC"); c.moveToFirst(); String id =c.getString(c.getColumnIndexOrThrow(BaseColumns._ID); Uri uri = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + id); getImage(uri); } else { getImage(uri); } }
もちろん、このコードは、最新の時刻の画像=今とった画像、ではないパターンで問題が出ます。
撮影直後に別のアプリが画像書き出してた、とか。タイムスタンプが未来の画像が入っちゃってる、とか。
エラーチェックを厳しくすればいいのでしょうが、、、
一応、1,2,3ともに共存可能なので、3は最終手段として使う予定です。
なお、Galaxyの場合、以下のような動作もあり。
・撮影が終わってもカメラアプリが終了しないという問題(仕様?)
・カメラ呼び出し元のActivityが終了させられてしまう
前者は、作ってるアプリの仕様上、撮影後はすぐに別画面に遷移させる必要があるので、
別画面を起動するIntentを投げてカメラを終了(中断)させています。
後者が厄介で、Activity::onDestroy()が呼ばれた上、GCまでされちゃいます。
カメラから呼び出し元Activityに戻ると、onCreate()からやり直しです。
つまり変数が全て初期化されます。スッゲ泣ける。
実は、SurfaceViewを使う方法でも、Galaxy Sは大変なんですが、、、それは次回にします。
Intentional Disciplemaking: Cultivating Spiritual Maturity in the Local Church
楽天ブックス
INTENTIONAL DISCIPLEMAKING Ron Bennett NAV PR2001
楽天市場 by
楽天ブックス
INTENTIONAL DISCIPLEMAKING Ron Bennett NAV PR2001
楽天市場 by
こういう話があるようです。
返信削除onConfigurationChangedを拾うようにすればonDestroyが起きないのでは。
Galaxy Sでカメラアプリを使用する時の注意点
http://relog.xii.jp/archives/2010/11/galaxy_s.html
Configuration Changes
http://developer.android.com/reference/android/app/Activity.html#ConfigurationChanges
コメントありがとうございます。
返信削除なるほど、横向きにされちゃうから、onDestroy()がくるとは・・・盲点・・・
今のコードはこの現象が発生しなくなってるのですが、少し調べたところ、どうやら呼び出し元のActivity(onDestroyが呼ばれちゃってたもの)を縦固定にしたため、発生しなくなったようです。
onConfigurationChanged()のほかにも、これでもいけるっぽいです。
大変有用な情報ありがとうございました.
返信削除方法3をうまく使えば,各社独自仕様になってるカメラのインテント周りをこれ1つでこなすことができるかと思います.
わざわざ端末毎に場合分けするのも大変になりますし...
お役に立てたようで幸いです。
削除ググってみても、いろんな人の苦労の跡が忍ばれます。
ところで、今は(この記事を書いたときはなかったと思う)、公式にもCameraの利用方法が上がっているようです
http://developer.android.com/intl/ja/guide/topics/media/camera.html
せめてこれに従えば良いという状況になればいいのですが。