Hi, I followed Donovan's tutorial using the CameraController pathway because it already has zoom, focus, WYSIWYG..etc, I am now trying to integrate VideoCapture (I believe it's still experimental?) .I only found examples for video on "Migrating camera1 to camerax' guide, I am getting errors about
being unresolved and others.. I would like to know If my code is outdated? I can't get it to work. Thanks!
class MainActivity : AppCompatActivity() {
private lateinit var viewBinding: ActivityMainBinding
//If using CameraController
private lateinit var cameraController: LifecycleCameraController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(viewBinding.root)
if(!hasPermissions(baseContext)) {
//Request camera-related permissions
activityResultLauncher.launch(REQUIRED_PERMISSIONS)
}else{
startCamera()
}
// Set up the listeners for take photo and video capture buttons
viewBinding.imageCaptureButton.setOnClickListener { takePhoto()}
viewBinding.videoCaptureButton.setOnClickListener { startStopVideo()}
}
private fun startCamera(){
val previewView: PreviewView = viewBinding.viewFinder
cameraController = LifecycleCameraController(baseContext)
cameraController.setEnabledUseCases(VIDEO_CAPTURE)
cameraController.bindToLifecycle(this)
cameraController.cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
previewView.controller = cameraController
}
//Define a VideoSaveCallback class for handling success and error states.
class VideoSaveCallback : OnVideoSavedCallback {
override fun onVideoSaved(outputFileResults: OutputFileResults) {
val msg = "Video capture succeeded: ${outputFileResults.savedUri}"
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
Log.d(TAG, msg)
}
override fun onError(videoCaptureError: Int, message: String,
cause: Throwable?) {
Log.d(TAG, "error saving video: $message", cause)
}
}
private fun startStopVideo() {
if (cameraController.isRecording()) {
// Stop the current recording session.
cameraController.stopRecording()
return
}
// Define the File options for saving the video.
val name = SimpleDateFormat(FILENAME_FORMAT, Locale.US)
.format(System.currentTimeMillis())
val outputFileOptions = OutputFileOptions
.Builder(File(this.filesDir, name))
.build()
// Call startRecording on the CameraController.
cameraController.startRecording(
outputFileOptions,AudioConfig.AUDIO_DISABLED,
ContextCompat.getMainExecutor(this),
VideoSaveCallback()
)
}
private fun takePhoto(){
// Create time stamped name and MediaStore entry.
val name = SimpleDateFormat(FILENAME_FORMAT, Locale.US)
.format(System.currentTimeMillis())
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, name)
put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg")
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.P){
put(MediaStore.Images.Media.RELATIVE_PATH, "Pictures/BAM2-Image")
}
}
//Create output options object which contains file + metadata
val outputOptions = ImageCapture.OutputFileOptions
.Builder(contentResolver,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
contentValues)
.build()
//Set up image capture listener, which is triggered after photo has
//been taken
cameraController.takePicture(
outputOptions,
ContextCompat.getMainExecutor(this),
object : ImageCapture.OnImageSavedCallback{
override fun onError(exc: ImageCaptureException) {
Log.e(TAG, "Photo capture failed: ${exc.message}", exc)
}
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val msg = "Photo capture succeeded: ${output.savedUri}"
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
Log.d(TAG,msg)
}
}
)
}