我已经阅读了https://developer.android.com/training/camerax上的 CameraX 概述。
我希望录制视频,CameraX 是否支持录制视频?
顺便说一句,我可以使用 CameraX (Android Jetpack) 录制视频中的代码吗?不适用于最新版本camerax_version = "1.0.0-alpha06"
我已经阅读了https://developer.android.com/training/camerax上的 CameraX 概述。
我希望录制视频,CameraX 是否支持录制视频?
顺便说一句,我可以使用 CameraX (Android Jetpack) 录制视频中的代码吗?不适用于最新版本camerax_version = "1.0.0-alpha06"
是的。您可以拥有视频用例。请检查示例代码以启用视频用例,
是的,CameraX 也支持录制视频。
我最近创建了演示。请检查以下代码。
Java 文件
private const val REQUEST_CODE_PERMISSIONS = 10
private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
private val tag = MainActivity::class.java.simpleName
@SuppressLint("RestrictedApi, ClickableViewAccessibility")
class VideoCaptureActivity : AppCompatActivity(), LifecycleOwner {
private lateinit var viewFinder: TextureView
private lateinit var captureButton: ImageButton
private lateinit var videoCapture: VideoCapture
private var lensFacing = CameraX.LensFacing.BACK
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_video_capture)
viewFinder = findViewById(R.id.view_finder)
captureButton = findViewById(R.id.capture_button)
// Request camera permissions
if (allPermissionsGranted()) {
viewFinder.post { startCamera() }
} else {
ActivityCompat.requestPermissions(
this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS
)
}
val file = File(
externalMediaDirs.first(),"${System.currentTimeMillis()}.mp4"
)
captureButton.setOnTouchListener { _, event ->
if (event.action == MotionEvent.ACTION_DOWN) {
captureButton.setBackgroundColor(Color.GREEN)
videoCapture.startRecording(file, object : VideoCapture.OnVideoSavedListener {
override fun onVideoSaved(file: File?) {
Log.i(tag, "Video File : $file")
}
override fun onError(
useCaseError: VideoCapture.UseCaseError?,
message: String?,
cause: Throwable?
) {
Log.i(tag, "Video Error: $message")
}
})
} else if (event.action == MotionEvent.ACTION_UP) {
captureButton.setBackgroundColor(Color.RED)
videoCapture.stopRecording()
Log.i(tag, "Video File stopped")
}
false
}
}
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>, grantResults: IntArray
) {
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
viewFinder.post { startCamera() }
} else {
Toast.makeText(this,"Permissions not granted by the user.",Toast.LENGTH_SHORT).show()
finish()
}
}
}
private fun allPermissionsGranted(): Boolean {
for (permission in REQUIRED_PERMISSIONS) {
if (ContextCompat.checkSelfPermission(
this, permission
) != PackageManager.PERMISSION_GRANTED
) {
return false
}
}
return true
}
private fun startCamera() {
// Create configuration object for the viewfinder use case
val previewConfig = PreviewConfig.Builder().apply {
setLensFacing(lensFacing)
}.build()
// Build the viewfinder use case
val preview = Preview(previewConfig)
// Create a configuration object for the video use case
val videoCaptureConfig = VideoCaptureConfig.Builder().apply {
setTargetRotation(viewFinder.display.rotation)
setLensFacing(lensFacing)
}.build()
videoCapture = VideoCapture(videoCaptureConfig)
preview.setOnPreviewOutputUpdateListener {
val parent = viewFinder.parent as ViewGroup
parent.removeView(viewFinder)
viewFinder.surfaceTexture = it.surfaceTexture
parent.addView(viewFinder, 0)
}
// Bind use cases to lifecycle
CameraX.bindToLifecycle(this, preview, videoCapture)
}
public final fun changeCamera(view : View) : Unit{
lensFacing = if (CameraX.LensFacing.FRONT == lensFacing) {
CameraX.LensFacing.BACK
} else {
CameraX.LensFacing.FRONT
}
try {
// Only bind use cases if we can query a camera with this orientation
CameraX.getCameraWithLensFacing(lensFacing)
// Unbind all use cases and bind them again with the new lens facing configuration
CameraX.unbindAll()
startCamera()
} catch (exc: Exception) {
// Do nothing
}
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.VideoCaptureActivity">
<TextureView
android:id="@+id/view_finder"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="@+id/capture_button"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="24dp"
android:background="#F44336"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/view_finder"
app:layout_constraintVertical_bias="0.923"
app:srcCompat="@android:drawable/ic_menu_camera" />
<ImageButton
android:id="@+id/switch_button"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:onClick="changeCamera"
android:layout_marginBottom="24dp"
android:background="@color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.024"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/view_finder"
app:layout_constraintVertical_bias="0.923"
app:srcCompat="@android:drawable/ic_menu_revert" />
</androidx.constraintlayout.widget.ConstraintLayout>
我在gradle下面使用过。
def camerax_version = "1.0.0-alpha03"
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"