ひらい ぶらり Hi-Library

ぷろぐらみんぐについて。ときどきどうでもいいことについて。

androidアプリ開発におけるカメラ問題に決着をつけようじゃないか 解決編

  • 条件振り分けで取得方法を変える
  • getContentResolver().insert()を使わない。MediaScannerConnection等を使って標準ギャラリーには反映させる。

そんな訳で、上記の具体的な解決方法を書く。

まず、getContentResolver()を使わないので、別の方法でカメラの保存先を取得する。

public class CameraActivity extends Activity {

    priate static final int REQUET_IMAGE_CAPTURE = 1;
    private Uri imageUri;

    // 省略

    private void runCamera() {
        Bundle extras = getIntent().getExtras();

        // 標準のカメラ撮影時の保存場所を取得
        File pathExternalPublicDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM);
        String filename = System.currentTimeMillis() + ".jpg";
        File capturedFile = new File( pathExternalPublicDir, filename );
        Uri imageUri = Uri.fromFile( capturedFile );
        Intent intent = new Intent( MediaStore.ACTION_IMAGE_CAPTURE );
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);
    }

とりあえず、これでカメラで撮った画像は端末標準の保存先に保存されることになる getContentResolver()も使ってないので、onActivityResultで取得する画像データにはexifがついてくるはず。 すべての機種で試したわけではないのでわからないけど、とりあえず持っている端末で試したところexifはついてきた

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // experiaとそれ以外で処理を分ける
        Uri pictureUri = (data != null && data.getData() != null) ? data.getData() : imageUri;
        if (pictureUri == null) {
            // IS03とかだとUriが取れないらしく、サムネイルクラスのしょぼい画像を取得するしかない
            Bitmap bmp = (Bitmap) data.getExtras().get("data");
            return;
        }
        // 標準ギャラリーにスキャンさせる
        MediaScannerConnection.scanFile( // API Level 8
                this, // Context
                new String[]{pictureUri.getPath()},
                new String[]{"image/jpeg"},
                null);
        }

        int orientation = ImageUtil.getOrientation(pictureUri);
        // 回転方向を取得して適切に回転させる

        Bitmap bmp = ImageUtil.createBitmapFromUri(this, pictureUri);
    }  
public class ImageUtil {

    public static Bitmap createBitmapFromUri(Context context, Uri uri) {
        ContentResolver contentResolver = context.getContentResolver();
        InputStream inputStream = null;
        BitmapFactory.Options imageOptions;
        Bitmap imageBitmap = null;

        // メモリ上に画像を読み込まず、画像サイズ情報のみを取得する
        try {
            inputStream = contentResolver.openInputStream(uri);
            imageOptions = new BitmapFactory.Options();
            imageOptions.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(inputStream, null, imageOptions);
            assert inputStream != null;
            inputStream.close();
            // もし読み込む画像が大きかったら縮小して読み込む
            inputStream = contentResolver.openInputStream(uri);
            if (imageOptions.outWidth > 2048 && imageOptions.outHeight > 2048) {
                imageOptions = new BitmapFactory.Options();
                imageOptions.inSampleSize = 2;
                imageBitmap = BitmapFactory.decodeStream(inputStream, null, imageOptions);
            } else {
                imageBitmap = BitmapFactory.decodeStream(inputStream, null, null);
            }
            inputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return imageBitmap;
    }

    public static int getOrientation(Uri uri) {
        ExifInterface exifInterface;

        try {
            exifInterface = new ExifInterface(uri.getPath());
        } catch (IOException e) {
            return 0;
        }

        int exifR = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
        int orientation = 0;
        switch (exifR) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                orientation = 90;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                orientation = 180;
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                orientation = 270;
                break;
            default:
                orientation = 0;
                break;
        }
        return orientation;
    }
}

とりあえず、これでBitmapとorientationを取得することができたので、あとは適当に画像回転させるなりエラー処理を書けばよさそう。