Programming/Android

android 카메라 전환

Min 2017. 7. 13. 14:16
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
String TAG = "KTH";
private SurfaceHolder mHolder;
private Camera mCamera;
Activity mCtx;

public CameraPreview(Context context, Camera camera) {
super(context);
mCamera = camera;
this.mCtx = (Activity) context;

// SurfaceHolder 가 가지고 있는 하위 Surface가 파괴되거나 업데이트 될경우 받을 콜백을 세팅한다
mHolder = getHolder();
mHolder.addCallback(this);
// deprecated 되었지만 3.0 이하 버젼에서 필수 메소드라서 호출해둠.
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

}


@Override
public void surfaceCreated(SurfaceHolder holder) {
Logger.log("surfaceCreated done");
// Surface가 생성되었으니 프리뷰를 어디에 띄울지 지정해준다. (holder 로 받은 SurfaceHolder에 뿌려준다.
try {
Camera.Parameters parameters = mCamera.getParameters();
if (getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
Logger.log("camera has open portrait");
parameters.set("orientation", "portrait");
mCamera.setDisplayOrientation(90);
parameters.setRotation(90);
} else {
Logger.log("camera has open landscape");
parameters.set("orientation", "landscape");
mCamera.setDisplayOrientation(0);
parameters.setRotation(0);
}
// mCamera.setDisplayOrientation(90);
// parameters.setRotation(90);

mCamera.setParameters(parameters);
mCamera.setPreviewDisplay(holder);
mCamera.startPreview();
} catch (IOException e) {
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
}
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// 프리뷰 제거시 카메라 사용도 끝났다고 간주하여 리소스를 전부 반환한다
if (mCamera != null) {
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mCamera.release();
mCamera = null;
Logger.log("카메라 기능 해제");
}
}


private Camera.Size getBestPreviewSize(int width, int height) {
Logger.log("getBestPreviewSize -> " + width + "," + height);
Camera.Size result = null;
Camera.Parameters p = mCamera.getParameters();
// for (Camera.Size size : p.getSupportedPreviewSizes()) {
//
// if (size.width <= width && size.height <= height) {
// if (result == null) {
// result = size;
// } else {
// int resultArea = result.width * result.height;
// int newArea = size.width * size.height;
//
// Logger.log("support camera size -> " + size.width + "," + size.height + "," + resultArea + "," + newArea);
//
// if (newArea > resultArea) {
// result = size;
// }
// }
// }
// }
return p.getSupportedPreviewSizes().get(0);
// return result;

}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// 프리뷰를 회전시키거나 변경시 처리를 여기서 해준다.
// 프리뷰 변경시에는 먼저 프리뷰를 멈춘다음 변경해야한다.
if (mHolder.getSurface() == null) {
// 프리뷰가 존재하지 않을때
return;
}

// 우선 멈춘다
try {
mCamera.stopPreview();
} catch (Exception e) {
// 프리뷰가 존재조차 하지 않는 경우다
}

// 프리뷰 변경, 처리 등을 여기서 해준다.
Camera.Parameters parameters = mCamera.getParameters();

int screen_size[] = CommonUtils.getDisplaySize(mCtx);

Camera.Size size = getBestPreviewSize( screen_size[0], screen_size[1]);
parameters.setPreviewSize(size.width, size.height);

Logger.log("preview size->" + screen_size[1] + "," + screen_size[0] + "," + size.width + "," + size.height);

mCamera.setParameters(parameters);
// 새로 변경된 설정으로 프리뷰를 재생성한다
try {
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();

} catch (Exception e) {
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
}


public class TakeCameraActivity extends AppCompatActivity {

CameraPreview mPreview;
Camera mCamera;
Context mContext;
FrameLayout preview;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_take_camera);
Userhabit.start(this);

if(checkCameraHardware(this)) {
init();
}

}

private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA) &&
context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)
){
// 카메라가 최소한 한개 있는 경우 처리
Logger.log("Number of available camera : "+ Camera.getNumberOfCameras());

return true;
} else {
// 카메라가 전혀 없는 경우
Toast.makeText(this, "No camera found!", Toast.LENGTH_SHORT).show();
finish();
return false;
}
}


private void init(){
mContext = this;

startCamera(Camera.CameraInfo.CAMERA_FACING_FRONT);

// 촬영버튼 등록
Button captureButton = (Button) findViewById(R.id.btnCommonBottom);
captureButton.setOnClickListener(v -> mCamera.takePicture(null,null,mPicture));

Button btn = (Button) findViewById(R.id.btn);


//카메라 전환
btn.setOnClickListener(v->{
changeCamera();
});

}

boolean isFrontCamera = true;

private void closeCamera() {
if(mCamera!=null){
// mCamera.stopPreview();
// mCamera.release();
// mCamera = null;
mPreview.surfaceDestroyed(mPreview.getHolder());
mPreview.getHolder().removeCallback(mPreview);
mPreview.destroyDrawingCache();
preview.removeView(mPreview);
}
}

public void changeCamera() {
closeCamera();

isFrontCamera = !isFrontCamera;
if (isFrontCamera) {
startCamera(Camera.CameraInfo.CAMERA_FACING_FRONT);
} else {
startCamera(Camera.CameraInfo.CAMERA_FACING_BACK);
}
// mCamera.startPreview();
}

private void startCamera(int facing){
mCamera = getCameraInstance(facing);
mPreview = new CameraPreview(this, mCamera);
preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
}


private Camera getCameraInstance(int facing){
int cameraCount = 0;
Camera cam = null;
Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
cameraCount = Camera.getNumberOfCameras();
for (int cameraId = 0; cameraId < cameraCount; cameraId++) {
Camera.
getCameraInfo(cameraId, cameraInfo);
if (cameraInfo.facing == facing) {
try {
cam = Camera.
open(cameraId);
break;
} catch (RuntimeException e) {
e.printStackTrace()
;
}
}
}
return cam;
}


private Camera.PictureCallback mPicture = new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
// JPEG 이미지가 byte[] 형태로 들어옵니다.
File pictureFile = getOutputMediaFile();
if(pictureFile == null){
Toast.makeText(mContext, "Error camera image saving", Toast.LENGTH_SHORT).show();
return;
}

try{
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
//Thread.sleep(500);
// mCamera.startPreview();
Logger.log("carmera take pickture done");

Intent intent = new Intent();
intent.putExtra("taken_camera_image_path" , pictureFile.getAbsolutePath());
setResult(RESULT_OK , intent);
finish();

} catch (FileNotFoundException e) {
Logger.log("File not found: " + e.getMessage());
} catch (IOException e) {
Logger.log("Error accessing file: " + e.getMessage());
}
}
};
}