Merge pull request #370 from KryptKode/fix/fast-switch-mode-inconsistencies
fix inconsistencies when user switches camera mode fast
This commit is contained in:
commit
6e794d4cf7
|
@ -69,7 +69,7 @@ dependencies {
|
||||||
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"
|
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.5.1"
|
||||||
implementation 'androidx.window:window:1.1.0-alpha03'
|
implementation 'androidx.window:window:1.1.0-alpha03'
|
||||||
|
|
||||||
def camerax_version = '1.2.0-rc01'
|
def camerax_version = '1.2.0-beta01'
|
||||||
implementation "androidx.camera:camera-core:$camerax_version"
|
implementation "androidx.camera:camera-core:$camerax_version"
|
||||||
implementation "androidx.camera:camera-camera2:$camerax_version"
|
implementation "androidx.camera:camera-camera2:$camerax_version"
|
||||||
implementation "androidx.camera:camera-video:$camerax_version"
|
implementation "androidx.camera:camera-video:$camerax_version"
|
||||||
|
|
|
@ -6,11 +6,8 @@ import android.content.Intent
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.hardware.SensorManager
|
import android.hardware.SensorManager
|
||||||
import android.hardware.camera2.CameraCharacteristics
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.provider.MediaStore
|
import android.provider.MediaStore
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
|
@ -40,11 +37,11 @@ import com.simplemobiletools.camera.views.FocusCircleView
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.commons.helpers.*
|
import com.simplemobiletools.commons.helpers.*
|
||||||
import com.simplemobiletools.commons.models.Release
|
import com.simplemobiletools.commons.models.Release
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import kotlin.math.abs
|
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import kotlinx.android.synthetic.main.layout_flash.*
|
import kotlinx.android.synthetic.main.layout_flash.*
|
||||||
import kotlinx.android.synthetic.main.layout_top.*
|
import kotlinx.android.synthetic.main.layout_top.*
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import kotlin.math.abs
|
||||||
|
|
||||||
class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, CameraXPreviewListener {
|
class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, CameraXPreviewListener {
|
||||||
private companion object {
|
private companion object {
|
||||||
|
@ -54,7 +51,6 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
private const val MIN_SWIPE_DISTANCE_X = 100
|
private const val MIN_SWIPE_DISTANCE_X = 100
|
||||||
}
|
}
|
||||||
|
|
||||||
lateinit var mTimerHandler: Handler
|
|
||||||
private lateinit var defaultScene: Scene
|
private lateinit var defaultScene: Scene
|
||||||
private lateinit var flashModeScene: Scene
|
private lateinit var flashModeScene: Scene
|
||||||
private lateinit var mOrientationEventListener: OrientationEventListener
|
private lateinit var mOrientationEventListener: OrientationEventListener
|
||||||
|
@ -62,15 +58,26 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
private var mPreview: MyPreview? = null
|
private var mPreview: MyPreview? = null
|
||||||
private var mediaSizeToggleGroup: MaterialButtonToggleGroup? = null
|
private var mediaSizeToggleGroup: MaterialButtonToggleGroup? = null
|
||||||
private var mPreviewUri: Uri? = null
|
private var mPreviewUri: Uri? = null
|
||||||
private var mIsInPhotoMode = true
|
|
||||||
private var mIsCameraAvailable = false
|
|
||||||
private var mIsHardwareShutterHandled = false
|
private var mIsHardwareShutterHandled = false
|
||||||
private var mCurrVideoRecTimer = 0
|
private var mLastHandledOrientation = 0
|
||||||
var mLastHandledOrientation = 0
|
|
||||||
|
|
||||||
private val tabSelectedListener = object : TabSelectedListener {
|
private val tabSelectedListener = object : TabSelectedListener {
|
||||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
override fun onTabSelected(tab: TabLayout.Tab) {
|
||||||
handleTogglePhotoVideo()
|
handlePermission(PERMISSION_RECORD_AUDIO) {
|
||||||
|
if (it) {
|
||||||
|
when (tab.position) {
|
||||||
|
VIDEO_MODE_INDEX -> mPreview?.initVideoMode()
|
||||||
|
PHOTO_MODE_INDEX -> mPreview?.initPhotoMode()
|
||||||
|
else -> throw IllegalStateException("Unsupported tab position ${tab.position}")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toast(R.string.no_audio_permissions)
|
||||||
|
selectPhotoTab()
|
||||||
|
if (isVideoCaptureIntent()) {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +86,6 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
appLaunched(BuildConfig.APPLICATION_ID)
|
appLaunched(BuildConfig.APPLICATION_ID)
|
||||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
|
|
||||||
initVariables()
|
initVariables()
|
||||||
tryInitCamera()
|
tryInitCamera()
|
||||||
supportActionBar?.hide()
|
supportActionBar?.hide()
|
||||||
|
@ -107,6 +113,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
if (!triggerListener) {
|
if (!triggerListener) {
|
||||||
removeTabListener()
|
removeTabListener()
|
||||||
}
|
}
|
||||||
|
|
||||||
camera_mode_tab.getTabAt(PHOTO_MODE_INDEX)?.select()
|
camera_mode_tab.getTabAt(PHOTO_MODE_INDEX)?.select()
|
||||||
setTabListener()
|
setTabListener()
|
||||||
}
|
}
|
||||||
|
@ -130,17 +137,13 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
if (hasStorageAndCameraPermissions()) {
|
if (hasStorageAndCameraPermissions()) {
|
||||||
resumeCameraItems()
|
val isInPhotoMode = isInPhotoMode()
|
||||||
setupPreviewImage(mIsInPhotoMode)
|
setupPreviewImage(isInPhotoMode)
|
||||||
mFocusCircleView.setStrokeColor(getProperPrimaryColor())
|
mFocusCircleView.setStrokeColor(getProperPrimaryColor())
|
||||||
|
|
||||||
if (isVideoCaptureIntent() && mIsInPhotoMode) {
|
|
||||||
handleTogglePhotoVideo()
|
|
||||||
checkButtons()
|
|
||||||
}
|
|
||||||
toggleBottomButtons(enabled = true)
|
toggleBottomButtons(enabled = true)
|
||||||
mOrientationEventListener.enable()
|
mOrientationEventListener.enable()
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
ensureTransparentNavigationBar()
|
ensureTransparentNavigationBar()
|
||||||
}
|
}
|
||||||
|
@ -156,7 +159,6 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
hideTimer()
|
|
||||||
mOrientationEventListener.disable()
|
mOrientationEventListener.disable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,18 +174,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initVariables() {
|
private fun initVariables() {
|
||||||
mIsInPhotoMode = if (isVideoCaptureIntent()) {
|
|
||||||
false
|
|
||||||
} else if (isImageCaptureIntent()) {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
config.initPhotoMode
|
|
||||||
}
|
|
||||||
mIsCameraAvailable = false
|
|
||||||
mIsHardwareShutterHandled = false
|
mIsHardwareShutterHandled = false
|
||||||
mCurrVideoRecTimer = 0
|
|
||||||
mLastHandledOrientation = 0
|
|
||||||
config.lastUsedCamera = CameraCharacteristics.LENS_FACING_BACK.toString()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
|
||||||
|
@ -218,19 +209,25 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
if (grantedCameraPermission) {
|
if (grantedCameraPermission) {
|
||||||
handleStoragePermission { grantedStoragePermission ->
|
handleStoragePermission { grantedStoragePermission ->
|
||||||
if (grantedStoragePermission) {
|
if (grantedStoragePermission) {
|
||||||
if (mIsInPhotoMode) {
|
val isInPhotoMode = isInPhotoMode()
|
||||||
initializeCamera()
|
if (isInPhotoMode) {
|
||||||
|
initializeCamera(true)
|
||||||
} else {
|
} else {
|
||||||
handlePermission(PERMISSION_RECORD_AUDIO) { grantedRecordAudioPermission ->
|
handlePermission(PERMISSION_RECORD_AUDIO) { grantedRecordAudioPermission ->
|
||||||
if (grantedRecordAudioPermission) {
|
if (grantedRecordAudioPermission) {
|
||||||
initializeCamera()
|
initializeCamera(false)
|
||||||
} else {
|
} else {
|
||||||
toast(R.string.no_audio_permissions)
|
toast(R.string.no_audio_permissions)
|
||||||
togglePhotoVideoMode()
|
if (isThirdPartyIntent()) {
|
||||||
|
finish()
|
||||||
|
} else {
|
||||||
|
// re-initialize in photo mode
|
||||||
|
config.initPhotoMode = true
|
||||||
tryInitCamera()
|
tryInitCamera()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
toast(R.string.no_storage_permissions)
|
toast(R.string.no_storage_permissions)
|
||||||
finish()
|
finish()
|
||||||
|
@ -243,6 +240,16 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isInPhotoMode(): Boolean {
|
||||||
|
return mPreview?.isInPhotoMode() ?: if (isVideoCaptureIntent()) {
|
||||||
|
false
|
||||||
|
} else if (isImageCaptureIntent()) {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
config.initPhotoMode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleStoragePermission(callback: (granted: Boolean) -> Unit) {
|
private fun handleStoragePermission(callback: (granted: Boolean) -> Unit) {
|
||||||
if (isTiramisuPlus()) {
|
if (isTiramisuPlus()) {
|
||||||
handlePermission(PERMISSION_READ_MEDIA_IMAGES) { grantedReadImages ->
|
handlePermission(PERMISSION_READ_MEDIA_IMAGES) { grantedReadImages ->
|
||||||
|
@ -263,24 +270,6 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
|
|
||||||
private fun isVideoCaptureIntent(): Boolean = intent?.action == MediaStore.ACTION_VIDEO_CAPTURE
|
private fun isVideoCaptureIntent(): Boolean = intent?.action == MediaStore.ACTION_VIDEO_CAPTURE
|
||||||
|
|
||||||
private fun checkImageCaptureIntent() {
|
|
||||||
if (isImageCaptureIntent()) {
|
|
||||||
hideIntentButtons()
|
|
||||||
val output = intent.extras?.get(MediaStore.EXTRA_OUTPUT)
|
|
||||||
if (output != null && output is Uri) {
|
|
||||||
mPreview?.setTargetUri(output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkVideoCaptureIntent() {
|
|
||||||
if (isVideoCaptureIntent()) {
|
|
||||||
mIsInPhotoMode = false
|
|
||||||
hideIntentButtons()
|
|
||||||
shutter.setImageResource(R.drawable.ic_video_rec_vector)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createToggleGroup(): MaterialButtonToggleGroup {
|
private fun createToggleGroup(): MaterialButtonToggleGroup {
|
||||||
return MaterialButtonToggleGroup(this).apply {
|
return MaterialButtonToggleGroup(this).apply {
|
||||||
isSingleSelection = true
|
isSingleSelection = true
|
||||||
|
@ -288,7 +277,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initializeCamera() {
|
private fun initializeCamera(isInPhotoMode: Boolean) {
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
initButtons()
|
initButtons()
|
||||||
initModeSwitcher()
|
initModeSwitcher()
|
||||||
|
@ -313,8 +302,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
WindowInsetsCompat.CONSUMED
|
WindowInsetsCompat.CONSUMED
|
||||||
}
|
}
|
||||||
|
|
||||||
checkVideoCaptureIntent()
|
if (isInPhotoMode) {
|
||||||
if (mIsInPhotoMode) {
|
|
||||||
selectPhotoTab()
|
selectPhotoTab()
|
||||||
} else {
|
} else {
|
||||||
selectVideoTab()
|
selectVideoTab()
|
||||||
|
@ -327,25 +315,18 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
listener = this,
|
listener = this,
|
||||||
outputUri = outputUri,
|
outputUri = outputUri,
|
||||||
isThirdPartyIntent = isThirdPartyIntent,
|
isThirdPartyIntent = isThirdPartyIntent,
|
||||||
initInPhotoMode = mIsInPhotoMode,
|
initInPhotoMode = isInPhotoMode,
|
||||||
)
|
)
|
||||||
checkImageCaptureIntent()
|
|
||||||
mPreview?.setIsImageCaptureIntent(isImageCaptureIntent())
|
|
||||||
|
|
||||||
val imageDrawable = if (config.lastUsedCamera == CameraCharacteristics.LENS_FACING_BACK.toString()) {
|
mFocusCircleView = FocusCircleView(this)
|
||||||
R.drawable.ic_camera_front_vector
|
|
||||||
} else {
|
|
||||||
R.drawable.ic_camera_rear_vector
|
|
||||||
}
|
|
||||||
|
|
||||||
toggle_camera.setImageResource(imageDrawable)
|
|
||||||
|
|
||||||
mFocusCircleView = FocusCircleView(applicationContext)
|
|
||||||
view_holder.addView(mFocusCircleView)
|
view_holder.addView(mFocusCircleView)
|
||||||
|
|
||||||
mTimerHandler = Handler(Looper.getMainLooper())
|
|
||||||
setupPreviewImage(true)
|
setupPreviewImage(true)
|
||||||
initFlashModeTransitionNames()
|
initFlashModeTransitionNames()
|
||||||
|
|
||||||
|
if (isThirdPartyIntent) {
|
||||||
|
hideIntentButtons()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initFlashModeTransitionNames() {
|
private fun initFlashModeTransitionNames() {
|
||||||
|
@ -357,9 +338,9 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initButtons() {
|
private fun initButtons() {
|
||||||
toggle_camera.setOnClickListener { toggleCamera() }
|
toggle_camera.setOnClickListener { mPreview!!.toggleFrontBackCamera() }
|
||||||
last_photo_video_preview.setOnClickListener { showLastMediaPreview() }
|
last_photo_video_preview.setOnClickListener { showLastMediaPreview() }
|
||||||
toggle_flash.setOnClickListener { toggleFlash() }
|
toggle_flash.setOnClickListener { mPreview!!.handleFlashlightClick() }
|
||||||
shutter.setOnClickListener { shutterPressed() }
|
shutter.setOnClickListener { shutterPressed() }
|
||||||
|
|
||||||
settings.setShadowIcon(R.drawable.ic_settings_vector)
|
settings.setShadowIcon(R.drawable.ic_settings_vector)
|
||||||
|
@ -382,7 +363,13 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
|
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
private fun initModeSwitcher() {
|
private fun initModeSwitcher() {
|
||||||
val gestureDetector = GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() {
|
val gestureDetector = GestureDetectorCompat(this, object : GestureDetector.SimpleOnGestureListener() {
|
||||||
|
override fun onDown(e: MotionEvent): Boolean {
|
||||||
|
// we have to return true here so ACTION_UP
|
||||||
|
// (and onFling) can be dispatched
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
override fun onFling(event1: MotionEvent, event2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
|
override fun onFling(event1: MotionEvent, event2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
|
||||||
// these can be null even if the docs say they cannot, getting event1.x in itself can cause crashes
|
// these can be null even if the docs say they cannot, getting event1.x in itself can cause crashes
|
||||||
try {
|
try {
|
||||||
|
@ -430,11 +417,6 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
mPreview?.setFlashlightState(flashMode)
|
mPreview?.setFlashlightState(flashMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toggleCamera() {
|
|
||||||
if (checkCameraAvailable()) {
|
|
||||||
mPreview!!.toggleFrontBackCamera()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showLastMediaPreview() {
|
private fun showLastMediaPreview() {
|
||||||
if (mPreviewUri != null) {
|
if (mPreviewUri != null) {
|
||||||
|
@ -443,24 +425,8 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toggleFlash() {
|
|
||||||
if (checkCameraAvailable()) {
|
|
||||||
if (mIsInPhotoMode) {
|
|
||||||
showFlashOptions(true)
|
|
||||||
} else {
|
|
||||||
mPreview?.toggleFlashlight()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun shutterPressed() {
|
private fun shutterPressed() {
|
||||||
if (checkCameraAvailable()) {
|
if (isInPhotoMode()) {
|
||||||
handleShutter()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleShutter() {
|
|
||||||
if (mIsInPhotoMode) {
|
|
||||||
toggleBottomButtons(enabled = false)
|
toggleBottomButtons(enabled = false)
|
||||||
change_resolution.isEnabled = true
|
change_resolution.isEnabled = true
|
||||||
mPreview?.tryTakePicture()
|
mPreview?.tryTakePicture()
|
||||||
|
@ -474,71 +440,15 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleTogglePhotoVideo() {
|
override fun onInitPhotoMode() {
|
||||||
handlePermission(PERMISSION_RECORD_AUDIO) {
|
|
||||||
if (it) {
|
|
||||||
togglePhotoVideo()
|
|
||||||
} else {
|
|
||||||
toast(R.string.no_audio_permissions)
|
|
||||||
selectPhotoTab()
|
|
||||||
if (isVideoCaptureIntent()) {
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun togglePhotoVideo() {
|
|
||||||
if (!checkCameraAvailable()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isVideoCaptureIntent()) {
|
|
||||||
mPreview?.initVideoMode()
|
|
||||||
}
|
|
||||||
|
|
||||||
mPreview?.setFlashlightState(FLASH_OFF)
|
|
||||||
hideTimer()
|
|
||||||
togglePhotoVideoMode()
|
|
||||||
checkButtons()
|
|
||||||
toggleBottomButtons(enabled = true)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun togglePhotoVideoMode() {
|
|
||||||
mIsInPhotoMode = !mIsInPhotoMode
|
|
||||||
config.initPhotoMode = mIsInPhotoMode
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkButtons() {
|
|
||||||
if (mIsInPhotoMode) {
|
|
||||||
initPhotoMode()
|
|
||||||
} else {
|
|
||||||
tryInitVideoMode()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initPhotoMode() {
|
|
||||||
shutter.setImageResource(R.drawable.ic_shutter_animated)
|
shutter.setImageResource(R.drawable.ic_shutter_animated)
|
||||||
mPreview?.initPhotoMode()
|
|
||||||
setupPreviewImage(true)
|
setupPreviewImage(true)
|
||||||
selectPhotoTab()
|
selectPhotoTab()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun tryInitVideoMode() {
|
override fun onInitVideoMode() {
|
||||||
try {
|
|
||||||
mPreview?.initVideoMode()
|
|
||||||
initVideoButtons()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
if (!isVideoCaptureIntent()) {
|
|
||||||
toast(R.string.video_mode_error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initVideoButtons() {
|
|
||||||
shutter.setImageResource(R.drawable.ic_video_rec_animated)
|
shutter.setImageResource(R.drawable.ic_video_rec_animated)
|
||||||
setupPreviewImage(false)
|
setupPreviewImage(false)
|
||||||
mPreview?.checkFlashlight()
|
|
||||||
selectVideoTab()
|
selectVideoTab()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -571,21 +481,8 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hideTimer() {
|
|
||||||
video_rec_curr_timer.text = 0.getFormattedDuration()
|
|
||||||
video_rec_curr_timer.beGone()
|
|
||||||
mCurrVideoRecTimer = 0
|
|
||||||
mTimerHandler.removeCallbacksAndMessages(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resumeCameraItems() {
|
|
||||||
if (!mIsInPhotoMode) {
|
|
||||||
initVideoButtons()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hasStorageAndCameraPermissions(): Boolean {
|
private fun hasStorageAndCameraPermissions(): Boolean {
|
||||||
return if (mIsInPhotoMode) hasPhotoModePermissions() else hasVideoModePermissions()
|
return if (isInPhotoMode()) hasPhotoModePermissions() else hasVideoModePermissions()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hasPhotoModePermissions(): Boolean {
|
private fun hasPhotoModePermissions(): Boolean {
|
||||||
|
@ -641,17 +538,6 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
|
|
||||||
private fun rotate(view: View, degrees: Int) = view.animate().rotation(degrees.toFloat()).start()
|
private fun rotate(view: View, degrees: Int) = view.animate().rotation(degrees.toFloat()).start()
|
||||||
|
|
||||||
private fun checkCameraAvailable(): Boolean {
|
|
||||||
if (!mIsCameraAvailable) {
|
|
||||||
toast(R.string.camera_unavailable)
|
|
||||||
}
|
|
||||||
return mIsCameraAvailable
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setCameraAvailable(available: Boolean) {
|
|
||||||
mIsCameraAvailable = available
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setHasFrontAndBackCamera(hasFrontAndBack: Boolean) {
|
override fun setHasFrontAndBackCamera(hasFrontAndBack: Boolean) {
|
||||||
toggle_camera?.beVisibleIf(hasFrontAndBack)
|
toggle_camera?.beVisibleIf(hasFrontAndBack)
|
||||||
}
|
}
|
||||||
|
@ -792,11 +678,11 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
isFrontCamera: Boolean,
|
isFrontCamera: Boolean,
|
||||||
onSelect: (index: Int, changed: Boolean) -> Unit
|
onSelect: (index: Int, changed: Boolean) -> Unit
|
||||||
) {
|
) {
|
||||||
|
|
||||||
top_options.removeView(mediaSizeToggleGroup)
|
top_options.removeView(mediaSizeToggleGroup)
|
||||||
val mediaSizeToggleGroup = createToggleGroup().apply {
|
val mediaSizeToggleGroup = createToggleGroup().apply {
|
||||||
mediaSizeToggleGroup = this
|
mediaSizeToggleGroup = this
|
||||||
}
|
}
|
||||||
|
|
||||||
top_options.addView(mediaSizeToggleGroup)
|
top_options.addView(mediaSizeToggleGroup)
|
||||||
|
|
||||||
val onItemClick = { clickedViewId: Int ->
|
val onItemClick = { clickedViewId: Int ->
|
||||||
|
@ -824,6 +710,7 @@ class MainActivity : SimpleActivity(), PhotoProcessor.MediaSavedListener, Camera
|
||||||
val params = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
val params = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||||
weight = 1f
|
weight = 1f
|
||||||
}
|
}
|
||||||
|
|
||||||
return (layoutInflater.inflate(R.layout.layout_button, null) as MaterialButton).apply {
|
return (layoutInflater.inflate(R.layout.layout_button, null) as MaterialButton).apply {
|
||||||
layoutParams = params
|
layoutParams = params
|
||||||
setShadowIcon(resolutionOption.imageDrawableResId)
|
setShadowIcon(resolutionOption.imageDrawableResId)
|
||||||
|
|
|
@ -35,10 +35,6 @@ class Config(context: Context) : BaseConfig(context) {
|
||||||
get() = prefs.getBoolean(FLIP_PHOTOS, true)
|
get() = prefs.getBoolean(FLIP_PHOTOS, true)
|
||||||
set(flipPhotos) = prefs.edit().putBoolean(FLIP_PHOTOS, flipPhotos).apply()
|
set(flipPhotos) = prefs.edit().putBoolean(FLIP_PHOTOS, flipPhotos).apply()
|
||||||
|
|
||||||
var lastUsedCamera: String
|
|
||||||
get() = prefs.getString(LAST_USED_CAMERA, "0")!!
|
|
||||||
set(cameraId) = prefs.edit().putString(LAST_USED_CAMERA, cameraId).apply()
|
|
||||||
|
|
||||||
var lastUsedCameraLens: Int
|
var lastUsedCameraLens: Int
|
||||||
get() = prefs.getInt(LAST_USED_CAMERA_LENS, CameraSelector.LENS_FACING_BACK)
|
get() = prefs.getInt(LAST_USED_CAMERA_LENS, CameraSelector.LENS_FACING_BACK)
|
||||||
set(lens) = prefs.edit().putInt(LAST_USED_CAMERA_LENS, lens).apply()
|
set(lens) = prefs.edit().putInt(LAST_USED_CAMERA_LENS, lens).apply()
|
||||||
|
|
|
@ -23,7 +23,8 @@ class CameraXInitializer(private val activity: BaseSimpleActivity) {
|
||||||
mediaOutputHelper,
|
mediaOutputHelper,
|
||||||
cameraErrorHandler,
|
cameraErrorHandler,
|
||||||
listener,
|
listener,
|
||||||
initInPhotoMode,
|
isThirdPartyIntent = isThirdPartyIntent,
|
||||||
|
initInPhotoMode = initInPhotoMode,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.hardware.SensorManager
|
import android.hardware.SensorManager
|
||||||
import android.hardware.display.DisplayManager
|
import android.hardware.display.DisplayManager
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import android.util.Rational
|
import android.util.Rational
|
||||||
import android.util.Size
|
import android.util.Size
|
||||||
import android.view.*
|
import android.view.*
|
||||||
|
@ -19,6 +21,7 @@ import androidx.camera.view.PreviewView.ScaleType
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.doOnLayout
|
import androidx.core.view.doOnLayout
|
||||||
import androidx.lifecycle.DefaultLifecycleObserver
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.window.layout.WindowMetricsCalculator
|
import androidx.window.layout.WindowMetricsCalculator
|
||||||
import com.bumptech.glide.load.ImageHeaderParser.UNKNOWN_ORIENTATION
|
import com.bumptech.glide.load.ImageHeaderParser.UNKNOWN_ORIENTATION
|
||||||
|
@ -39,6 +42,7 @@ class CameraXPreview(
|
||||||
private val mediaOutputHelper: MediaOutputHelper,
|
private val mediaOutputHelper: MediaOutputHelper,
|
||||||
private val cameraErrorHandler: CameraErrorHandler,
|
private val cameraErrorHandler: CameraErrorHandler,
|
||||||
private val listener: CameraXPreviewListener,
|
private val listener: CameraXPreviewListener,
|
||||||
|
private val isThirdPartyIntent: Boolean,
|
||||||
initInPhotoMode: Boolean,
|
initInPhotoMode: Boolean,
|
||||||
) : MyPreview, DefaultLifecycleObserver {
|
) : MyPreview, DefaultLifecycleObserver {
|
||||||
|
|
||||||
|
@ -46,6 +50,7 @@ class CameraXPreview(
|
||||||
// Auto focus is 1/6 of the area.
|
// Auto focus is 1/6 of the area.
|
||||||
private const val AF_SIZE = 1.0f / 6.0f
|
private const val AF_SIZE = 1.0f / 6.0f
|
||||||
private const val AE_SIZE = AF_SIZE * 1.5f
|
private const val AE_SIZE = AF_SIZE * 1.5f
|
||||||
|
private const val CAMERA_MODE_SWITCH_WAIT_TIME = 500L
|
||||||
}
|
}
|
||||||
|
|
||||||
private val config = activity.config
|
private val config = activity.config
|
||||||
|
@ -80,6 +85,29 @@ class CameraXPreview(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private val startCameraHandler = Handler(Looper.getMainLooper())
|
||||||
|
private val photoModeRunnable = Runnable {
|
||||||
|
if (imageCapture == null) {
|
||||||
|
isPhotoCapture = true
|
||||||
|
if (!isThirdPartyIntent) { // we don't want to store the state for 3rd party intents
|
||||||
|
config.initPhotoMode = true
|
||||||
|
}
|
||||||
|
startCamera()
|
||||||
|
} else {
|
||||||
|
listener.onInitPhotoMode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private val videoModeRunnable = Runnable {
|
||||||
|
if (videoCapture == null) {
|
||||||
|
isPhotoCapture = false
|
||||||
|
if (!isThirdPartyIntent) { // we don't want to store the state for 3rd party intents
|
||||||
|
config.initPhotoMode = false
|
||||||
|
}
|
||||||
|
startCamera()
|
||||||
|
} else {
|
||||||
|
listener.onInitVideoMode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var preview: Preview? = null
|
private var preview: Preview? = null
|
||||||
private var cameraProvider: ProcessCameraProvider? = null
|
private var cameraProvider: ProcessCameraProvider? = null
|
||||||
|
@ -92,13 +120,11 @@ class CameraXPreview(
|
||||||
private var flashMode = FLASH_MODE_OFF
|
private var flashMode = FLASH_MODE_OFF
|
||||||
private var isPhotoCapture = initInPhotoMode
|
private var isPhotoCapture = initInPhotoMode
|
||||||
private var lastRotation = 0
|
private var lastRotation = 0
|
||||||
|
private var lastCameraStartTime = 0L
|
||||||
|
|
||||||
init {
|
init {
|
||||||
bindToLifeCycle()
|
bindToLifeCycle()
|
||||||
mediaSoundHelper.loadSounds()
|
mediaSoundHelper.loadSounds()
|
||||||
previewView.doOnLayout {
|
|
||||||
startCamera()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindToLifeCycle() {
|
private fun bindToLifeCycle() {
|
||||||
|
@ -106,13 +132,12 @@ class CameraXPreview(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startCamera(switching: Boolean = false) {
|
private fun startCamera(switching: Boolean = false) {
|
||||||
imageQualityManager.initSupportedQualities()
|
val cameraProviderFuture = ProcessCameraProvider.getInstance(activity.applicationContext)
|
||||||
|
|
||||||
val cameraProviderFuture = ProcessCameraProvider.getInstance(activity)
|
|
||||||
cameraProviderFuture.addListener({
|
cameraProviderFuture.addListener({
|
||||||
try {
|
try {
|
||||||
val provider = cameraProviderFuture.get()
|
val provider = cameraProviderFuture.get()
|
||||||
cameraProvider = provider
|
cameraProvider = provider
|
||||||
|
imageQualityManager.initSupportedQualities()
|
||||||
videoQualityManager.initSupportedQualities(provider)
|
videoQualityManager.initSupportedQualities(provider)
|
||||||
bindCameraUseCases()
|
bindCameraUseCases()
|
||||||
setupCameraObservers()
|
setupCameraObservers()
|
||||||
|
@ -128,11 +153,11 @@ class CameraXPreview(
|
||||||
|
|
||||||
val resolution = if (isPhotoCapture) {
|
val resolution = if (isPhotoCapture) {
|
||||||
imageQualityManager.getUserSelectedResolution(cameraSelector).also {
|
imageQualityManager.getUserSelectedResolution(cameraSelector).also {
|
||||||
displaySelectedResolution(it.toResolutionOption())
|
listener.displaySelectedResolution(it.toResolutionOption())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val selectedQuality = videoQualityManager.getUserSelectedQuality(cameraSelector).also {
|
val selectedQuality = videoQualityManager.getUserSelectedQuality(cameraSelector).also {
|
||||||
displaySelectedResolution(it.toResolutionOption())
|
listener.displaySelectedResolution(it.toResolutionOption())
|
||||||
}
|
}
|
||||||
MySize(selectedQuality.width, selectedQuality.height)
|
MySize(selectedQuality.width, selectedQuality.height)
|
||||||
}
|
}
|
||||||
|
@ -178,10 +203,6 @@ class CameraXPreview(
|
||||||
setFlashlightState(config.flashlightState)
|
setFlashlightState(config.flashlightState)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun displaySelectedResolution(resolutionOption: ResolutionOption) {
|
|
||||||
listener.displaySelectedResolution(resolutionOption)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getRotatedResolution(resolution: MySize, rotationDegrees: Int): Size {
|
private fun getRotatedResolution(resolution: MySize, rotationDegrees: Int): Size {
|
||||||
return if (rotationDegrees == Surface.ROTATION_0 || rotationDegrees == Surface.ROTATION_180) {
|
return if (rotationDegrees == Surface.ROTATION_0 || rotationDegrees == Surface.ROTATION_180) {
|
||||||
Size(resolution.height, resolution.width)
|
Size(resolution.height, resolution.width)
|
||||||
|
@ -201,10 +222,12 @@ class CameraXPreview(
|
||||||
return if (isPhotoCapture) {
|
return if (isPhotoCapture) {
|
||||||
buildImageCapture(resolution, rotation).also {
|
buildImageCapture(resolution, rotation).also {
|
||||||
imageCapture = it
|
imageCapture = it
|
||||||
|
videoCapture = null
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buildVideoCapture().also {
|
buildVideoCapture().also {
|
||||||
videoCapture = it
|
videoCapture = it
|
||||||
|
imageCapture = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,11 +265,16 @@ class CameraXPreview(
|
||||||
private fun setupCameraObservers() {
|
private fun setupCameraObservers() {
|
||||||
listener.setFlashAvailable(camera?.cameraInfo?.hasFlashUnit() ?: false)
|
listener.setFlashAvailable(camera?.cameraInfo?.hasFlashUnit() ?: false)
|
||||||
listener.onChangeCamera(isFrontCameraInUse())
|
listener.onChangeCamera(isFrontCameraInUse())
|
||||||
|
if (isPhotoCapture) {
|
||||||
|
listener.onInitPhotoMode()
|
||||||
|
} else {
|
||||||
|
listener.onInitVideoMode()
|
||||||
|
}
|
||||||
camera?.cameraInfo?.cameraState?.observe(activity) { cameraState ->
|
camera?.cameraInfo?.cameraState?.observe(activity) { cameraState ->
|
||||||
|
if (cameraState.error == null) {
|
||||||
when (cameraState.type) {
|
when (cameraState.type) {
|
||||||
CameraState.Type.OPEN,
|
CameraState.Type.OPENING,
|
||||||
CameraState.Type.OPENING -> {
|
CameraState.Type.OPEN -> {
|
||||||
listener.setHasFrontAndBackCamera(hasFrontCamera() && hasBackCamera())
|
listener.setHasFrontAndBackCamera(hasFrontCamera() && hasBackCamera())
|
||||||
listener.setCameraAvailable(true)
|
listener.setCameraAvailable(true)
|
||||||
}
|
}
|
||||||
|
@ -256,8 +284,10 @@ class CameraXPreview(
|
||||||
listener.setCameraAvailable(false)
|
listener.setCameraAvailable(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
cameraErrorHandler.handleCameraError(cameraState?.error)
|
listener.setCameraAvailable(false)
|
||||||
|
cameraErrorHandler.handleCameraError(cameraState.error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,12 +342,21 @@ class CameraXPreview(
|
||||||
|
|
||||||
override fun onStart(owner: LifecycleOwner) {
|
override fun onStart(owner: LifecycleOwner) {
|
||||||
orientationEventListener.enable()
|
orientationEventListener.enable()
|
||||||
|
previewView.doOnLayout {
|
||||||
|
if (owner.lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED)) {
|
||||||
|
startCamera()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onStop(owner: LifecycleOwner) {
|
override fun onStop(owner: LifecycleOwner) {
|
||||||
orientationEventListener.disable()
|
orientationEventListener.disable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun isInPhotoMode(): Boolean {
|
||||||
|
return isPhotoCapture
|
||||||
|
}
|
||||||
|
|
||||||
override fun showChangeResolution() {
|
override fun showChangeResolution() {
|
||||||
val selectedResolution = if (isPhotoCapture) {
|
val selectedResolution = if (isPhotoCapture) {
|
||||||
imageQualityManager.getUserSelectedResolution(cameraSelector).toResolutionOption()
|
imageQualityManager.getUserSelectedResolution(cameraSelector).toResolutionOption()
|
||||||
|
@ -377,7 +416,15 @@ class CameraXPreview(
|
||||||
startCamera(switching = true)
|
startCamera(switching = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toggleFlashlight() {
|
override fun handleFlashlightClick() {
|
||||||
|
if (isPhotoCapture) {
|
||||||
|
listener.showFlashOptions(true)
|
||||||
|
} else {
|
||||||
|
toggleFlashlight()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toggleFlashlight() {
|
||||||
val newFlashMode = if (isPhotoCapture) {
|
val newFlashMode = if (isPhotoCapture) {
|
||||||
when (flashMode) {
|
when (flashMode) {
|
||||||
FLASH_MODE_OFF -> FLASH_MODE_ON
|
FLASH_MODE_OFF -> FLASH_MODE_ON
|
||||||
|
@ -396,17 +443,22 @@ class CameraXPreview(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setFlashlightState(state: Int) {
|
override fun setFlashlightState(state: Int) {
|
||||||
|
var flashState = state
|
||||||
if (isPhotoCapture) {
|
if (isPhotoCapture) {
|
||||||
camera?.cameraControl?.enableTorch(state == FLASH_ALWAYS_ON)
|
camera?.cameraControl?.enableTorch(flashState == FLASH_ALWAYS_ON)
|
||||||
} else {
|
} else {
|
||||||
camera?.cameraControl?.enableTorch(state == FLASH_ON || state == FLASH_ALWAYS_ON)
|
camera?.cameraControl?.enableTorch(flashState == FLASH_ON || flashState == FLASH_ALWAYS_ON)
|
||||||
|
// reset to the FLASH_ON for video capture
|
||||||
|
if (flashState == FLASH_ALWAYS_ON) {
|
||||||
|
flashState = FLASH_ON
|
||||||
}
|
}
|
||||||
val newFlashMode = state.toCameraXFlashMode()
|
}
|
||||||
|
val newFlashMode = flashState.toCameraXFlashMode()
|
||||||
flashMode = newFlashMode
|
flashMode = newFlashMode
|
||||||
imageCapture?.flashMode = newFlashMode
|
imageCapture?.flashMode = newFlashMode
|
||||||
|
|
||||||
config.flashlightState = state
|
config.flashlightState = flashState
|
||||||
listener.onChangeFlashMode(state)
|
listener.onChangeFlashMode(flashState)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun tryTakePicture() {
|
override fun tryTakePicture() {
|
||||||
|
@ -467,13 +519,23 @@ class CameraXPreview(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initPhotoMode() {
|
override fun initPhotoMode() {
|
||||||
isPhotoCapture = true
|
debounceChangeCameraMode(photoModeRunnable)
|
||||||
startCamera()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initVideoMode() {
|
override fun initVideoMode() {
|
||||||
isPhotoCapture = false
|
debounceChangeCameraMode(videoModeRunnable)
|
||||||
startCamera()
|
}
|
||||||
|
|
||||||
|
private fun debounceChangeCameraMode(cameraModeRunnable: Runnable) {
|
||||||
|
val currentTime = System.currentTimeMillis()
|
||||||
|
if (currentTime - lastCameraStartTime > CAMERA_MODE_SWITCH_WAIT_TIME) {
|
||||||
|
cameraModeRunnable.run()
|
||||||
|
} else {
|
||||||
|
startCameraHandler.removeCallbacks(photoModeRunnable)
|
||||||
|
startCameraHandler.removeCallbacks(videoModeRunnable)
|
||||||
|
startCameraHandler.postDelayed(cameraModeRunnable, CAMERA_MODE_SWITCH_WAIT_TIME)
|
||||||
|
}
|
||||||
|
lastCameraStartTime = currentTime
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toggleRecording() {
|
override fun toggleRecording() {
|
||||||
|
@ -489,8 +551,7 @@ class CameraXPreview(
|
||||||
private fun startRecording() {
|
private fun startRecording() {
|
||||||
val videoCapture = videoCapture ?: throw IllegalStateException("Camera initialization failed.")
|
val videoCapture = videoCapture ?: throw IllegalStateException("Camera initialization failed.")
|
||||||
|
|
||||||
val mediaOutput = mediaOutputHelper.getVideoMediaOutput()
|
val recording = when (val mediaOutput = mediaOutputHelper.getVideoMediaOutput()) {
|
||||||
val recording = when (mediaOutput) {
|
|
||||||
is MediaOutput.FileDescriptorMediaOutput -> {
|
is MediaOutput.FileDescriptorMediaOutput -> {
|
||||||
FileDescriptorOutputOptions.Builder(mediaOutput.fileDescriptor).build()
|
FileDescriptorOutputOptions.Builder(mediaOutput.fileDescriptor).build()
|
||||||
.let { videoCapture.output.prepareRecording(activity, it) }
|
.let { videoCapture.output.prepareRecording(activity, it) }
|
||||||
|
|
|
@ -5,7 +5,9 @@ import android.net.Uri
|
||||||
import com.simplemobiletools.camera.models.ResolutionOption
|
import com.simplemobiletools.camera.models.ResolutionOption
|
||||||
|
|
||||||
interface CameraXPreviewListener {
|
interface CameraXPreviewListener {
|
||||||
fun setCameraAvailable(available: Boolean)
|
fun onInitPhotoMode()
|
||||||
|
fun onInitVideoMode()
|
||||||
|
fun setCameraAvailable(available: Boolean) {}
|
||||||
fun setHasFrontAndBackCamera(hasFrontAndBack: Boolean)
|
fun setHasFrontAndBackCamera(hasFrontAndBack: Boolean)
|
||||||
fun setFlashAvailable(available: Boolean)
|
fun setFlashAvailable(available: Boolean)
|
||||||
fun onChangeCamera(frontCamera: Boolean)
|
fun onChangeCamera(frontCamera: Boolean)
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
package com.simplemobiletools.camera.interfaces
|
package com.simplemobiletools.camera.interfaces
|
||||||
|
|
||||||
import android.net.Uri
|
|
||||||
|
|
||||||
interface MyPreview {
|
interface MyPreview {
|
||||||
|
|
||||||
fun setTargetUri(uri: Uri) = Unit
|
fun isInPhotoMode(): Boolean
|
||||||
|
|
||||||
fun setIsImageCaptureIntent(isImageCaptureIntent: Boolean) = Unit
|
fun setFlashlightState(state: Int)
|
||||||
|
|
||||||
fun setFlashlightState(state: Int) = Unit
|
|
||||||
|
|
||||||
fun toggleFrontBackCamera()
|
fun toggleFrontBackCamera()
|
||||||
|
|
||||||
fun toggleFlashlight() = Unit
|
fun handleFlashlightClick()
|
||||||
|
|
||||||
fun tryTakePicture()
|
fun tryTakePicture()
|
||||||
|
|
||||||
|
@ -22,7 +18,5 @@ interface MyPreview {
|
||||||
|
|
||||||
fun initVideoMode()
|
fun initVideoMode()
|
||||||
|
|
||||||
fun checkFlashlight() = Unit
|
fun showChangeResolution()
|
||||||
|
|
||||||
fun showChangeResolution() = Unit
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue