You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
687 lines
25 KiB
687 lines
25 KiB
package com.flurgle.camerakit;
|
|
|
|
import android.graphics.Rect;
|
|
import android.graphics.YuvImage;
|
|
import android.hardware.Camera;
|
|
import android.media.CamcorderProfile;
|
|
import android.media.MediaRecorder;
|
|
import android.os.Build;
|
|
import android.os.Handler;
|
|
import android.util.Log;
|
|
import android.support.annotation.Nullable;
|
|
import android.view.MotionEvent;
|
|
import android.view.SurfaceHolder;
|
|
import android.view.View;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.TreeSet;
|
|
|
|
import static com.flurgle.camerakit.CameraKit.Constants.FLASH_OFF;
|
|
import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_CONTINUOUS;
|
|
import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_OFF;
|
|
import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_TAP;
|
|
import static com.flurgle.camerakit.CameraKit.Constants.METHOD_STANDARD;
|
|
import static com.flurgle.camerakit.CameraKit.Constants.METHOD_STILL;
|
|
|
|
@SuppressWarnings("deprecation")
|
|
public class Camera1 extends CameraImpl {
|
|
|
|
private static final String TAG = Camera1.class.getSimpleName();
|
|
|
|
private static final int FOCUS_AREA_SIZE_DEFAULT = 300;
|
|
private static final int FOCUS_METERING_AREA_WEIGHT_DEFAULT = 1000;
|
|
private static final int DELAY_MILLIS_BEFORE_RESETTING_FOCUS = 3000;
|
|
|
|
private int mCameraId;
|
|
private Camera mCamera;
|
|
private Camera.Parameters mCameraParameters;
|
|
private CameraProperties mCameraProperties;
|
|
private Camera.CameraInfo mCameraInfo;
|
|
private Size mPreviewSize;
|
|
private Size mCaptureSize;
|
|
private MediaRecorder mMediaRecorder;
|
|
private File mVideoFile;
|
|
private Camera.AutoFocusCallback mAutofocusCallback;
|
|
private boolean capturingImage = false;
|
|
|
|
private int mDisplayOrientation;
|
|
|
|
@Facing
|
|
private int mFacing;
|
|
|
|
@Flash
|
|
private int mFlash;
|
|
|
|
@Focus
|
|
private int mFocus;
|
|
|
|
@Method
|
|
private int mMethod;
|
|
|
|
@Zoom
|
|
private int mZoom;
|
|
|
|
@VideoQuality
|
|
private int mVideoQuality;
|
|
|
|
private Handler mHandler = new Handler();
|
|
|
|
Camera1(CameraListener callback, PreviewImpl preview) {
|
|
super(callback, preview);
|
|
preview.setCallback(new PreviewImpl.Callback() {
|
|
@Override
|
|
public void onSurfaceChanged() {
|
|
if (mCamera != null) {
|
|
setupPreview();
|
|
adjustCameraParameters();
|
|
}
|
|
}
|
|
});
|
|
|
|
mCameraInfo = new Camera.CameraInfo();
|
|
|
|
}
|
|
|
|
// CameraImpl:
|
|
|
|
@Override
|
|
void start() {
|
|
setFacing(mFacing);
|
|
openCamera();
|
|
if (mPreview.isReady()) setupPreview();
|
|
mCamera.startPreview();
|
|
}
|
|
|
|
@Override
|
|
void stop() {
|
|
if (mCamera != null) mCamera.stopPreview();
|
|
mHandler.removeCallbacksAndMessages(null);
|
|
releaseCamera();
|
|
}
|
|
|
|
@Override
|
|
void setDisplayOrientation(int displayOrientation) {
|
|
this.mDisplayOrientation = displayOrientation;
|
|
}
|
|
|
|
@Override
|
|
void setFacing(@Facing int facing) {
|
|
int internalFacing = new ConstantMapper.Facing(facing).map();
|
|
if (internalFacing == -1) {
|
|
return;
|
|
}
|
|
|
|
for (int i = 0, count = Camera.getNumberOfCameras(); i < count; i++) {
|
|
Camera.getCameraInfo(i, mCameraInfo);
|
|
if (mCameraInfo.facing == internalFacing) {
|
|
mCameraId = i;
|
|
mFacing = facing;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (mFacing == facing && isCameraOpened()) {
|
|
stop();
|
|
start();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
void setFlash(@Flash int flash) {
|
|
if (mCameraParameters != null) {
|
|
List<String> flashes = mCameraParameters.getSupportedFlashModes();
|
|
String internalFlash = new ConstantMapper.Flash(flash).map();
|
|
if (flashes != null && flashes.contains(internalFlash)) {
|
|
mCameraParameters.setFlashMode(internalFlash);
|
|
mFlash = flash;
|
|
} else {
|
|
String currentFlash = new ConstantMapper.Flash(mFlash).map();
|
|
if (flashes == null || !flashes.contains(currentFlash)) {
|
|
mCameraParameters.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
|
|
mFlash = FLASH_OFF;
|
|
}
|
|
}
|
|
|
|
mCamera.setParameters(mCameraParameters);
|
|
} else {
|
|
mFlash = flash;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
void setFocus(@Focus int focus) {
|
|
this.mFocus = focus;
|
|
switch (focus) {
|
|
case FOCUS_CONTINUOUS:
|
|
if (mCameraParameters != null) {
|
|
detachFocusTapListener();
|
|
final List<String> modes = mCameraParameters.getSupportedFocusModes();
|
|
if (modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
|
|
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
|
|
} else {
|
|
setFocus(FOCUS_OFF);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FOCUS_TAP:
|
|
if (mCameraParameters != null) {
|
|
attachFocusTapListener();
|
|
final List<String> modes = mCameraParameters.getSupportedFocusModes();
|
|
if (modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
|
|
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case FOCUS_OFF:
|
|
if (mCameraParameters != null) {
|
|
detachFocusTapListener();
|
|
final List<String> modes = mCameraParameters.getSupportedFocusModes();
|
|
if (modes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) {
|
|
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED);
|
|
} else if (modes.contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
|
|
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
|
|
} else {
|
|
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
void setMethod(@Method int method) {
|
|
this.mMethod = method;
|
|
}
|
|
|
|
@Override
|
|
void setZoom(@Zoom int zoom) {
|
|
this.mZoom = zoom;
|
|
}
|
|
|
|
@Override
|
|
void setVideoQuality(int videoQuality) {
|
|
this.mVideoQuality = videoQuality;
|
|
}
|
|
|
|
@Override
|
|
void captureImage() {
|
|
switch (mMethod) {
|
|
case METHOD_STANDARD:
|
|
// Null check required for camera here as is briefly null when View is detached
|
|
if (!capturingImage && mCamera != null) {
|
|
|
|
// Set boolean to wait for image callback
|
|
capturingImage = true;
|
|
|
|
mCamera.takePicture(null, null, null,
|
|
new Camera.PictureCallback() {
|
|
@Override
|
|
public void onPictureTaken(byte[] data, Camera camera) {
|
|
mCameraListener.onPictureTaken(data);
|
|
|
|
// Reset capturing state to allow photos to be taken
|
|
capturingImage = false;
|
|
|
|
camera.startPreview();
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
Log.w(TAG, "Unable, waiting for picture to be taken");
|
|
}
|
|
break;
|
|
|
|
case METHOD_STILL:
|
|
mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
|
|
@Override
|
|
public void onPreviewFrame(byte[] data, Camera camera) {
|
|
new Thread(new ProcessStillTask(data, camera, calculateCaptureRotation(), new ProcessStillTask.OnStillProcessedListener() {
|
|
@Override
|
|
public void onStillProcessed(final YuvImage yuv) {
|
|
mCameraListener.onPictureTaken(yuv);
|
|
}
|
|
})).start();
|
|
}
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
void startVideo() {
|
|
initMediaRecorder();
|
|
prepareMediaRecorder();
|
|
mMediaRecorder.start();
|
|
}
|
|
|
|
@Override
|
|
void endVideo() {
|
|
mMediaRecorder.stop();
|
|
mMediaRecorder.release();
|
|
mMediaRecorder = null;
|
|
mCameraListener.onVideoTaken(mVideoFile);
|
|
}
|
|
|
|
// Code from SandriosCamera library
|
|
// https://github.com/sandrios/sandriosCamera/blob/master/sandriosCamera/src/main/java/com/sandrios/sandriosCamera/internal/utils/CameraHelper.java#L218
|
|
public static Size getSizeWithClosestRatio(List<Size> sizes, int width, int height)
|
|
{
|
|
if (sizes == null) return null;
|
|
|
|
double MIN_TOLERANCE = 100;
|
|
double targetRatio = (double) height / width;
|
|
Size optimalSize = null;
|
|
double minDiff = Double.MAX_VALUE;
|
|
|
|
int targetHeight = height;
|
|
|
|
for (Size size : sizes) {
|
|
if (size.getWidth() == width && size.getHeight() == height)
|
|
return size;
|
|
|
|
double ratio = (double) size.getHeight() / size.getWidth();
|
|
|
|
if (Math.abs(ratio - targetRatio) < MIN_TOLERANCE) MIN_TOLERANCE = ratio;
|
|
else continue;
|
|
|
|
if (Math.abs(size.getHeight() - targetHeight) < minDiff) {
|
|
optimalSize = size;
|
|
minDiff = Math.abs(size.getHeight() - targetHeight);
|
|
}
|
|
}
|
|
|
|
if (optimalSize == null) {
|
|
minDiff = Double.MAX_VALUE;
|
|
for (Size size : sizes) {
|
|
if (Math.abs(size.getHeight() - targetHeight) < minDiff) {
|
|
optimalSize = size;
|
|
minDiff = Math.abs(size.getHeight() - targetHeight);
|
|
}
|
|
}
|
|
}
|
|
return optimalSize;
|
|
}
|
|
|
|
List<Size> sizesFromList(List<Camera.Size> sizes) {
|
|
if (sizes == null) return null;
|
|
List<Size> result = new ArrayList<>(sizes.size());
|
|
|
|
for (Camera.Size size : sizes) {
|
|
result.add(new Size(size.width, size.height));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// Code from SandriosCamera library
|
|
// https://github.com/sandrios/sandriosCamera/blob/master/sandriosCamera/src/main/java/com/sandrios/sandriosCamera/internal/manager/impl/Camera1Manager.java#L212
|
|
void initResolutions() {
|
|
List<Size> previewSizes = sizesFromList(mCameraParameters.getSupportedPreviewSizes());
|
|
List<Size> videoSizes = (Build.VERSION.SDK_INT > 10) ? sizesFromList(mCameraParameters.getSupportedVideoSizes()) : previewSizes;
|
|
|
|
CamcorderProfile camcorderProfile = getCamcorderProfile(mVideoQuality);
|
|
|
|
mCaptureSize = getSizeWithClosestRatio(
|
|
(videoSizes == null || videoSizes.isEmpty()) ? previewSizes : videoSizes,
|
|
camcorderProfile.videoFrameWidth, camcorderProfile.videoFrameHeight);
|
|
|
|
mPreviewSize = getSizeWithClosestRatio(previewSizes, mCaptureSize.getWidth(), mCaptureSize.getHeight());
|
|
}
|
|
|
|
@Override
|
|
Size getCaptureResolution() {
|
|
return mCaptureSize;
|
|
}
|
|
|
|
@Override
|
|
Size getPreviewResolution() {
|
|
return mPreviewSize;
|
|
}
|
|
|
|
@Override
|
|
boolean isCameraOpened() {
|
|
return mCamera != null;
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
CameraProperties getCameraProperties() {
|
|
return mCameraProperties;
|
|
}
|
|
|
|
// Internal:
|
|
|
|
private void openCamera() {
|
|
if (mCamera != null) {
|
|
releaseCamera();
|
|
}
|
|
|
|
mCamera = Camera.open(mCameraId);
|
|
mCameraParameters = mCamera.getParameters();
|
|
|
|
collectCameraProperties();
|
|
adjustCameraParameters();
|
|
mCamera.setDisplayOrientation(calculatePreviewRotation());
|
|
|
|
mCameraListener.onCameraOpened();
|
|
}
|
|
|
|
private void setupPreview() {
|
|
try {
|
|
if (mPreview.getOutputClass() == SurfaceHolder.class) {
|
|
mCamera.setPreviewDisplay(mPreview.getSurfaceHolder());
|
|
} else {
|
|
mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
|
|
}
|
|
} catch (IOException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
|
|
private void releaseCamera() {
|
|
if (mCamera != null) {
|
|
mCamera.release();
|
|
mCamera = null;
|
|
mCameraParameters = null;
|
|
mPreviewSize = null;
|
|
mCaptureSize = null;
|
|
mCameraListener.onCameraClosed();
|
|
}
|
|
}
|
|
|
|
private int calculatePreviewRotation() {
|
|
if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
|
return ((mCameraInfo.orientation - mDisplayOrientation) + 360 + 180) % 360;
|
|
} else {
|
|
return (mCameraInfo.orientation - mDisplayOrientation + 360) % 360;
|
|
}
|
|
}
|
|
|
|
private int calculateCaptureRotation() {
|
|
int previewRotation = calculatePreviewRotation();
|
|
if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
|
//Front is flipped
|
|
return (previewRotation + 180 + 2*mDisplayOrientation + 720) %360;
|
|
} else {
|
|
return previewRotation;
|
|
}
|
|
}
|
|
|
|
private void adjustCameraParameters() {
|
|
initResolutions();
|
|
|
|
boolean invertPreviewSizes = mDisplayOrientation%180 != 0;
|
|
mPreview.setTruePreviewSize(
|
|
invertPreviewSizes? getPreviewResolution().getHeight() : getPreviewResolution().getWidth(),
|
|
invertPreviewSizes? getPreviewResolution().getWidth() : getPreviewResolution().getHeight()
|
|
);
|
|
|
|
mCameraParameters.setPreviewSize(
|
|
getPreviewResolution().getWidth(),
|
|
getPreviewResolution().getHeight()
|
|
);
|
|
|
|
mCameraParameters.setPictureSize(
|
|
getCaptureResolution().getWidth(),
|
|
getCaptureResolution().getHeight()
|
|
);
|
|
int rotation = calculateCaptureRotation();
|
|
mCameraParameters.setRotation(rotation);
|
|
|
|
setFocus(mFocus);
|
|
setFlash(mFlash);
|
|
|
|
mCamera.setParameters(mCameraParameters);
|
|
}
|
|
|
|
private void collectCameraProperties() {
|
|
mCameraProperties = new CameraProperties(mCameraParameters.getVerticalViewAngle(),
|
|
mCameraParameters.getHorizontalViewAngle());
|
|
}
|
|
|
|
private TreeSet<AspectRatio> findCommonAspectRatios(List<Camera.Size> previewSizes, List<Camera.Size> captureSizes) {
|
|
Set<AspectRatio> previewAspectRatios = new HashSet<>();
|
|
for (Camera.Size size : previewSizes) {
|
|
if (size.width >= CameraKit.Internal.screenHeight && size.height >= CameraKit.Internal.screenWidth) {
|
|
previewAspectRatios.add(AspectRatio.of(size.width, size.height));
|
|
}
|
|
}
|
|
|
|
Set<AspectRatio> captureAspectRatios = new HashSet<>();
|
|
for (Camera.Size size : captureSizes) {
|
|
captureAspectRatios.add(AspectRatio.of(size.width, size.height));
|
|
}
|
|
|
|
TreeSet<AspectRatio> output = new TreeSet<>();
|
|
for (AspectRatio aspectRatio : previewAspectRatios) {
|
|
if (captureAspectRatios.contains(aspectRatio)) {
|
|
output.add(aspectRatio);
|
|
}
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
private void initMediaRecorder() {
|
|
mMediaRecorder = new MediaRecorder();
|
|
mCamera.unlock();
|
|
|
|
mMediaRecorder.setCamera(mCamera);
|
|
|
|
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
|
|
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
|
|
|
|
mMediaRecorder.setProfile(getCamcorderProfile(mVideoQuality));
|
|
|
|
mVideoFile = new File(mPreview.getView().getContext().getExternalFilesDir(null), "video.mp4");
|
|
mMediaRecorder.setOutputFile(mVideoFile.getAbsolutePath());
|
|
mMediaRecorder.setOrientationHint(calculatePreviewRotation());
|
|
mMediaRecorder.setVideoSize(mCaptureSize.getWidth(), mCaptureSize.getHeight());
|
|
}
|
|
|
|
private void prepareMediaRecorder() {
|
|
try {
|
|
mMediaRecorder.prepare();
|
|
} catch (IllegalStateException e) {
|
|
e.printStackTrace();
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
private CamcorderProfile getCamcorderProfile(@VideoQuality int videoQuality) {
|
|
CamcorderProfile camcorderProfile = null;
|
|
switch (videoQuality) {
|
|
case CameraKit.Constants.VIDEO_QUALITY_QVGA:
|
|
if (CamcorderProfile.hasProfile(mCameraId, CamcorderProfile.QUALITY_QVGA)) {
|
|
camcorderProfile = CamcorderProfile.get(mCameraId, CamcorderProfile.QUALITY_QVGA);
|
|
} else {
|
|
return getCamcorderProfile(CameraKit.Constants.VIDEO_QUALITY_LOWEST);
|
|
}
|
|
break;
|
|
|
|
case CameraKit.Constants.VIDEO_QUALITY_480P:
|
|
if (CamcorderProfile.hasProfile(mCameraId, CamcorderProfile.QUALITY_480P)) {
|
|
camcorderProfile = CamcorderProfile.get(mCameraId, CamcorderProfile.QUALITY_480P);
|
|
} else {
|
|
return getCamcorderProfile(CameraKit.Constants.VIDEO_QUALITY_QVGA);
|
|
}
|
|
break;
|
|
|
|
case CameraKit.Constants.VIDEO_QUALITY_720P:
|
|
if (CamcorderProfile.hasProfile(mCameraId, CamcorderProfile.QUALITY_720P)) {
|
|
camcorderProfile = CamcorderProfile.get(mCameraId, CamcorderProfile.QUALITY_720P);
|
|
} else {
|
|
return getCamcorderProfile(CameraKit.Constants.VIDEO_QUALITY_480P);
|
|
}
|
|
break;
|
|
|
|
case CameraKit.Constants.VIDEO_QUALITY_1080P:
|
|
if (CamcorderProfile.hasProfile(mCameraId, CamcorderProfile.QUALITY_1080P)) {
|
|
camcorderProfile = CamcorderProfile.get(mCameraId, CamcorderProfile.QUALITY_1080P);
|
|
} else {
|
|
return getCamcorderProfile(CameraKit.Constants.VIDEO_QUALITY_720P);
|
|
}
|
|
break;
|
|
|
|
case CameraKit.Constants.VIDEO_QUALITY_2160P:
|
|
try {
|
|
camcorderProfile = CamcorderProfile.get(mCameraId, CamcorderProfile.QUALITY_2160P);
|
|
} catch (Exception e) {
|
|
return getCamcorderProfile(CameraKit.Constants.VIDEO_QUALITY_HIGHEST);
|
|
}
|
|
break;
|
|
|
|
case CameraKit.Constants.VIDEO_QUALITY_HIGHEST:
|
|
camcorderProfile = CamcorderProfile.get(mCameraId, CamcorderProfile.QUALITY_HIGH);
|
|
break;
|
|
|
|
case CameraKit.Constants.VIDEO_QUALITY_LOWEST:
|
|
camcorderProfile = CamcorderProfile.get(mCameraId, CamcorderProfile.QUALITY_LOW);
|
|
break;
|
|
}
|
|
|
|
return camcorderProfile;
|
|
}
|
|
|
|
void setTapToAutofocusListener(Camera.AutoFocusCallback callback) {
|
|
if (this.mFocus != FOCUS_TAP) {
|
|
throw new IllegalArgumentException("Please set the camera to FOCUS_TAP.");
|
|
}
|
|
|
|
this.mAutofocusCallback = callback;
|
|
}
|
|
|
|
private int getFocusAreaSize() {
|
|
return FOCUS_AREA_SIZE_DEFAULT;
|
|
}
|
|
|
|
private int getFocusMeteringAreaWeight() {
|
|
return FOCUS_METERING_AREA_WEIGHT_DEFAULT;
|
|
}
|
|
|
|
private void detachFocusTapListener() {
|
|
mPreview.getView().setOnTouchListener(null);
|
|
}
|
|
|
|
private void attachFocusTapListener() {
|
|
mPreview.getView().setOnTouchListener(new View.OnTouchListener() {
|
|
@Override
|
|
public boolean onTouch(View v, MotionEvent event) {
|
|
if (event.getAction() == MotionEvent.ACTION_UP) {
|
|
if (mCamera != null) {
|
|
Camera.Parameters parameters = mCamera.getParameters();
|
|
String focusMode = parameters.getFocusMode();
|
|
Rect rect = calculateFocusArea(event.getX(), event.getY());
|
|
List<Camera.Area> meteringAreas = new ArrayList<>();
|
|
meteringAreas.add(new Camera.Area(rect, getFocusMeteringAreaWeight()));
|
|
if (parameters.getMaxNumFocusAreas() != 0 && focusMode != null &&
|
|
(focusMode.equals(Camera.Parameters.FOCUS_MODE_AUTO) ||
|
|
focusMode.equals(Camera.Parameters.FOCUS_MODE_MACRO) ||
|
|
focusMode.equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) ||
|
|
focusMode.equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
|
|
) {
|
|
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
|
|
parameters.setFocusAreas(meteringAreas);
|
|
if (parameters.getMaxNumMeteringAreas() > 0) {
|
|
parameters.setMeteringAreas(meteringAreas);
|
|
}
|
|
if(!parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
|
|
return false; //cannot autoFocus
|
|
}
|
|
mCamera.setParameters(parameters);
|
|
mCamera.autoFocus(new Camera.AutoFocusCallback() {
|
|
@Override
|
|
public void onAutoFocus(boolean success, Camera camera) {
|
|
resetFocus(success, camera);
|
|
}
|
|
});
|
|
} else if (parameters.getMaxNumMeteringAreas() > 0) {
|
|
if(!parameters.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO)) {
|
|
return false; //cannot autoFocus
|
|
}
|
|
parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
|
|
parameters.setFocusAreas(meteringAreas);
|
|
parameters.setMeteringAreas(meteringAreas);
|
|
|
|
mCamera.setParameters(parameters);
|
|
mCamera.autoFocus(new Camera.AutoFocusCallback() {
|
|
@Override
|
|
public void onAutoFocus(boolean success, Camera camera) {
|
|
resetFocus(success, camera);
|
|
}
|
|
});
|
|
} else {
|
|
mCamera.autoFocus(new Camera.AutoFocusCallback() {
|
|
@Override
|
|
public void onAutoFocus(boolean success, Camera camera) {
|
|
if (mAutofocusCallback != null) {
|
|
mAutofocusCallback.onAutoFocus(success, camera);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
});
|
|
}
|
|
|
|
private void resetFocus(final boolean success, final Camera camera) {
|
|
mHandler.removeCallbacksAndMessages(null);
|
|
mHandler.postDelayed(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (camera != null) {
|
|
camera.cancelAutoFocus();
|
|
Camera.Parameters params = camera.getParameters();
|
|
if (params.getFocusMode() != Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {
|
|
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
|
|
params.setFocusAreas(null);
|
|
params.setMeteringAreas(null);
|
|
camera.setParameters(params);
|
|
}
|
|
|
|
if (mAutofocusCallback != null) {
|
|
mAutofocusCallback.onAutoFocus(success, camera);
|
|
}
|
|
}
|
|
}
|
|
}, DELAY_MILLIS_BEFORE_RESETTING_FOCUS);
|
|
}
|
|
|
|
private Rect calculateFocusArea(float x, float y) {
|
|
int buffer = getFocusAreaSize() / 2;
|
|
int centerX = calculateCenter(x, mPreview.getView().getWidth(), buffer);
|
|
int centerY = calculateCenter(y, mPreview.getView().getHeight(), buffer);
|
|
return new Rect(
|
|
centerX - buffer,
|
|
centerY - buffer,
|
|
centerX + buffer,
|
|
centerY + buffer
|
|
);
|
|
}
|
|
|
|
private static int calculateCenter(float coord, int dimen, int buffer) {
|
|
int normalized = (int) ((coord / dimen) * 2000 - 1000);
|
|
if (Math.abs(normalized) + buffer > 1000) {
|
|
if (normalized > 0) {
|
|
return 1000 - buffer;
|
|
} else {
|
|
return -1000 + buffer;
|
|
}
|
|
} else {
|
|
return normalized;
|
|
}
|
|
}
|
|
|
|
}
|
|
|