해당 부분은 개발자가 직접 개발할 수 있는 어플들에 관한 계층입니다.
시중에 나와있는 각종 안드로이드 책에서도 쉽게 볼 수 있는 부분입니다.
실제적으로 코딩을 해야되는 부분이므로, 천천히 읽어나가셨으면 합니다.
이 부분도 '안드로이드의 모든것 분석과 포팅'과 카메라 개발문서를 보면서 제 개인적으로 정리한 부분을 적어놓은것임을 미리 밝혀 드립니다.
카메라 애플리케이션을 만들기 위해서는 기본적으로 카메라영상을 사용자가 볼 수 있게 출력을 하는 Preview 부분이 먼저 구현이 되어야 한다.
그래서 카메라를 구동해서
영상을 입력받기 위한 카메라서비스 관련 기능과
영상을 화면에 출력하기 위한 SurfaceFlinger 서비스 관련 기능이 구현되어야 한다.
(카메라 예제 애플리케이션의 구조도)
애플리케이션을 코딩하기전에 androidManifest부터 설정을 해야한다.
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>
그다음 영상을 위한 출력을 해보자.
먼저 출력할 영역을 설정을 해야하는데, 이부분은 xml로도 가능하고 바로 코딩으로도 가능하다. 출력은 SurfaceView에서하는데 Surface를 생성하도록 SurfaceFlinger서비스에 요청을 해야한다. 그런데 SurfaceView를 관리하기 위한 SurfaceHolder가 존재하고 이를 통해 SurfaceView영역에 대한 처리를 SurfaceFlinger에 요청을 한다.
public class CameraPreview extends Activity{
private Preview mPreview;
protected void onCreate(Bundle savedInstanceState){
mPreview = new Preview(this);
setContentView(mPreview);
}
}
Preview 클래스는 ViewGroup 클래스를 확장하고, SurfaceHolder.Callback 인터페이스를 구현하였다. Preview 클래스는 인스턴스 생성 시 SurfaceVIew와 관련된 처리를 수행한다.
ViewGroup은 android.view.ViewGroup으로 View클래스를 확장한것이다. 그런데 이는 다른뷰를 포함할 수 있는 특별한 뷰이다.
SurfaceHolder.Callback 인터페이스는 SurfaceFlinger서비스에서 요청된 Surface를 생성하거나 소멸시킬 때를 알기 위한 것으로, 애플리케이션이 Surface에 직접 접근할 권한이 없기 때문에 SurfaceHolder.Callback 인터페이스를 통해 콜백 메서드를 구현하여 Surface를 처리하여야 한다.
class Preview extends ViewGroup implements surfaceholder.callback{
Surfaceview mSurfaceView;
SurfaceHolder mHolder;
Preview(Context context){
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView);
//Install a SurfaceHolder. Callback so we get notified when the
//underlying surface is created and destroyed.
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
}
SufaceView 와 SurfaceHolder를 연결을 시켜야 하는데, 이 역할을 addCallback()메서드로 하게 된다. 이후 Surface가 생성되거나 소멸될 때, 속성이 변경될 때 콜백 메서드를 통해 Preview 인스턴스의 메서드를 호출한다.
이렇게 출력할 화면이 준비가 되면, 그 다음으로 카메라 장치와 이를 연결을 해주면 된다. 위의 CameraPreview애플리케이션이 구동이 되면
onResume()메서드가 호출이 되고, 이때 카메라 서비스를 이용해 카메라를 구동한다.
android.hardware.Camera의 open()메서드로 카메라 서비스를 이용해 카메라 장치를 활성화 하고, Camera 인스턴스를 얻어 온다.
그 후 Preview의 setCamera() 메서드를 호출하여 카메라 정보를 기반으로 레이아웃을 설정한다.
protected void onResume(){
mCamera = Camera.open();
mPreview.setCamera(mCamera);
}
public void setCamera(Camera camera){
mCamera = camera;
if(mCamera !=null){
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
}
}
애플리케이션에서 카메라 서비스의 현재 설정값을 얻고자 할때는
android.hardware.Camera에서 제공하는 getParameters()메서드를 사용한다.
카메라의 매개변수 중에서 카메라가 지원하는 프리뷰 크기 정보를 기반으로 하여,
Preview의 onMeasure()메서드에서 적절한 프리뷰 크기를 찾고,
Preview의 onLayout()메서드에서 선택된 프리뷰 크기 정보를 기반으로 뷰를 생성하고 크기 및 위치를 조정한다.
카메라 영상이 출력될 Surface가 생성되면 surfaceCreate()메서드가 호출되고,
카메라 서비스에 프리뷰 영역으로 생성된 Surface에 카메라 프리뷰가 출력되도록 설정한다.
public void surfaceCreated(SurfaceHolder holder){
try{
if(mCamera != null){
mCamera.setPreviewDisplay(holder);
}
}
}
이후 Surface가 변경되어 프리뷰 인스턴스의 surfaceChanged()메서드가 호출되면,
카메라의 현재 매개변수 값을 다시 가져와 선택된 프리뷰 크기로 변경하고,
setParameters()메서드로 프리뷰 카메라에 설정한다.
이후 startPreview()메서드로 카메라 서비스에서 영상을 가져와 화면에 출력한다.
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h){
//Now that the size is known, set up the camera parameters and begin the //preview.
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height);
requestLayout();
mCamera.setParameters(parameters);
mCamera.startPreview();
}
'CS > 안드로이드' 카테고리의 다른 글
[안드로이드] 카메라 #3_Callback (0) | 2016.10.24 |
---|---|
[안드로이드] 카메라 #1_매커니즘 (0) | 2016.10.24 |