2011年6月2日木曜日

カメラやギャラリーピッカーからの画像取得周りまとめ

AndroidSDKでの開発中にギャラリー機能やカメラ機能を活用して画像を取り込みたいと思う要件はさまざまなシーンで発生しますが、
やり方をど忘れした上に、どこのブログに情報が載っていたかまで忘れることがあるので、ギャラリーからの画像取得周りについて簡単にまとめます。

やりたい事としては以下の2つです。
1.ギャラリーから画像を取り込む
2.標準カメラから撮影した画像を取得する

これを実現する方法を3点にわけて説明します。
1.ギャラリーから画像を選択して戻ってくる画面の呼び出し
2.撮影したらアプリに戻ってくる標準カメラの呼び出し
3.1、2からのコールバックに対しての処理方法

1.ギャラリーから画像を選択して戻ってくる画面の呼び出し

Intentを用いてActivity呼び出す際に、startActivityForResultを使用することで、
自ActivityのonActivityResultへコールバックを得られます。
ギャラリー、カメラ両方ともこの仕組みを活用することで、
画像へのUriを取得する事が可能です。

1、2の内容はギャラリーorカメラボタンの押下イベント等に適切に実装してください。

まずはギャラリー画面の呼び出しを説明します。


IntentにsetActionでACTION_PICKを指定してあげることで、一発で標準ギャラリーが呼び出されます。

try{
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_PICK);
//GALLARERY_IMAGEは適当なintです。onActivityResultでどこからの戻りか識別する必要がある場合に有効です
startActivityForResult(intent,GALLERY_IMAGE);
}catch(Exception e){

}

※2、3はこちらに訂正版のエントリーがありますので、ソースコードはそちらを参照してください。
説明は一読されることをお奨めします。


2.撮影したらアプリに戻ってくる標準カメラの呼び出し

try{
Intent intent = new Intent();
intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
/*
//putExtraでEXTRA_OUTPUTを設定すると、カメラに画像の保存パスを指定することができます。指定しない場合は標準のファイル名で保存されます。
File mTmpFile = new File(Environment.getExternalStorageDirectory(), "tmp_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTmpFile));
*/
// ギャラリーと同じく判別用のintです
startActivityForResult(intent, CAMMERA_IMAGE);

}catch(Exception e){

}

3.1、2からのコールバックに対しての処理方法


protected void onActivityResult(int requestCode, int resultCode, Intent data) {

super.onActivityResult(requestCode, resultCode, data);

if (resultCode != RESULT_OK){
return;
}

Uri uri = null;
if (requestCode == GALLERY_IMAGE) {
uri = data.getData();
}
else if(requestCode == CAMMERA_IMAGE){
uri =data.getData();
}

if(uri == null){
return;
}

try {
InputStream is = getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(is);

/*
//ファイルパスを取得したい場合は下記のようにContentResolverを活用する
//ContentResolver経由でファイルパスを取得
ContentResolver cr = getContentResolver();
String[] columns = {MediaStore.Images.Media.DATA };
Cursor c = cr.query(uri, columns, null, null, null);

c.moveToFirst();
File picture = new File(c.getString(0));
*/
} catch (Exception e){
// } catch (FileNotFoundException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
return;
}
}

以上で、標準カメラおよび標準ギャラリーから画像を取得することができると思います。

【カメラから撮影画像を取得する場合のout of memory対策】

カメラから撮影画像を取得する場合ですが、
カメラの撮影サイズが5M等、非常に大きいサイズの画像だとoutofmemory例外が発生しやすくなります。
そこでBitmapFactoryのOptionsを駆使して画像のサイズ事前に調べた上でリサイズした画像をBitmapとして取得することでメモリー使用を抑えます。

以前どちらかのブログで紹介されていたもので、私のアプリにほぼコピペ移植させていただいた関数を下記URLにメモしています。
どちらのブログだったか覚えておらず出展を表記できず申し訳ありません。

http://ameblo.jp/yolluca/entry-10888432114.html


先ほどのカメラで撮影した画像を活用する場合はこちらのような処理を噛ませ画像の大きさをコントロールすることをお薦めいたします。


Reference Link