add some initial PreviewCameraTwo implementation from the sample code
This commit is contained in:
parent
77fb00097c
commit
26f33e8c26
|
@ -84,6 +84,7 @@ class MainActivity : SimpleActivity(), PreviewListener, PhotoProcessor.MediaSave
|
||||||
if (hasStorageAndCameraPermissions()) {
|
if (hasStorageAndCameraPermissions()) {
|
||||||
mOrientationEventListener.enable()
|
mOrientationEventListener.enable()
|
||||||
}
|
}
|
||||||
|
mPreview?.onResumed()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
|
@ -102,6 +103,7 @@ class MainActivity : SimpleActivity(), PreviewListener, PhotoProcessor.MediaSave
|
||||||
if (mPreview?.getCameraState() == STATE_PICTURE_TAKEN) {
|
if (mPreview?.getCameraState() == STATE_PICTURE_TAKEN) {
|
||||||
toast(R.string.photo_not_saved)
|
toast(R.string.photo_not_saved)
|
||||||
}
|
}
|
||||||
|
mPreview?.onPaused()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
|
@ -194,7 +196,7 @@ class MainActivity : SimpleActivity(), PreviewListener, PhotoProcessor.MediaSave
|
||||||
|
|
||||||
(btn_holder.layoutParams as RelativeLayout.LayoutParams).setMargins(0, 0, 0, (navBarHeight + resources.getDimension(R.dimen.activity_margin)).toInt())
|
(btn_holder.layoutParams as RelativeLayout.LayoutParams).setMargins(0, 0, 0, (navBarHeight + resources.getDimension(R.dimen.activity_margin)).toInt())
|
||||||
|
|
||||||
mPreview = if (isLollipopPlus()) PreviewCameraTwo(this) else PreviewCameraOne(this, camera_surface_view, this)
|
mPreview = if (isLollipopPlus()) PreviewCameraTwo(this, camera_texture_view) else PreviewCameraOne(this, camera_surface_view, this)
|
||||||
view_holder.addView(mPreview as ViewGroup)
|
view_holder.addView(mPreview as ViewGroup)
|
||||||
|
|
||||||
val imageDrawable = if (config.lastUsedCamera == mCameraImpl.getBackCameraId()) R.drawable.ic_camera_front else R.drawable.ic_camera_rear
|
val imageDrawable = if (config.lastUsedCamera == mCameraImpl.getBackCameraId()) R.drawable.ic_camera_front else R.drawable.ic_camera_rear
|
||||||
|
|
|
@ -31,3 +31,6 @@ const val FLASH_AUTO = 2
|
||||||
// camera states
|
// camera states
|
||||||
const val STATE_PREVIEW = 0
|
const val STATE_PREVIEW = 0
|
||||||
const val STATE_PICTURE_TAKEN = 1
|
const val STATE_PICTURE_TAKEN = 1
|
||||||
|
const val STATE_WAITING_LOCK = 2
|
||||||
|
const val STATE_WAITING_PRECAPTURE = 3
|
||||||
|
const val STATE_WAITING_NON_PRECAPTURE = 4
|
||||||
|
|
|
@ -3,6 +3,10 @@ package com.simplemobiletools.camera.interfaces
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
|
||||||
interface MyPreview {
|
interface MyPreview {
|
||||||
|
fun onResumed()
|
||||||
|
|
||||||
|
fun onPaused()
|
||||||
|
|
||||||
fun setTargetUri(uri: Uri)
|
fun setTargetUri(uri: Uri)
|
||||||
|
|
||||||
fun setIsImageCaptureIntent(isImageCaptureIntent: Boolean)
|
fun setIsImageCaptureIntent(isImageCaptureIntent: Boolean)
|
||||||
|
|
|
@ -113,6 +113,10 @@ class PreviewCameraOne : ViewGroup, SurfaceHolder.Callback, MyPreview {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResumed() {}
|
||||||
|
|
||||||
|
override fun onPaused() {}
|
||||||
|
|
||||||
override fun tryInitVideoMode() {
|
override fun tryInitVideoMode() {
|
||||||
if (mIsSurfaceCreated) {
|
if (mIsSurfaceCreated) {
|
||||||
initVideoMode()
|
initVideoMode()
|
||||||
|
|
|
@ -1,14 +1,404 @@
|
||||||
package com.simplemobiletools.camera.views
|
package com.simplemobiletools.camera.views
|
||||||
|
|
||||||
|
import android.annotation.TargetApi
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import android.graphics.*
|
||||||
|
import android.hardware.camera2.*
|
||||||
|
import android.media.ImageReader
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.HandlerThread
|
||||||
|
import android.util.Size
|
||||||
|
import android.util.SparseIntArray
|
||||||
|
import android.view.Surface
|
||||||
|
import android.view.TextureView
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import com.simplemobiletools.camera.helpers.STATE_PREVIEW
|
import com.simplemobiletools.camera.activities.MainActivity
|
||||||
|
import com.simplemobiletools.camera.helpers.*
|
||||||
import com.simplemobiletools.camera.interfaces.MyPreview
|
import com.simplemobiletools.camera.interfaces.MyPreview
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.Semaphore
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class PreviewCameraTwo(context: Context) : ViewGroup(context), MyPreview {
|
// based on the Android Camera2 sample at https://github.com/googlesamples/android-Camera2Basic
|
||||||
private var mTargetUri: Uri? = null
|
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||||
|
class PreviewCameraTwo : ViewGroup, TextureView.SurfaceTextureListener, MyPreview {
|
||||||
|
private val MAX_PREVIEW_WIDTH = 1920
|
||||||
|
private val MAX_PREVIEW_HEIGHT = 1080
|
||||||
|
|
||||||
|
private val ORIENTATIONS = SparseIntArray().apply {
|
||||||
|
append(Surface.ROTATION_0, 90)
|
||||||
|
append(Surface.ROTATION_90, 0)
|
||||||
|
append(Surface.ROTATION_180, 270)
|
||||||
|
append(Surface.ROTATION_270, 180)
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var mActivity: MainActivity
|
||||||
|
private lateinit var mTextureView: AutoFitTextureView
|
||||||
|
|
||||||
|
private var mSensorOrientation = 0
|
||||||
|
private var mIsFlashSupported = true
|
||||||
private var mIsImageCaptureIntent = false
|
private var mIsImageCaptureIntent = false
|
||||||
|
private var mCameraId = ""
|
||||||
|
private var mCameraState = STATE_PREVIEW
|
||||||
|
|
||||||
|
private var mBackgroundThread: HandlerThread? = null
|
||||||
|
private var mBackgroundHandler: Handler? = null
|
||||||
|
private var mImageReader: ImageReader? = null
|
||||||
|
private var mPreviewSize: Size? = null
|
||||||
|
private var mTargetUri: Uri? = null
|
||||||
|
private var mCameraDevice: CameraDevice? = null
|
||||||
|
private var mCaptureSession: CameraCaptureSession? = null
|
||||||
|
private var mPreviewRequestBuilder: CaptureRequest.Builder? = null
|
||||||
|
private var mPreviewRequest: CaptureRequest? = null
|
||||||
|
private val mCameraOpenCloseLock = Semaphore(1)
|
||||||
|
|
||||||
|
constructor(context: Context) : super(context)
|
||||||
|
|
||||||
|
constructor(activity: MainActivity, textureView: AutoFitTextureView) : super(activity) {
|
||||||
|
mActivity = activity
|
||||||
|
mTextureView = textureView
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResumed() {
|
||||||
|
startBackgroundThread()
|
||||||
|
|
||||||
|
if (mTextureView.isAvailable) {
|
||||||
|
openCamera(mTextureView.width, mTextureView.height)
|
||||||
|
} else {
|
||||||
|
mTextureView.surfaceTextureListener = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPaused() {
|
||||||
|
stopBackgroundThread()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) {
|
||||||
|
configureTransform(width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSurfaceTextureUpdated(surface: SurfaceTexture?) {}
|
||||||
|
|
||||||
|
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture) = true
|
||||||
|
|
||||||
|
override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
|
||||||
|
openCamera(width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startBackgroundThread() {
|
||||||
|
mBackgroundThread = HandlerThread("SimpleCameraBackground")
|
||||||
|
mBackgroundThread!!.start()
|
||||||
|
mBackgroundHandler = Handler(mBackgroundThread!!.looper)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopBackgroundThread() {
|
||||||
|
mBackgroundThread?.quitSafely()
|
||||||
|
try {
|
||||||
|
mBackgroundThread?.join()
|
||||||
|
mBackgroundThread = null
|
||||||
|
mBackgroundHandler = null
|
||||||
|
} catch (e: InterruptedException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun openCamera(width: Int, height: Int) {
|
||||||
|
setUpCameraOutputs(width, height)
|
||||||
|
configureTransform(width, height)
|
||||||
|
val manager = mActivity.getSystemService(Context.CAMERA_SERVICE) as CameraManager
|
||||||
|
try {
|
||||||
|
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
|
||||||
|
throw RuntimeException("Time out waiting to lock camera opening.")
|
||||||
|
}
|
||||||
|
manager.openCamera(mCameraId, cameraStateCallback, mBackgroundHandler)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val imageAvailableListener = ImageReader.OnImageAvailableListener { reader -> val image = reader.acquireNextImage() }
|
||||||
|
|
||||||
|
private fun setUpCameraOutputs(width: Int, height: Int) {
|
||||||
|
val manager = mActivity.getSystemService(Context.CAMERA_SERVICE) as CameraManager
|
||||||
|
try {
|
||||||
|
for (cameraId in manager.cameraIdList) {
|
||||||
|
val characteristics = manager.getCameraCharacteristics(cameraId)
|
||||||
|
|
||||||
|
val map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP) ?: continue
|
||||||
|
val largest = map.getOutputSizes(ImageFormat.JPEG).maxBy { it.width * it.height }
|
||||||
|
|
||||||
|
mImageReader = ImageReader.newInstance(largest!!.width, largest.height, ImageFormat.JPEG, 2)
|
||||||
|
mImageReader!!.setOnImageAvailableListener(imageAvailableListener, mBackgroundHandler)
|
||||||
|
|
||||||
|
val displayRotation = mActivity.windowManager.defaultDisplay.rotation
|
||||||
|
|
||||||
|
mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)!!
|
||||||
|
var swappedDimensions = false
|
||||||
|
when (displayRotation) {
|
||||||
|
Surface.ROTATION_0, Surface.ROTATION_180 -> if (mSensorOrientation == 90 || mSensorOrientation == 270) {
|
||||||
|
swappedDimensions = true
|
||||||
|
}
|
||||||
|
Surface.ROTATION_90, Surface.ROTATION_270 -> if (mSensorOrientation == 0 || mSensorOrientation == 180) {
|
||||||
|
swappedDimensions = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val displaySize = Point()
|
||||||
|
mActivity.windowManager.defaultDisplay.getSize(displaySize)
|
||||||
|
var rotatedPreviewWidth = width
|
||||||
|
var rotatedPreviewHeight = height
|
||||||
|
var maxPreviewWidth = displaySize.x
|
||||||
|
var maxPreviewHeight = displaySize.y
|
||||||
|
|
||||||
|
if (swappedDimensions) {
|
||||||
|
rotatedPreviewWidth = height
|
||||||
|
rotatedPreviewHeight = width
|
||||||
|
maxPreviewWidth = displaySize.y
|
||||||
|
maxPreviewHeight = displaySize.x
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxPreviewWidth > MAX_PREVIEW_WIDTH) {
|
||||||
|
maxPreviewWidth = MAX_PREVIEW_WIDTH
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) {
|
||||||
|
maxPreviewHeight = MAX_PREVIEW_HEIGHT
|
||||||
|
}
|
||||||
|
|
||||||
|
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture::class.java),
|
||||||
|
rotatedPreviewWidth, rotatedPreviewHeight, maxPreviewWidth,
|
||||||
|
maxPreviewHeight, largest)
|
||||||
|
|
||||||
|
val orientation = resources.configuration.orientation
|
||||||
|
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||||
|
mTextureView.setAspectRatio(mPreviewSize!!.width, mPreviewSize!!.height)
|
||||||
|
} else {
|
||||||
|
mTextureView.setAspectRatio(mPreviewSize!!.height, mPreviewSize!!.width)
|
||||||
|
}
|
||||||
|
|
||||||
|
val available = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE)
|
||||||
|
mIsFlashSupported = available ?: false
|
||||||
|
mCameraId = cameraId
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun chooseOptimalSize(choices: Array<Size>, textureViewWidth: Int, textureViewHeight: Int, maxWidth: Int, maxHeight: Int, aspectRatio: Size): Size {
|
||||||
|
val bigEnough = ArrayList<Size>()
|
||||||
|
val notBigEnough = ArrayList<Size>()
|
||||||
|
val width = aspectRatio.width
|
||||||
|
val height = aspectRatio.height
|
||||||
|
for (option in choices) {
|
||||||
|
if (option.width <= maxWidth && option.height <= maxHeight && option.height == option.width * height / width) {
|
||||||
|
if (option.width >= textureViewWidth && option.height >= textureViewHeight) {
|
||||||
|
bigEnough.add(option)
|
||||||
|
} else {
|
||||||
|
notBigEnough.add(option)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return when {
|
||||||
|
bigEnough.size > 0 -> bigEnough.minBy { it.width * it.height }!!
|
||||||
|
notBigEnough.size > 0 -> notBigEnough.maxBy { it.width * it.height }!!
|
||||||
|
else -> choices[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun configureTransform(viewWidth: Int, viewHeight: Int) {
|
||||||
|
if (mPreviewSize == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val rotation = mActivity.windowManager.defaultDisplay.rotation
|
||||||
|
val matrix = Matrix()
|
||||||
|
val viewRect = RectF(0f, 0f, viewWidth.toFloat(), viewHeight.toFloat())
|
||||||
|
val bufferRect = RectF(0f, 0f, mPreviewSize!!.height.toFloat(), mPreviewSize!!.width.toFloat())
|
||||||
|
val centerX = viewRect.centerX()
|
||||||
|
val centerY = viewRect.centerY()
|
||||||
|
|
||||||
|
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
|
||||||
|
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY())
|
||||||
|
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL)
|
||||||
|
val scale = Math.max(viewHeight.toFloat() / mPreviewSize!!.height, viewWidth.toFloat() / mPreviewSize!!.width)
|
||||||
|
matrix.postScale(scale, scale, centerX, centerY)
|
||||||
|
matrix.postRotate((90 * (rotation - 2)).toFloat(), centerX, centerY)
|
||||||
|
} else if (Surface.ROTATION_180 == rotation) {
|
||||||
|
matrix.postRotate(180f, centerX, centerY)
|
||||||
|
}
|
||||||
|
|
||||||
|
mTextureView.setTransform(matrix)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var cameraStateCallback = object : CameraDevice.StateCallback() {
|
||||||
|
override fun onOpened(cameraDevice: CameraDevice) {
|
||||||
|
mCameraOpenCloseLock.release()
|
||||||
|
mCameraDevice = cameraDevice
|
||||||
|
createCameraPreviewSession()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisconnected(cameraDevice: CameraDevice) {
|
||||||
|
mCameraOpenCloseLock.release()
|
||||||
|
cameraDevice.close()
|
||||||
|
mCameraDevice = null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(cameraDevice: CameraDevice, error: Int) {
|
||||||
|
mCameraOpenCloseLock.release()
|
||||||
|
cameraDevice.close()
|
||||||
|
mCameraDevice = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createCameraPreviewSession() {
|
||||||
|
try {
|
||||||
|
val texture = mTextureView.surfaceTexture!!
|
||||||
|
texture.setDefaultBufferSize(mPreviewSize!!.width, mPreviewSize!!.height)
|
||||||
|
|
||||||
|
val surface = Surface(texture)
|
||||||
|
mPreviewRequestBuilder = mCameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)
|
||||||
|
mPreviewRequestBuilder!!.addTarget(surface)
|
||||||
|
|
||||||
|
mCameraDevice!!.createCaptureSession(Arrays.asList(surface, mImageReader!!.surface),
|
||||||
|
object : CameraCaptureSession.StateCallback() {
|
||||||
|
override fun onConfigured(cameraCaptureSession: CameraCaptureSession) {
|
||||||
|
if (mCameraDevice == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mCaptureSession = cameraCaptureSession
|
||||||
|
try {
|
||||||
|
mPreviewRequestBuilder!!.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
|
||||||
|
setAutoFlash(mPreviewRequestBuilder!!)
|
||||||
|
mPreviewRequest = mPreviewRequestBuilder!!.build()
|
||||||
|
mCaptureSession!!.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mBackgroundHandler)
|
||||||
|
} catch (e: CameraAccessException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onConfigureFailed(cameraCaptureSession: CameraCaptureSession) {
|
||||||
|
}
|
||||||
|
}, null
|
||||||
|
)
|
||||||
|
} catch (e: CameraAccessException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setAutoFlash(requestBuilder: CaptureRequest.Builder) {
|
||||||
|
if (mIsFlashSupported) {
|
||||||
|
requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val mCaptureCallback = object : CameraCaptureSession.CaptureCallback() {
|
||||||
|
private fun process(result: CaptureResult) {
|
||||||
|
when (mCameraState) {
|
||||||
|
STATE_WAITING_LOCK -> {
|
||||||
|
val afState = result.get(CaptureResult.CONTROL_AF_STATE)
|
||||||
|
if (afState == null) {
|
||||||
|
captureStillPicture()
|
||||||
|
} else if (afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED || afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) {
|
||||||
|
val aeState = result.get(CaptureResult.CONTROL_AE_STATE)
|
||||||
|
if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
|
||||||
|
mCameraState = STATE_PICTURE_TAKEN
|
||||||
|
captureStillPicture()
|
||||||
|
} else {
|
||||||
|
runPrecaptureSequence()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
STATE_WAITING_PRECAPTURE -> {
|
||||||
|
val aeState = result.get(CaptureResult.CONTROL_AE_STATE)
|
||||||
|
if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE || aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
|
||||||
|
mCameraState = STATE_WAITING_NON_PRECAPTURE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
STATE_WAITING_NON_PRECAPTURE -> {
|
||||||
|
val aeState = result.get(CaptureResult.CONTROL_AE_STATE)
|
||||||
|
if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
|
||||||
|
mCameraState = STATE_PICTURE_TAKEN
|
||||||
|
captureStillPicture()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCaptureProgressed(session: CameraCaptureSession, request: CaptureRequest, partialResult: CaptureResult) {
|
||||||
|
process(partialResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCaptureCompleted(session: CameraCaptureSession, request: CaptureRequest, result: TotalCaptureResult) {
|
||||||
|
process(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun runPrecaptureSequence() {
|
||||||
|
try {
|
||||||
|
mPreviewRequestBuilder!!.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START)
|
||||||
|
mCameraState = STATE_WAITING_PRECAPTURE
|
||||||
|
mCaptureSession!!.capture(mPreviewRequestBuilder!!.build(), mCaptureCallback, mBackgroundHandler)
|
||||||
|
} catch (e: CameraAccessException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun captureStillPicture() {
|
||||||
|
try {
|
||||||
|
if (mCameraDevice == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val captureBuilder = mCameraDevice!!.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
|
||||||
|
captureBuilder.addTarget(mImageReader!!.surface)
|
||||||
|
|
||||||
|
captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)
|
||||||
|
setAutoFlash(captureBuilder)
|
||||||
|
|
||||||
|
val rotation = mActivity.windowManager.defaultDisplay.rotation
|
||||||
|
captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation))
|
||||||
|
|
||||||
|
val CaptureCallback = object : CameraCaptureSession.CaptureCallback() {
|
||||||
|
override fun onCaptureCompleted(session: CameraCaptureSession, request: CaptureRequest, result: TotalCaptureResult) {
|
||||||
|
unlockFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mCaptureSession!!.apply {
|
||||||
|
stopRepeating()
|
||||||
|
abortCaptures()
|
||||||
|
capture(captureBuilder.build(), CaptureCallback, null)
|
||||||
|
}
|
||||||
|
} catch (e: CameraAccessException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getOrientation(rotation: Int) = (ORIENTATIONS.get(rotation) + mSensorOrientation + 270) % 360
|
||||||
|
|
||||||
|
private fun unlockFocus() {
|
||||||
|
try {
|
||||||
|
mPreviewRequestBuilder!!.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL)
|
||||||
|
setAutoFlash(mPreviewRequestBuilder!!)
|
||||||
|
mCaptureSession!!.capture(mPreviewRequestBuilder!!.build(), mCaptureCallback, mBackgroundHandler)
|
||||||
|
mCameraState = STATE_PREVIEW
|
||||||
|
mCaptureSession!!.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mBackgroundHandler)
|
||||||
|
} catch (e: CameraAccessException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun lockFocus() {
|
||||||
|
try {
|
||||||
|
mPreviewRequestBuilder!!.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START)
|
||||||
|
mCameraState = STATE_WAITING_LOCK
|
||||||
|
mCaptureSession!!.capture(mPreviewRequestBuilder!!.build(), mCaptureCallback, mBackgroundHandler)
|
||||||
|
} catch (e: CameraAccessException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun takePicture() {
|
||||||
|
lockFocus()
|
||||||
|
}
|
||||||
|
|
||||||
override fun setTargetUri(uri: Uri) {
|
override fun setTargetUri(uri: Uri) {
|
||||||
mTargetUri = uri
|
mTargetUri = uri
|
||||||
|
@ -42,6 +432,7 @@ class PreviewCameraTwo(context: Context) : ViewGroup(context), MyPreview {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tryTakePicture() {
|
override fun tryTakePicture() {
|
||||||
|
takePicture()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toggleRecording(): Boolean {
|
override fun toggleRecording(): Boolean {
|
||||||
|
|
Loading…
Reference in New Issue