複数のカメラを使う


Android 2.3から複数のカメラをサポートしました。
主にビデオ通話を目的とするカメラ(端末前面に取り付けられるフロントカメラ)の対応です。
今回はAndroid 2.3のAPI Demoに含まれているCameraPreviewを参考に詳細を追ってみたいと思います。

 

CameraInfoクラスの追加

Android 2.3では複数のカメラのサポートの為にAPIに幾つか追加や変更がなされています。

まず、大きな変更点としてCameraInfoクラスが新たに追加されています。
CameraInfoクラスにはカメラの取り付け位置に関する情報が格納されます。
アプリケーションとしてはCameraInfoクラスの情報を頼りにフロントカメラ、バックフロントカメラの処理を切り替えることになります。

CameraInfoクラスのフィールドと定数を以下に示します。

・CameraInfoクラスのフィールド

public int facing カメラの取り付け位置(正面/背面)に関する情報が格納されます。
public int orientation カメラ画像の角度情報が格納されます。

・CameraInfoクラスの定数

CAMERA_FACING_BACK facingフィールドに格納される定数です。
カメラが背面に取り付けられていることを示します。
CAMERA_FACING_FRONT facingフィールドに格納される定数です。
カメラが正面に取り付けられていることを示します。

また、CameraInfoクラスのほかにも以下の2つのメソッドが追加されています。

・getCameraInfoメソッドとgetNumberOfCamerasメソッド

getCameraInfo() 上記のCameraInfoを返すメソッドです。
getNumberOfCameras() 利用できるカメラの個数を返すメソッドです。

CameraPreview

では、CameraPreviewのソースコードを見てみます。
特に複数のカメラを制御している部分を抽出して紹介します。

まずはonCreateメソッドです。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // ウィンドウタイトルを非表示に設定
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

    // プレビュー画面の作成
    mPreview = new Preview(this);
    setContentView(mPreview);

    // 利用可能なカメラの個数を取得
    numberOfCameras = Camera.getNumberOfCameras();

    // CameraInfoからバックフロントカメラのidを取得
    CameraInfo cameraInfo = new CameraInfo();
        for (int i = 0; i < numberOfCameras; i++) {
            Camera.getCameraInfo(i, cameraInfo);
            if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
                defaultCameraId = i;
            }
        }
}

上記14行目で利用可能なカメラの個数を取得、17行目からCameraInfoクラスを使ってバックフロントカメラを探し、見つかったバックフロントカメラをデフォルトのカメラに設定しています。

次に、バックフロントカメラとフロントカメラの切り替えを行う処理を見ていきます。
CameraPreviewではメニューボタンからカメラの切り替えが行えます。

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.switch_cam:
        // カメラが複数あるかチェック
        if (numberOfCameras == 1) {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage(this.getString(R.string.camera_alert))
                   .setNeutralButton("Close", null);
            AlertDialog alert = builder.create();
            alert.show();
            return true;
        }

        // 現在利用しているカメラを解放
        if (mCamera != null) {
            mCamera.stopPreview();
            mPreview.setCamera(null);
            mCamera.release();
            mCamera = null;
        }

        // カメラを切り替え
        mCamera = Camera
                .open((cameraCurrentlyLocked + 1) % numberOfCameras);
        cameraCurrentlyLocked = (cameraCurrentlyLocked + 1)
                % numberOfCameras;
        mPreview.switchCamera(mCamera);

        // プレビュー再開
        mCamera.startPreview();
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}

5行目からの条件文でカメラが1つだけの場合をチェックしています。
(エミュレータではカメラを1つだけしか設定できないのでこのチェックで弾かれます。。。)

15行目で現在動作中のカメラを解放し、23行目で次のカメラにスイッチしています。
camera.openメソッドの引数にカメラ番号を指定することで任意のカメラを使用することができます。
なお、このカメラ番号は0からgetNumberOfCameras()-1までの値になります。

One Comment