|
|
@ -8,6 +8,7 @@ import android.arch.lifecycle.LifecycleOwner; |
|
|
|
import android.arch.lifecycle.OnLifecycleEvent; |
|
|
|
import android.arch.lifecycle.OnLifecycleEvent; |
|
|
|
import android.content.Context; |
|
|
|
import android.content.Context; |
|
|
|
import android.content.ContextWrapper; |
|
|
|
import android.content.ContextWrapper; |
|
|
|
|
|
|
|
import android.content.pm.PackageInfo; |
|
|
|
import android.content.pm.PackageManager; |
|
|
|
import android.content.pm.PackageManager; |
|
|
|
import android.content.res.TypedArray; |
|
|
|
import android.content.res.TypedArray; |
|
|
|
import android.graphics.Rect; |
|
|
|
import android.graphics.Rect; |
|
|
@ -18,12 +19,12 @@ import android.support.annotation.NonNull; |
|
|
|
import android.support.annotation.Nullable; |
|
|
|
import android.support.annotation.Nullable; |
|
|
|
import android.support.v4.app.ActivityCompat; |
|
|
|
import android.support.v4.app.ActivityCompat; |
|
|
|
import android.support.v4.content.ContextCompat; |
|
|
|
import android.support.v4.content.ContextCompat; |
|
|
|
import android.support.v4.hardware.display.DisplayManagerCompat; |
|
|
|
|
|
|
|
import android.support.v4.view.ViewCompat; |
|
|
|
|
|
|
|
import android.util.AttributeSet; |
|
|
|
import android.util.AttributeSet; |
|
|
|
|
|
|
|
import android.util.Log; |
|
|
|
import android.view.Display; |
|
|
|
import android.view.Display; |
|
|
|
import android.view.MotionEvent; |
|
|
|
import android.view.MotionEvent; |
|
|
|
import android.view.View; |
|
|
|
import android.view.View; |
|
|
|
|
|
|
|
import android.view.WindowManager; |
|
|
|
import android.widget.FrameLayout; |
|
|
|
import android.widget.FrameLayout; |
|
|
|
|
|
|
|
|
|
|
|
import java.io.ByteArrayOutputStream; |
|
|
|
import java.io.ByteArrayOutputStream; |
|
|
@ -38,9 +39,8 @@ import static com.flurgle.camerakit.CameraKit.Constants.FLASH_OFF; |
|
|
|
import static com.flurgle.camerakit.CameraKit.Constants.FLASH_ON; |
|
|
|
import static com.flurgle.camerakit.CameraKit.Constants.FLASH_ON; |
|
|
|
import static com.flurgle.camerakit.CameraKit.Constants.FLASH_TORCH; |
|
|
|
import static com.flurgle.camerakit.CameraKit.Constants.FLASH_TORCH; |
|
|
|
import static com.flurgle.camerakit.CameraKit.Constants.METHOD_STANDARD; |
|
|
|
import static com.flurgle.camerakit.CameraKit.Constants.METHOD_STANDARD; |
|
|
|
import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_LAZY; |
|
|
|
|
|
|
|
import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_PICTURE; |
|
|
|
import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_PICTURE; |
|
|
|
import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_STRICT; |
|
|
|
import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_VIDEO; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* The CameraView implements the LifecycleObserver interface for ease of use. To take advantage of |
|
|
|
* The CameraView implements the LifecycleObserver interface for ease of use. To take advantage of |
|
|
@ -58,46 +58,37 @@ import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_STRICT; |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final static String TAG = CameraView.class.getSimpleName(); |
|
|
|
|
|
|
|
|
|
|
|
private static Handler sWorkerHandler; |
|
|
|
private static Handler sWorkerHandler; |
|
|
|
|
|
|
|
|
|
|
|
static { |
|
|
|
private static Handler getWorkerHandler() { |
|
|
|
// Initialize a single worker thread. This can be static since only a single camera
|
|
|
|
if (sWorkerHandler == null) { |
|
|
|
// reference can exist at a time.
|
|
|
|
HandlerThread workerThread = new HandlerThread("CameraViewWorker"); |
|
|
|
HandlerThread workerThread = new HandlerThread("CameraViewWorker"); |
|
|
|
workerThread.setDaemon(true); |
|
|
|
workerThread.setDaemon(true); |
|
|
|
workerThread.start(); |
|
|
|
workerThread.start(); |
|
|
|
sWorkerHandler = new Handler(workerThread.getLooper()); |
|
|
|
sWorkerHandler = new Handler(workerThread.getLooper()); |
|
|
|
} |
|
|
|
|
|
|
|
return sWorkerHandler; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Facing |
|
|
|
private void run(Runnable runnable) { |
|
|
|
private int mFacing; |
|
|
|
getWorkerHandler().post(runnable); |
|
|
|
|
|
|
|
} |
|
|
|
@Flash |
|
|
|
|
|
|
|
private int mFlash; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Focus |
|
|
|
|
|
|
|
private int mFocus; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Method |
|
|
|
|
|
|
|
private int mMethod; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Zoom |
|
|
|
|
|
|
|
private int mZoom; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Permissions |
|
|
|
|
|
|
|
private int mPermissions; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@VideoQuality |
|
|
|
@Facing private int mFacing; |
|
|
|
private int mVideoQuality; |
|
|
|
@Flash private int mFlash; |
|
|
|
|
|
|
|
@Focus private int mFocus; |
|
|
|
|
|
|
|
@Method private int mMethod; |
|
|
|
|
|
|
|
@Zoom private int mZoom; |
|
|
|
|
|
|
|
@Permissions private int mPermissions; |
|
|
|
|
|
|
|
@VideoQuality private int mVideoQuality; |
|
|
|
private int mJpegQuality; |
|
|
|
private int mJpegQuality; |
|
|
|
private boolean mCropOutput; |
|
|
|
private boolean mCropOutput; |
|
|
|
|
|
|
|
|
|
|
|
private boolean mAdjustViewBounds; |
|
|
|
private boolean mAdjustViewBounds; |
|
|
|
private CameraListenerMiddleWare mCameraListener; |
|
|
|
private CameraListenerMiddleWare mCameraListener; |
|
|
|
|
|
|
|
private OrientationHelper mOrientationHelper; |
|
|
|
private DisplayOrientationDetector mDisplayOrientationDetector; |
|
|
|
|
|
|
|
private CameraImpl mCameraImpl; |
|
|
|
private CameraImpl mCameraImpl; |
|
|
|
|
|
|
|
|
|
|
|
private PreviewImpl mPreviewImpl; |
|
|
|
private PreviewImpl mPreviewImpl; |
|
|
|
|
|
|
|
|
|
|
|
private Lifecycle mLifecycle; |
|
|
|
private Lifecycle mLifecycle; |
|
|
@ -108,7 +99,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
init(context, null); |
|
|
|
init(context, null); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@SuppressWarnings("all") |
|
|
|
|
|
|
|
public CameraView(@NonNull Context context, @Nullable AttributeSet attrs) { |
|
|
|
public CameraView(@NonNull Context context, @Nullable AttributeSet attrs) { |
|
|
|
super(context, attrs); |
|
|
|
super(context, attrs); |
|
|
|
init(context, attrs); |
|
|
|
init(context, attrs); |
|
|
@ -117,11 +107,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
@SuppressWarnings("WrongConstant") |
|
|
|
@SuppressWarnings("WrongConstant") |
|
|
|
private void init(@NonNull Context context, @Nullable AttributeSet attrs) { |
|
|
|
private void init(@NonNull Context context, @Nullable AttributeSet attrs) { |
|
|
|
if (attrs != null) { |
|
|
|
if (attrs != null) { |
|
|
|
TypedArray a = context.getTheme().obtainStyledAttributes( |
|
|
|
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CameraView, 0, 0); |
|
|
|
attrs, |
|
|
|
|
|
|
|
R.styleable.CameraView, |
|
|
|
|
|
|
|
0, 0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
try { |
|
|
|
mFacing = a.getInteger(R.styleable.CameraView_ckFacing, CameraKit.Defaults.DEFAULT_FACING); |
|
|
|
mFacing = a.getInteger(R.styleable.CameraView_ckFacing, CameraKit.Defaults.DEFAULT_FACING); |
|
|
|
mFlash = a.getInteger(R.styleable.CameraView_ckFlash, CameraKit.Defaults.DEFAULT_FLASH); |
|
|
|
mFlash = a.getInteger(R.styleable.CameraView_ckFlash, CameraKit.Defaults.DEFAULT_FLASH); |
|
|
@ -149,15 +135,21 @@ public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
setFocus(mFocus); |
|
|
|
setFocus(mFocus); |
|
|
|
setMethod(mMethod); |
|
|
|
setMethod(mMethod); |
|
|
|
setZoom(mZoom); |
|
|
|
setZoom(mZoom); |
|
|
|
setPermissions(mPermissions); |
|
|
|
setPermissionPolicy(mPermissions); |
|
|
|
setVideoQuality(mVideoQuality); |
|
|
|
setVideoQuality(mVideoQuality); |
|
|
|
|
|
|
|
|
|
|
|
if (!isInEditMode()) { |
|
|
|
if (!isInEditMode()) { |
|
|
|
mDisplayOrientationDetector = new DisplayOrientationDetector(context) { |
|
|
|
mOrientationHelper = new OrientationHelper(context) { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void onDisplayOrientationChanged(int displayOrientation) { |
|
|
|
public void onDisplayOffsetChanged(int displayOffset) { |
|
|
|
mCameraImpl.setDisplayOrientation(displayOrientation); |
|
|
|
mCameraImpl.onDisplayOffset(displayOffset); |
|
|
|
mPreviewImpl.setDisplayOrientation(displayOrientation); |
|
|
|
mPreviewImpl.onDisplayOffset(displayOffset); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
protected void onDeviceOrientationChanged(int deviceOrientation) { |
|
|
|
|
|
|
|
mCameraImpl.onDeviceOrientation(deviceOrientation); |
|
|
|
|
|
|
|
mPreviewImpl.onDeviceOrientation(deviceOrientation); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
@ -167,7 +159,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public boolean onTouch(View v, MotionEvent motionEvent) { |
|
|
|
public boolean onTouch(View v, MotionEvent motionEvent) { |
|
|
|
int action = motionEvent.getAction(); |
|
|
|
int action = motionEvent.getAction(); |
|
|
|
if (motionEvent.getAction() == MotionEvent.ACTION_UP && mFocus == CameraKit.Constants.FOCUS_TAP_WITH_MARKER) { |
|
|
|
if (action == MotionEvent.ACTION_UP && mFocus == CameraKit.Constants.FOCUS_TAP_WITH_MARKER) { |
|
|
|
focusMarkerLayout.focus(motionEvent.getX(), motionEvent.getY()); |
|
|
|
focusMarkerLayout.focus(motionEvent.getX(), motionEvent.getY()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -182,55 +174,69 @@ public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected void onAttachedToWindow() { |
|
|
|
protected void onAttachedToWindow() { |
|
|
|
super.onAttachedToWindow(); |
|
|
|
super.onAttachedToWindow(); |
|
|
|
|
|
|
|
Log.e(TAG, "onAttachedToWindow"); |
|
|
|
if (!isInEditMode()) { |
|
|
|
if (!isInEditMode()) { |
|
|
|
mDisplayOrientationDetector.enable( |
|
|
|
Log.e(TAG, "onAttachedToWindow: enabling orientation detector."); |
|
|
|
ViewCompat.isAttachedToWindow(this) |
|
|
|
WindowManager manager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); |
|
|
|
? DisplayManagerCompat.getInstance(getContext()) |
|
|
|
Display display = manager.getDefaultDisplay(); |
|
|
|
.getDisplay(Display.DEFAULT_DISPLAY) |
|
|
|
mOrientationHelper.enable(display); |
|
|
|
: null |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected void onDetachedFromWindow() { |
|
|
|
protected void onDetachedFromWindow() { |
|
|
|
|
|
|
|
Log.e(TAG, "onDetachedFromWindow"); |
|
|
|
if (!isInEditMode()) { |
|
|
|
if (!isInEditMode()) { |
|
|
|
mDisplayOrientationDetector.disable(); |
|
|
|
Log.e(TAG, "onDetachedFromWindow: disabling orientation detector."); |
|
|
|
|
|
|
|
mOrientationHelper.disable(); |
|
|
|
} |
|
|
|
} |
|
|
|
super.onDetachedFromWindow(); |
|
|
|
super.onDetachedFromWindow(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* If {@link CameraView#mAdjustViewBounds} was set AND one of the dimensions is set to WRAP_CONTENT, |
|
|
|
|
|
|
|
* CameraView will adjust that dimensions to fit the preview aspect ratio as returned by |
|
|
|
|
|
|
|
* {@link #getPreviewSize()}. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* If this is not true, the surface will adapt to the dimension specified in the layout file. |
|
|
|
|
|
|
|
* Having fixed dimensions means that, very likely, what the user sees is different from what |
|
|
|
|
|
|
|
* the final picture will be. This is also due to what happens in {@link PreviewImpl#refreshScale()}. |
|
|
|
|
|
|
|
*/ |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { |
|
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { |
|
|
|
if (mAdjustViewBounds) { |
|
|
|
if (!mAdjustViewBounds) { |
|
|
|
Size previewSize = getPreviewSize(); |
|
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec); |
|
|
|
if (previewSize != null) { |
|
|
|
return; |
|
|
|
if (getLayoutParams().width == LayoutParams.WRAP_CONTENT) { |
|
|
|
} |
|
|
|
int height = MeasureSpec.getSize(heightMeasureSpec); |
|
|
|
|
|
|
|
float ratio = (float) height / (float) previewSize.getWidth(); |
|
|
|
Size previewSize = getPreviewSize(); |
|
|
|
int width = (int) (previewSize.getHeight() * ratio); |
|
|
|
if (previewSize == null) { |
|
|
|
super.onMeasure( |
|
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec); |
|
|
|
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), |
|
|
|
return; |
|
|
|
heightMeasureSpec |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} else if (getLayoutParams().height == LayoutParams.WRAP_CONTENT) { |
|
|
|
|
|
|
|
int width = MeasureSpec.getSize(widthMeasureSpec); |
|
|
|
|
|
|
|
float ratio = (float) width / (float) previewSize.getHeight(); |
|
|
|
|
|
|
|
int height = (int) (previewSize.getWidth() * ratio); |
|
|
|
|
|
|
|
super.onMeasure( |
|
|
|
|
|
|
|
widthMeasureSpec, |
|
|
|
|
|
|
|
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY) |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec); |
|
|
|
if (getLayoutParams().width == LayoutParams.WRAP_CONTENT) { |
|
|
|
|
|
|
|
int height = MeasureSpec.getSize(heightMeasureSpec); |
|
|
|
|
|
|
|
float ratio = (float) height / (float) previewSize.getWidth(); |
|
|
|
|
|
|
|
int width = (int) (previewSize.getHeight() * ratio); |
|
|
|
|
|
|
|
super.onMeasure( |
|
|
|
|
|
|
|
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), |
|
|
|
|
|
|
|
heightMeasureSpec |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else if (getLayoutParams().height == LayoutParams.WRAP_CONTENT) { |
|
|
|
|
|
|
|
int width = MeasureSpec.getSize(widthMeasureSpec); |
|
|
|
|
|
|
|
float ratio = (float) width / (float) previewSize.getHeight(); |
|
|
|
|
|
|
|
int height = (int) (previewSize.getWidth() * ratio); |
|
|
|
|
|
|
|
super.onMeasure( |
|
|
|
|
|
|
|
widthMeasureSpec, |
|
|
|
|
|
|
|
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY) |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public boolean isStarted() { |
|
|
|
public boolean isStarted() { |
|
|
@ -263,30 +269,29 @@ public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
stop(); |
|
|
|
stop(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) |
|
|
|
|
|
|
|
public void onDestroy(LifecycleOwner owner) { |
|
|
|
|
|
|
|
mLifecycle = owner.getLifecycle(); |
|
|
|
|
|
|
|
// This might be useless, but no time to think about it now.
|
|
|
|
|
|
|
|
sWorkerHandler = null; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void start() { |
|
|
|
public void start() { |
|
|
|
if (mIsStarted || !isEnabled()) { |
|
|
|
if (mIsStarted || !isEnabled()) { |
|
|
|
// Already started, do nothing.
|
|
|
|
// Already started, do nothing.
|
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
mIsStarted = true; |
|
|
|
checkPermissionPolicyOrThrow(); |
|
|
|
int cameraCheck = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA); |
|
|
|
int cameraCheck = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA); |
|
|
|
int audioCheck = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.RECORD_AUDIO); |
|
|
|
int audioCheck = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.RECORD_AUDIO); |
|
|
|
|
|
|
|
|
|
|
|
switch (mPermissions) { |
|
|
|
switch (mPermissions) { |
|
|
|
case PERMISSIONS_STRICT: |
|
|
|
case PERMISSIONS_VIDEO: |
|
|
|
if (cameraCheck != PackageManager.PERMISSION_GRANTED || audioCheck != PackageManager.PERMISSION_GRANTED) { |
|
|
|
if (cameraCheck != PackageManager.PERMISSION_GRANTED || audioCheck != PackageManager.PERMISSION_GRANTED) { |
|
|
|
requestPermissions(true, true); |
|
|
|
requestPermissions(true, true); |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case PERMISSIONS_LAZY: |
|
|
|
|
|
|
|
if (cameraCheck != PackageManager.PERMISSION_GRANTED) { |
|
|
|
|
|
|
|
requestPermissions(true, true); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case PERMISSIONS_PICTURE: |
|
|
|
case PERMISSIONS_PICTURE: |
|
|
|
if (cameraCheck != PackageManager.PERMISSION_GRANTED) { |
|
|
|
if (cameraCheck != PackageManager.PERMISSION_GRANTED) { |
|
|
|
requestPermissions(true, false); |
|
|
|
requestPermissions(true, false); |
|
|
@ -295,7 +300,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
sWorkerHandler.post(new Runnable() { |
|
|
|
mIsStarted = true; |
|
|
|
|
|
|
|
run(new Runnable() { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void run() { |
|
|
|
public void run() { |
|
|
|
mCameraImpl.start(); |
|
|
|
mCameraImpl.start(); |
|
|
@ -325,7 +331,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
public void setFacing(@Facing final int facing) { |
|
|
|
public void setFacing(@Facing final int facing) { |
|
|
|
this.mFacing = facing; |
|
|
|
this.mFacing = facing; |
|
|
|
|
|
|
|
|
|
|
|
sWorkerHandler.post(new Runnable() { |
|
|
|
run(new Runnable() { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void run() { |
|
|
|
public void run() { |
|
|
|
mCameraImpl.setFacing(facing); |
|
|
|
mCameraImpl.setFacing(facing); |
|
|
@ -363,8 +369,13 @@ public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
mCameraImpl.setZoom(mZoom); |
|
|
|
mCameraImpl.setZoom(mZoom); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setPermissions(@Permissions int permissions) { |
|
|
|
/** |
|
|
|
|
|
|
|
* Sets permission policy. |
|
|
|
|
|
|
|
* @param permissions desired policy, either picture or video. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
public void setPermissionPolicy(@Permissions int permissions) { |
|
|
|
this.mPermissions = permissions; |
|
|
|
this.mPermissions = permissions; |
|
|
|
|
|
|
|
checkPermissionPolicyOrThrow(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void setVideoQuality(@VideoQuality int videoQuality) { |
|
|
|
public void setVideoQuality(@VideoQuality int videoQuality) { |
|
|
@ -431,12 +442,18 @@ public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
mCameraImpl.endVideo(); |
|
|
|
mCameraImpl.endVideo(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Returns the size used for the preview, |
|
|
|
|
|
|
|
* or null if it hasn't been computed (for example if the surface is not ready). |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
@Nullable |
|
|
|
public Size getPreviewSize() { |
|
|
|
public Size getPreviewSize() { |
|
|
|
return mCameraImpl != null ? mCameraImpl.getPreviewResolution() : null; |
|
|
|
return mCameraImpl != null ? mCameraImpl.getPreviewSize() : null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Nullable |
|
|
|
public Size getCaptureSize() { |
|
|
|
public Size getCaptureSize() { |
|
|
|
return mCameraImpl != null ? mCameraImpl.getCaptureResolution() : null; |
|
|
|
return mCameraImpl != null ? mCameraImpl.getCaptureSize() : null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void requestPermissions(boolean requestCamera, boolean requestAudio) { |
|
|
|
private void requestPermissions(boolean requestCamera, boolean requestAudio) { |
|
|
@ -452,12 +469,10 @@ public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
List<String> permissions = new ArrayList<>(); |
|
|
|
List<String> permissions = new ArrayList<>(); |
|
|
|
if (requestCamera) permissions.add(Manifest.permission.CAMERA); |
|
|
|
if (requestCamera) permissions.add(Manifest.permission.CAMERA); |
|
|
|
if (requestAudio) permissions.add(Manifest.permission.RECORD_AUDIO); |
|
|
|
if (requestAudio) permissions.add(Manifest.permission.RECORD_AUDIO); |
|
|
|
|
|
|
|
|
|
|
|
if (activity != null) { |
|
|
|
if (activity != null) { |
|
|
|
ActivityCompat.requestPermissions( |
|
|
|
ActivityCompat.requestPermissions(activity, |
|
|
|
activity, |
|
|
|
|
|
|
|
permissions.toArray(new String[permissions.size()]), |
|
|
|
permissions.toArray(new String[permissions.size()]), |
|
|
|
CameraKit.Constants.PERMISSION_REQUEST_CAMERA); |
|
|
|
CameraKit.Constants.PERMISSION_REQUEST_CODE); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -481,8 +496,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
public void onPictureTaken(byte[] jpeg) { |
|
|
|
public void onPictureTaken(byte[] jpeg) { |
|
|
|
super.onPictureTaken(jpeg); |
|
|
|
super.onPictureTaken(jpeg); |
|
|
|
if (mCropOutput) { |
|
|
|
if (mCropOutput) { |
|
|
|
int width = mMethod == METHOD_STANDARD ? mCameraImpl.getCaptureResolution().getWidth() : mCameraImpl.getPreviewResolution().getWidth(); |
|
|
|
int width = mMethod == METHOD_STANDARD ? mCameraImpl.getCaptureSize().getWidth() : mCameraImpl.getPreviewSize().getWidth(); |
|
|
|
int height = mMethod == METHOD_STANDARD ? mCameraImpl.getCaptureResolution().getHeight() : mCameraImpl.getPreviewResolution().getHeight(); |
|
|
|
int height = mMethod == METHOD_STANDARD ? mCameraImpl.getCaptureSize().getHeight() : mCameraImpl.getPreviewSize().getHeight(); |
|
|
|
AspectRatio outputRatio = AspectRatio.of(getWidth(), getHeight()); |
|
|
|
AspectRatio outputRatio = AspectRatio.of(getWidth(), getHeight()); |
|
|
|
getCameraListener().onPictureTaken(new CenterCrop(jpeg, outputRatio, mJpegQuality).getJpeg()); |
|
|
|
getCameraListener().onPictureTaken(new CenterCrop(jpeg, outputRatio, mJpegQuality).getJpeg()); |
|
|
|
} else { |
|
|
|
} else { |
|
|
@ -521,4 +536,29 @@ public class CameraView extends FrameLayout implements LifecycleObserver { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* If mPermissions == PERMISSIONS_VIDEO we will ask for RECORD_AUDIO permission. |
|
|
|
|
|
|
|
* If the developer did not add this to its manifest, throw and fire warnings. |
|
|
|
|
|
|
|
* (Hoping this is not cought elsewhere... we should test). |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
private void checkPermissionPolicyOrThrow() { |
|
|
|
|
|
|
|
if (mPermissions == PERMISSIONS_VIDEO) { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
PackageManager manager = getContext().getPackageManager(); |
|
|
|
|
|
|
|
PackageInfo info = manager.getPackageInfo(getContext().getPackageName(), PackageManager.GET_PERMISSIONS); |
|
|
|
|
|
|
|
for (String requestedPermission : info.requestedPermissions) { |
|
|
|
|
|
|
|
if (requestedPermission.equals(Manifest.permission.RECORD_AUDIO)) { |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
String message = "When the permission policy is PERMISSION_VIDEO, the RECORD_AUDIO permission " + |
|
|
|
|
|
|
|
"should be added to the application manifest file."; |
|
|
|
|
|
|
|
Log.w(TAG, message); |
|
|
|
|
|
|
|
throw new IllegalStateException(message); |
|
|
|
|
|
|
|
} catch (PackageManager.NameNotFoundException e) { |
|
|
|
|
|
|
|
// Not possible.
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|