forked from hardcoresushi/DroidFS
Fix flash and timer for video recording
This commit is contained in:
parent
8b4adfbe21
commit
b65ee230be
@ -84,6 +84,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
|||||||
private var isBackCamera = true
|
private var isBackCamera = true
|
||||||
private var isInVideoMode = false
|
private var isInVideoMode = false
|
||||||
private var isRecording = false
|
private var isRecording = false
|
||||||
|
private var isWaitingForTimer = false
|
||||||
private lateinit var binding: ActivityCameraBinding
|
private lateinit var binding: ActivityCameraBinding
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@ -185,24 +186,39 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
|||||||
dialog.show()
|
dialog.show()
|
||||||
}
|
}
|
||||||
binding.imageFlash.setOnClickListener {
|
binding.imageFlash.setOnClickListener {
|
||||||
binding.imageFlash.setImageResource(when (imageCapture?.flashMode) {
|
binding.imageFlash.setImageResource(if (isInVideoMode) {
|
||||||
ImageCapture.FLASH_MODE_AUTO -> {
|
when (imageCapture?.flashMode) {
|
||||||
imageCapture?.flashMode = ImageCapture.FLASH_MODE_ON
|
ImageCapture.FLASH_MODE_ON -> {
|
||||||
R.drawable.icon_flash_on
|
camera?.cameraControl?.enableTorch(false)
|
||||||
|
imageCapture?.flashMode = ImageCapture.FLASH_MODE_OFF
|
||||||
|
R.drawable.icon_flash_off
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
camera?.cameraControl?.enableTorch(true)
|
||||||
|
imageCapture?.flashMode = ImageCapture.FLASH_MODE_ON
|
||||||
|
R.drawable.icon_flash_on
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImageCapture.FLASH_MODE_ON -> {
|
} else {
|
||||||
imageCapture?.flashMode = ImageCapture.FLASH_MODE_OFF
|
when (imageCapture?.flashMode) {
|
||||||
R.drawable.icon_flash_off
|
ImageCapture.FLASH_MODE_AUTO -> {
|
||||||
}
|
imageCapture?.flashMode = ImageCapture.FLASH_MODE_ON
|
||||||
else -> {
|
R.drawable.icon_flash_on
|
||||||
imageCapture?.flashMode = ImageCapture.FLASH_MODE_AUTO
|
}
|
||||||
R.drawable.icon_flash_auto
|
ImageCapture.FLASH_MODE_ON -> {
|
||||||
|
imageCapture?.flashMode = ImageCapture.FLASH_MODE_OFF
|
||||||
|
R.drawable.icon_flash_off
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
imageCapture?.flashMode = ImageCapture.FLASH_MODE_AUTO
|
||||||
|
R.drawable.icon_flash_auto
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
binding.imageModeSwitch.setOnClickListener {
|
binding.imageModeSwitch.setOnClickListener {
|
||||||
isInVideoMode = !isInVideoMode
|
isInVideoMode = !isInVideoMode
|
||||||
if (isInVideoMode) {
|
binding.imageFlash.setImageResource(if (isInVideoMode) {
|
||||||
binding.recordVideoButton.visibility = View.VISIBLE
|
binding.recordVideoButton.visibility = View.VISIBLE
|
||||||
binding.takePhotoButton.visibility = View.GONE
|
binding.takePhotoButton.visibility = View.GONE
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
@ -211,10 +227,14 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
|||||||
requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), AUDIO_PERMISSION_REQUEST_CODE)
|
requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), AUDIO_PERMISSION_REQUEST_CODE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
imageCapture?.flashMode = ImageCapture.FLASH_MODE_OFF
|
||||||
|
R.drawable.icon_flash_off
|
||||||
} else {
|
} else {
|
||||||
binding.recordVideoButton.visibility = View.GONE
|
binding.recordVideoButton.visibility = View.GONE
|
||||||
binding.takePhotoButton.visibility = View.VISIBLE
|
binding.takePhotoButton.visibility = View.VISIBLE
|
||||||
}
|
imageCapture?.flashMode = ImageCapture.FLASH_MODE_AUTO
|
||||||
|
R.drawable.icon_flash_auto
|
||||||
|
})
|
||||||
}
|
}
|
||||||
binding.imageCameraSwitch.setOnClickListener {
|
binding.imageCameraSwitch.setOnClickListener {
|
||||||
isBackCamera = if (isBackCamera) {
|
isBackCamera = if (isBackCamera) {
|
||||||
@ -337,34 +357,6 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun takePhoto(outputPath: String) {
|
|
||||||
val imageCapture = imageCapture ?: return
|
|
||||||
val outputBuff = ByteArrayOutputStream()
|
|
||||||
val outputOptions = ImageCapture.OutputFileOptions.Builder(outputBuff).build()
|
|
||||||
imageCapture.takePicture(outputOptions, executor, object : ImageCapture.OnImageSavedCallback {
|
|
||||||
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
|
|
||||||
binding.takePhotoButton.onPhotoTaken()
|
|
||||||
if (gocryptfsVolume.importFile(ByteArrayInputStream(outputBuff.toByteArray()), outputPath)){
|
|
||||||
Toast.makeText(applicationContext, getString(R.string.picture_save_success, outputPath), Toast.LENGTH_SHORT).show()
|
|
||||||
} else {
|
|
||||||
CustomAlertDialogBuilder(this@CameraActivity, themeValue)
|
|
||||||
.setTitle(R.string.error)
|
|
||||||
.setMessage(R.string.picture_save_failed)
|
|
||||||
.setCancelable(false)
|
|
||||||
.setPositiveButton(R.string.ok) { _, _ ->
|
|
||||||
isFinishingIntentionally = true
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
override fun onError(exception: ImageCaptureException) {
|
|
||||||
binding.takePhotoButton.onPhotoTaken()
|
|
||||||
Toast.makeText(applicationContext, exception.message, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getOutputPath(isVideo: Boolean): String {
|
private fun getOutputPath(isVideo: Boolean): String {
|
||||||
val baseName = if (isVideo) {"VID"} else {"IMG"}+'_'+dateFormat.format(Date())+'_'
|
val baseName = if (isVideo) {"VID"} else {"IMG"}+'_'+dateFormat.format(Date())+'_'
|
||||||
var fileName: String
|
var fileName: String
|
||||||
@ -374,57 +366,94 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
|||||||
return PathUtils.pathJoin(outputDirectory, fileName)
|
return PathUtils.pathJoin(outputDirectory, fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onClickTakePhoto() {
|
private fun startTimerThen(action: () -> Unit) {
|
||||||
val path = getOutputPath(false)
|
|
||||||
if (timerDuration > 0){
|
if (timerDuration > 0){
|
||||||
binding.textTimer.visibility = View.VISIBLE
|
binding.textTimer.visibility = View.VISIBLE
|
||||||
|
isWaitingForTimer = true
|
||||||
Thread{
|
Thread{
|
||||||
for (i in timerDuration downTo 1){
|
for (i in timerDuration downTo 1){
|
||||||
runOnUiThread { binding.textTimer.text = i.toString() }
|
runOnUiThread { binding.textTimer.text = i.toString() }
|
||||||
Thread.sleep(1000)
|
Thread.sleep(1000)
|
||||||
}
|
}
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
takePhoto(path)
|
action()
|
||||||
binding.textTimer.visibility = View.GONE
|
binding.textTimer.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
isWaitingForTimer = false
|
||||||
}.start()
|
}.start()
|
||||||
} else {
|
} else {
|
||||||
takePhoto(path)
|
action()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onClickTakePhoto() {
|
||||||
|
if (!isWaitingForTimer) {
|
||||||
|
val outputPath = getOutputPath(false)
|
||||||
|
startTimerThen {
|
||||||
|
imageCapture?.let { imageCapture ->
|
||||||
|
val outputBuff = ByteArrayOutputStream()
|
||||||
|
val outputOptions = ImageCapture.OutputFileOptions.Builder(outputBuff).build()
|
||||||
|
imageCapture.takePicture(outputOptions, executor, object : ImageCapture.OnImageSavedCallback {
|
||||||
|
override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {
|
||||||
|
binding.takePhotoButton.onPhotoTaken()
|
||||||
|
if (gocryptfsVolume.importFile(ByteArrayInputStream(outputBuff.toByteArray()), outputPath)) {
|
||||||
|
Toast.makeText(applicationContext, getString(R.string.picture_save_success, outputPath), Toast.LENGTH_SHORT).show()
|
||||||
|
} else {
|
||||||
|
CustomAlertDialogBuilder(this@CameraActivity, themeValue)
|
||||||
|
.setTitle(R.string.error)
|
||||||
|
.setMessage(R.string.picture_save_failed)
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(R.string.ok) { _, _ ->
|
||||||
|
isFinishingIntentionally = true
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override fun onError(exception: ImageCaptureException) {
|
||||||
|
binding.takePhotoButton.onPhotoTaken()
|
||||||
|
Toast.makeText(applicationContext, exception.message, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
private fun onClickRecordVideo() {
|
private fun onClickRecordVideo() {
|
||||||
isRecording = if (isRecording) {
|
if (isRecording) {
|
||||||
videoCapture?.stopRecording()
|
videoCapture?.stopRecording()
|
||||||
false
|
isRecording = false
|
||||||
} else {
|
} else if (!isWaitingForTimer) {
|
||||||
val path = getOutputPath(true)
|
val path = getOutputPath(true)
|
||||||
val handleId = gocryptfsVolume.openWriteMode(path)
|
startTimerThen {
|
||||||
videoCapture?.startRecording(VideoCapture.OutputFileOptions(object : SeekableWriter {
|
val handleId = gocryptfsVolume.openWriteMode(path)
|
||||||
var offset = 0L
|
videoCapture?.startRecording(VideoCapture.OutputFileOptions(object : SeekableWriter {
|
||||||
override fun write(byteArray: ByteArray) {
|
var offset = 0L
|
||||||
offset += gocryptfsVolume.writeFile(handleId, offset, byteArray, byteArray.size)
|
override fun write(byteArray: ByteArray) {
|
||||||
}
|
offset += gocryptfsVolume.writeFile(handleId, offset, byteArray, byteArray.size)
|
||||||
override fun seek(offset: Long) {
|
}
|
||||||
this.offset = offset
|
override fun seek(offset: Long) {
|
||||||
}
|
this.offset = offset
|
||||||
override fun close() {
|
}
|
||||||
gocryptfsVolume.closeFile(handleId)
|
override fun close() {
|
||||||
}
|
gocryptfsVolume.closeFile(handleId)
|
||||||
}), executor, object : VideoCapture.OnVideoSavedCallback {
|
}
|
||||||
override fun onVideoSaved() {
|
}), executor, object : VideoCapture.OnVideoSavedCallback {
|
||||||
Toast.makeText(applicationContext, getString(R.string.video_save_success, path), Toast.LENGTH_SHORT).show()
|
override fun onVideoSaved() {
|
||||||
binding.recordVideoButton.setImageResource(R.drawable.record_video_button)
|
Toast.makeText(applicationContext, getString(R.string.video_save_success, path), Toast.LENGTH_SHORT).show()
|
||||||
}
|
binding.recordVideoButton.setImageResource(R.drawable.record_video_button)
|
||||||
override fun onError(videoCaptureError: Int, message: String, cause: Throwable?) {
|
}
|
||||||
Toast.makeText(applicationContext, message, Toast.LENGTH_SHORT).show()
|
override fun onError(videoCaptureError: Int, message: String, cause: Throwable?) {
|
||||||
cause?.printStackTrace()
|
Toast.makeText(applicationContext, message, Toast.LENGTH_SHORT).show()
|
||||||
binding.recordVideoButton.setImageResource(R.drawable.record_video_button)
|
cause?.printStackTrace()
|
||||||
}
|
binding.recordVideoButton.setImageResource(R.drawable.record_video_button)
|
||||||
})
|
}
|
||||||
binding.recordVideoButton.setImageResource(R.drawable.stop_recording_video_button)
|
})
|
||||||
true
|
binding.recordVideoButton.setImageResource(R.drawable.stop_recording_video_button)
|
||||||
|
isRecording = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user