Android カメラを起動して、ビューに表示してみる

Multimedia and Camera > Camera を参考にして、カメラを起動して、写真を取ったら、それを画面内にプレビューするものを作成していきます。

その後、Android カメラで撮影するかギャラリーから選択した画像をビューに表示してみる のもやりました。

ご参考までに。

Manifest に追記

カメラを使うにはパーミッションを与える必要があります。

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-feature android:name="android.hardware.camera" android:required="false" />

上から、カメラの利用、外部ストレージの書き込み、音声の録音の許可を求めます。

表示領域とカメラ起動ボタン

ここは自作です。カメラを起動するためのボタンと、プレビュー領域だけ配置します。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:weightSum="1">
    <ImageView
      android:id="@+id/preview"
      android:layout_width="match_parent"
      android:layout_height="300dp"
      android:layout_gravity="center"></ImageView>
    <ImageButton
      android:id="@+id/camera"
      android:src="@android:drawable/ic_menu_camera"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="center"
      android:onClick="camera"></ImageButton>
</LinearLayout>

ImageView と ImageButton を配置しました。ImageButton の src にカメラのアイコンなんかを指定するとそれっぽくて良いカンジです。

既存カメラアプリを使う

カメラオブジェクトを作成して、独自機能のカメラアプリを作ることもできますが、とりあえず簡単に、撮影はデフォルトインストールされているカメラアプリに任せることにします。

Image capture intent からソースコードをベースに、ボタンを押したらカメラアプリにインテントを送るように修正しました。

    private Uri fileUri;
    private ImageView preview; // プレビュー用
    private Bitmap    bm;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        preview = (ImageView)findViewById(R.id.preview);

        // cameraメソッドに移動
     }

    // xml 内で onClick で呼び出されるように指定している
    public void camera(View v){
        // create Intent to take a picture and return control to the calling application
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

        fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
        intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

        startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
    }

// http://developer.android.com/guide/topics/media/camera.html#saving-media
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;

/** Create a file Uri for saving an image or video */
private static Uri getOutputMediaFileUri(int type){
      return Uri.fromFile(getOutputMediaFile(type));
}

/** Create a File for saving an image or video */
private static File getOutputMediaFile(int type){
    // To be safe, you should check that the SDCard is mounted
    // using Environment.getExternalStorageState() before doing this.

    File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
              Environment.DIRECTORY_PICTURES), "MyCameraApp");
    // This location works best if you want the created images to be shared
    // between applications and persist after your app has been uninstalled.

    // Create the storage directory if it does not exist
    if (! mediaStorageDir.exists()){
        if (! mediaStorageDir.mkdirs()){
            Log.d("MyCameraApp", "failed to create directory");
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE){
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "IMG_"+ timeStamp + ".jpg");
    } else if(type == MEDIA_TYPE_VIDEO) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator +
        "VID_"+ timeStamp + ".mp4");
    } else {
        return null;
    }

    return mediaFile;
}

getOutputMediaFileUri(MEDIA_TYPE_IMAGE) は別ページで実装例があるので、それも貼り付けます。

原文の private static Uri getOutputMediaFile(int type) の戻り型が Uri ですが、File の間違いのようなので、修正します。

カメラアプリから戻ってきたときの動作

カメラアプリで撮影を行い、もとのアクティビティに戻ってきたときの動作を作成します。

RESULT_OK が帰ってきたときの挙動を、カメラアプリが撮った写真のパスを持った fileUri を利用して、preview に描画するように修正しました。

private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            // Image captured and saved to fileUri specified in the Intent
            // 直前の bitmap が読み込まれていたら開放する
            if(null != bm){
                bm.recycle();
            }
            BitmapFactory.Options options = new BitmapFactory.Options();
            // 4 を指定すると 元の 1/4 のサイズで bitmap を取得する
            options.inSampleSize = 4;
            bm = BitmapFactory.decodeFile(fileUri.getPath(), options);

            preview.setImageBitmap(bm);
        } else if (resultCode == RESULT_CANCELED) {
            // User cancelled the image capture
        } else {
            // Image capture failed, advise user
        }
    }
}

CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE の定義が既にあるので片方消します。

今回ビデオはあつかわないので、そのあたりの処理も消してしまいました。

メモリ消費対策として、ビットマップを描画する前に、直前のビットマップの片付けをします。

さらに、描画する画像も 1/4 のサイズで取得し、データ量を小さくしておきます。

とりあえず、カメラが起動して、ファイルとして保存され、それを読み込んで表示することができました。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする