Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,11 @@ public void run() {
});
}

@Override
public void notPermission() {
Toast.makeText(MainActivity.this, R.string.camera_permission_not_granted,
Toast.LENGTH_SHORT).show();
}
};

public static class ConfirmationDialogFragment extends DialogFragment {
Expand Down
149 changes: 142 additions & 7 deletions library/src/main/api14/com/google/android/cameraview/Camera1.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,19 @@
package com.google.android.cameraview;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Build;
import android.os.Handler;
import android.support.v4.util.SparseArrayCompat;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
Expand Down Expand Up @@ -71,6 +77,10 @@ class Camera1 extends CameraViewImpl {

private int mDisplayOrientation;

private Handler mHandler = new Handler();

private Camera.AutoFocusCallback mAutofocusCallback;

Camera1(Callback callback, PreviewImpl preview) {
super(callback, preview);
preview.setCallback(new PreviewImpl.Callback() {
Expand All @@ -86,14 +96,19 @@ public void onSurfaceChanged() {

@Override
boolean start() {
chooseCamera();
openCamera();
if (mPreview.isReady()) {
setUpPreview();
try {
chooseCamera();
openCamera();
if (mPreview.isReady()) {
setUpPreview();
}
mShowingPreview = true;
mCamera.startPreview();
return true;
} catch (Exception e) {
mCallback.notPermission();
return false;
}
mShowingPreview = true;
mCamera.startPreview();
return true;
}

@Override
Expand All @@ -102,6 +117,8 @@ void stop() {
mCamera.stopPreview();
}
mShowingPreview = false;
if (mHandler != null)
mHandler.removeCallbacksAndMessages(null);
releaseCamera();
}

Expand Down Expand Up @@ -438,12 +455,16 @@ private boolean setAutoFocusInternal(boolean autoFocus) {
if (isCameraOpened()) {
final List<String> modes = mCameraParameters.getSupportedFocusModes();
if (autoFocus && modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
attachFocusTapListener();
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
} else if (modes.contains(Camera.Parameters.FOCUS_MODE_FIXED)) {
detachFocusTapListener();
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_FIXED);
} else if (modes.contains(Camera.Parameters.FOCUS_MODE_INFINITY)) {
detachFocusTapListener();
mCameraParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_INFINITY);
} else {
detachFocusTapListener();
mCameraParameters.setFocusMode(modes.get(0));
}
return true;
Expand Down Expand Up @@ -477,4 +498,118 @@ private boolean setFlashInternal(int flash) {
}
}

@TargetApi(14)
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;
}
});
}

@TargetApi(14)
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);
}

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
);
}

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;
}
}

}
65 changes: 65 additions & 0 deletions library/src/main/api21/com/google/android/cameraview/Camera2.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,26 @@
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.support.annotation.NonNull;
import android.util.Log;
import android.util.SparseIntArray;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;

import java.nio.ByteBuffer;
import java.util.Arrays;
Expand Down Expand Up @@ -525,14 +530,17 @@ void updateAutoFocus() {
// Auto focus is not supported
if (modes == null || modes.length == 0 ||
(modes.length == 1 && modes[0] == CameraCharacteristics.CONTROL_AF_MODE_OFF)) {
detachFocusTapListener();
mAutoFocus = false;
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_OFF);
} else {
attachFocusTapListener();
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
}
} else {
detachFocusTapListener();
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_OFF);
}
Expand Down Expand Up @@ -671,6 +679,63 @@ void unlockFocus() {
}
}

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) {
Rect rect = mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
if (rect == null) return true;
int areaSize = getFocusAreaSize();
int right = rect.right;
int bottom = rect.bottom;
int viewWidth = mPreview.getView().getWidth();
int viewHeight = mPreview.getView().getHeight();
int ll, rr;
Rect newRect;
int centerX = (int) event.getX();
int centerY = (int) event.getY();
ll = ((centerX * right) - areaSize) / viewWidth;
rr = ((centerY * bottom) - areaSize) / viewHeight;
int focusLeft = clamp(ll, 0, right);
int focusBottom = clamp(rr, 0, bottom);
newRect = new Rect(focusLeft, focusBottom, focusLeft + areaSize, focusBottom + areaSize);
MeteringRectangle meteringRectangle = new MeteringRectangle(newRect, getFocusMeteringAreaWeight());
MeteringRectangle[] meteringRectangleArr = {meteringRectangle};

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, meteringRectangleArr);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, meteringRectangleArr);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START);

updatePreview();
}
}
return true;
}
});
}

private int clamp(int x, int min, int max) {
if (x < min) {
return min;
} else if (x > max) {
return max;
} else {
return x;
}
}

private void updatePreview() {
try {
mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}

/**
* A {@link CameraCaptureSession.CaptureCallback} for capturing a still picture.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@

abstract class CameraViewImpl {

static final int FOCUS_AREA_SIZE_DEFAULT = 300;
static final int FOCUS_METERING_AREA_WEIGHT_DEFAULT = 1000;
static final int DELAY_MILLIS_BEFORE_RESETTING_FOCUS = 3000;

protected final Callback mCallback;

protected final PreviewImpl mPreview;
Expand All @@ -35,6 +39,18 @@ View getView() {
return mPreview.getView();
}

int getFocusAreaSize() {
return FOCUS_AREA_SIZE_DEFAULT;
}

int getFocusMeteringAreaWeight() {
return FOCUS_METERING_AREA_WEIGHT_DEFAULT;
}

void detachFocusTapListener() {
mPreview.getView().setOnTouchListener(null);
}

/**
* @return {@code true} if the implementation was able to start the camera session.
*/
Expand Down Expand Up @@ -77,6 +93,7 @@ interface Callback {

void onPictureTaken(byte[] data);

void notPermission();
}

}
Loading