*.1 Manifest에 주가해야되는 권한
- <uses-permission android:name="android.permission.CAMERA"/> //카메라 사용
- <uses-permission android:name="android.permission.FLASHLIGHT"/> //카메라 플레쉬 사용
1. 카메라 미리보기 주요과정
1.1 카메라 미리보는 SurfaceView를 사용함 따라서, SurfaceView 사용 패턴을 그대로 사용한다.(SurfaceHolder를 이용한 SurfaceView 컨트롤)
1.2 카메라에게 서피스뷰를 알려주는 메서드
camera.setPreviewDisplay(mHolder);1.3 미리보기에 시작 메서드
camera.startPreview();2. 카메라 캡처 주요과정
- 이부분은 주관적인 부분으로 정확하지않을수 있습니다.
2.1 카메라 셔터를 눌렀을때 일어나는 이벤트를 정의한 인터페이스를 재정의한다.
Camera.ShutterCallback suttercallback = new Camera.ShutterCallback() { public void onShutter() {...} };2.2 카메라 캡처후 사진데이터가 Raw 혹은 JPEG 형식으로 메모리에 적제되면 그것을 어떻게 처리할것인지 처리하는 인터페이스를 제정의한다.
Camera.PictureCallback picturecallback = new Camera.PictureCallback() { public void onPictureTaken(byte[] data, Camera camera) {...} };2.3 카메라 캡처 이벤트가 발생한곳(버튼이거나 뷰 등등)에 메서드를 넣어준다. 그리고 2.1 / 2.2 에서 생성한 객체들을 매개변수에 넣어준다
camera.takePicture(suttercallback , null , picturecallback);3. SurfaceView 재정의 주요과정(전형적인 패턴)
-가끔 디테일한 설정이 필요할때는 SurfaceView를 재정의 해서 사용한다.
3.1 클래스 재정의 할때 SurfaceView 와 SurfaceView 의 상태컨트롤을 위한 SurfaceHolder.Callback를 상속받아서 정의한다
class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback3.2 재정의된 SurfaceView를 컨트롤할 내부 변수 SurfaceHolder 객체를 선언하고 생성자나 다른 함수를 안에서 SurfaceHolder 객체를 생성한다.
private SurfaceHolder mHolder; mHolder = getHolder();3.3 카메라가 SurfaceView를 독점하기 위해선 SurfaceHolder의 타입은 항상SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS로 설정한다.
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);3.4 SurfaceView 의상태(메모리 유무 ,사이즈변화 등등)는 SurfaceHolder.Callback 인터페이스 에 정의된 메서드로 처리한다.(기존 다른 리스너 방식과 유사)
-mHolder.addCallback(this); //콜백 인터페이스 홀더에 설정 -public void surfaceCreated(SurfaceHolder holder) // SurfaceView가 생성됬을때 호출된다 -public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) //SurfaceView 크기가 변화될때 호출된다 -public void surfaceDestroyed(SurfaceHolder holder) //SurfaceView 메모리 헤제됬을때 호출된다
4. 예제
android version = jelly bean
import android.app.Activity; import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.hardware.Camera; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.util.Log; import android.view.Menu; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.widget.Button; import android.widget.FrameLayout; import android.widget.Toast; // SurfaceView를 이용해 미리보기 화면을 만든 후 사진찍기를 하는 방법에 대해 알 수 있습니다. public class MainActivity extends Activity { // 캡처한 사진파일 저장할 이름 public static String IMAGE_FILE = "capture.jpg"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // FrameLayout에 재정의한 CameraSurfaceView 추가 final CameraSurfaceView cameraView = new CameraSurfaceView( getApplicationContext()); FrameLayout previewFrame = (FrameLayout) findViewById(R.id.previewFrame); previewFrame.addView(cameraView); // 버튼을 눌렀을때 캡처 Button saveBtn = (Button) findViewById(R.id.saveBtn); saveBtn.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // cameraView에 있는 capture() 메서드 실행 cameraView.capture(new Camera.PictureCallback() { // JPEG 사진파일 생성후 호출됨 // 찍은 사진을 처리 // PictureCallback 인터페이스 에 있는 onPictureTaken() 메서드 // byte[] data - 사진 데이타 public void onPictureTaken(byte[] data, Camera camera) { try { // 사진데이타를 비트맵 객체로 저장 Bitmap bitmap = BitmapFactory.decodeByteArray(data,0, data.length); // bitmap 이미지를 이용해 앨범에 저장 // 내용재공자를 통해서 앨범에 저장 String outUriStr = MediaStore.Images.Media.insertImage(getContentResolver(), bitmap,"Captured Image","Captured Image using Camera."); if (outUriStr == null) { Log.d("SampleCapture", "Image insert failed."); return; } else { Uri outUri = Uri.parse(outUriStr); sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,outUri)); } Toast.makeText(getApplicationContext(),"카메라로 찍은 사진을 앨범에 저장했습니다.",Toast.LENGTH_LONG).show(); // 다시 미리보기 화면 보여줌 camera.startPreview(); } catch (Exception e) { Log.e("SampleCapture", "Failed to insert image.", e); } } }); } }); } // 카메라 미리보기를 위해 SurfaceView 클래스 재정의 private class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback { // SurfaceView를 컨트롤할 SurfaceHolder 객체 선언 private SurfaceHolder mHolder; // 미리보기를 위한 카메라 객체 선언 private Camera camera = null; public CameraSurfaceView(Context context) { super(context); // SurfaceHolder 객체 생성 getHolder()는 SurfaceView 내부 함수 mHolder = getHolder(); // SurfaceHolder.Callback 인터페이스 장착 mHolder.addCallback(this); // 카메라가 SurfaceView를 독점하기 위한 타입 설정 // 버퍼를 사용하지않음 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } // SurfaceView 가 메모리에 생성될때 호출된다. public void surfaceCreated(SurfaceHolder holder) { // 카메라를 사용할려고 한다는 설정 camera = Camera.open(); try { // 미리보기를 설정 camera.setPreviewDisplay(mHolder); } catch (Exception e) { Log.e("CameraSurfaceView", "Failed to set camera preview.", e); } } // 보통 SurfaceView가 보여지기전 과 사이즈가 변화가있을때 호출된다. // 그래서 보여지기전인 surfaceCreated()가 호출된 다음 호출된다. public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // 카메라의 파라미터 값을 가져와서 미리보기 크기를 설정한다 Camera.Parameters parameters= camera.getParameters(); parameters.setPreviewSize(width, height); camera.setParameters(parameters); // 미리보기화면을 뿌려준다 camera.startPreview(); } // SurfaceView의 메모리가 해제되었을때 호출된다. // SurfaceView가 화면에 표시되지않을때(액티비티가 비활성화 될때) 호출된다. public void surfaceDestroyed(SurfaceHolder holder) { // 미리보기 중지 camera.stopPreview(); // 메모리 해제 camera.release(); camera = null; } // 사진을 찍을때 호출되는 함수 (스냅샷) public boolean capture(Camera.PictureCallback handler) { if (camera != null) { // 셔터후 // Raw 이미지 생성후 // JPE 이미지 생성후 camera.takePicture(null, null, handler); return true; } else { return false; } } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
FrameLayout은 어떻게 정의하셨는지...
답글삭제