반응형

멀티미디어는 음악 파일 재생, 동영상 재생, 음성 녹음과 사진찍기에 이르기까지 다양한 기능을 포함합니다.

그중에서도 사람들이 가장 많이 사용하는 기능으로 사진찍기를 들 수 있습니다.

사진이 잘 나오는 단말기를 사고 싶다는 것이 단말기 구매의 기본 조건이 되기도 하니 카메라를 이용하는 것이 얼마나 중요한 기능인지 짐작할 수 있을 것입니다.

많은 사람이 사진을 찍는 것을 좋아하니까 여러분이 앱을 만들 때도 사진 찍는 방법에 대해 알아두는 것이 좋습니다.

어떻게 사진을 찍을 수 있는지 알아봅시다.



카메라 앱 화면 보여주기

사진을 찍는 가장 간단한 방법은 단말에 이미 설치된 카메라 앱을 사용하는 것입니다.

이미 만들어져 있는 화면이니 여러분이 직접 화면을 만들 필요가 없죠.

다른 앱의 화면을 보여주어야 하므로 인텐트를 이용해 시스템으로 요청하는 과정이 필요합니다.

사용자가 사진찍기 버튼을 누르면 인텐트 객체를 만들고 startActivityForResult 메소드를 이용해 시스템으로 인텐트 객체를 전달합니다.

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));

if (intent.resolveActivity(getPackageManager()) != null) {
  startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);
}

인텐트 객체를 만들 때는 MediaStore.ACTION_IMAGE_CAPTURE라는 액션 정보를 전달합니다.

그리고 부가데이터로 MediaStore.EXTRA_OUTPUT을 추가합니다.

이 부가데이터의 값으로는 카메라 앱에서 찍은 사진을 저장할 위치를 넣어줍니다.

Uri라는 자료형으로 되어 있어야 하므로 Uri.fromFile 메소드를 이용해 파일의 Uri를 지정합니다.

이렇게 요청하면 카메라 앱의 화면이 보이고 사진을 찍을 수 있습니다.

 

사진 찍은 결과 보여주기

사진을 찍고 나면 다시 여러분이 만든 앱의 화면으로 돌아오며 이때 찍은 사진을 확인할 수 있습니다.

새로 띄운 화면에서 돌아오는 과정이므로 onActivityResult 메소드를 재정의하면 이 메소드가 자동으로 호출됩니다.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 8;
        Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options); 
        imageView.setImageBitmap(bitmap); 
    }
}

onActivityResult 메소드 안에서 파일을 확인하면 찍은 사진이 저장되어 있다는 것을 알 수 있습니다.

이것을 이미지뷰에 설정하면 사진이 화면에 보이게 됩니다.

 

카메라 미리보기 추가하기

여러분이 만든 화면에 카메라 미리 보기를 추가하고 싶다면 SurfaceView를 사용하면 됩니다.

이 뷰는 일반적인 뷰와 달라서 만들어야 하는 코드가 조금 더 많습니다.

SurfaceView를 상속하는 새로운 클래스를 만들고 이 클래스가 SurfaceHolder의 Callback 인터페이스를 구현하도록 합니다.

SurfaceView는 껍데기 역할만 하고 실제 컨트롤은 SurfaceHolder가 담당합니다.

그리고 뷰의 상태 변화를 알 수 있도록 Callback 인터페이스를 제공합니다.

이 인터페이스를 구현하면 뷰가 만들어졌을 때, 변경될 때, 없어질 때 자동으로 메소드가 호출됩니다.

private class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder mHolder;
    
    public CameraSurfaceView(Context context) {
        super(context);

        mHolder = getHolder();
        mHolder.addCallback(this);
    }
 
    public void surfaceCreated(SurfaceHolder holder) {
 
    } 
 
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 

    }
 
    public void surfaceDestroyed(SurfaceHolder holder) {
 
    }

}

SurfaceView 객체가 메모리에 만들어질 때 자동으로 호출되는 surfaceCreated 메소드 안에서는 카메라 객체를 오픈하고(코드 라인:2) 카메라 객체에 서피스홀더 객체를 설정합니다(코드 라인:4).

public void surfaceCreated(SurfaceHolder holder) {
    camera = Camera.open();
    try {
        camera.setPreviewDisplay(mHolder);
    } catch (Exception e) {
        Log.e("CameraSurfaceView", "Failed to set camera preview.", e);
    }
} 

Camera 객체는 단말의 하드웨어 카메라를 참조하며 이 클래스 안에 변수로 선언되어 있습니다.

뷰의 크기가 변경되는 시점에는 미리 보기 화면이 보이도록 만들어줍니다.

public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    camera.startPreview();
}

뷰가 메모리에서 사라지는 시점에는 카메라 참조를 해제합니다.

capture 메소드는 이 객체를 통해 사진을 찍을 수 있도록 합니다.

public void surfaceDestroyed(SurfaceHolder holder) {
  camera.stopPreview();
  camera.release();
  camera = null;
}

public boolean capture(Camera.PictureCallback handler) {
    if (camera != null) {
        camera.takePicture(null, null, handler);
        return true;
    } else {
        return false;
    }
}

카메라 미리 보기 등의 기능을 구현할 때는 권한이 필요하므로 AndroidManifest.xml 파일에 다음 권한을 추가합니다.

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

 

만들어진 객체 사용하기

버튼을 눌렀을 때 카메라 미리 보기를 위해 만들었던 객체의 capture 메소드를 호출하도록 합니다.

그러면 사진을 찍은 결과를 바이트 배열로 받을 수 있습니다.

public void onClick(View v) {
    cameraView.capture(new Camera.PictureCallback() {
        public void onPictureTaken(byte[] data, Camera camera) {
            try {
                Bitmap bitmap = BitmapFactory.decodeByteArray(data,0,data.length);

사진을 찍은 결과를 비트맵 객체로 변환했으니 이미지뷰에 설정하면 화면에 보여줄 수 있습니다.

 

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기