前言
kotlin使用CameraX实现录制视频 实现效果: 录制视频,点击对焦,录制完成后在手机相册中即可找到录制的视频
一、添加依赖
包括camerax的依赖自身和用于权限申请的permissionx依赖 camerax自身依赖可以在官方文档中查阅最新版本
def camerax_version = "1.2.0-alpha02"
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
implementation "androidx.camera:camera-video:${camerax_version}"
implementation "androidx.camera:camera-view:${camerax_version}"
implementation "androidx.camera:camera-mlkit-vision:${camerax_version}"
implementation "androidx.camera:camera-extensions:${camerax_version}"
implementation 'com.guolindev.permissionx:permissionx:1.6.4'
二、权限申请
1.Manifest配置文件中
代码如下(示例):
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> <!-- 摄像头权限 -->
<uses-permission android:name="android.permission.CAMERA" /> <!-- 具备摄像头 -->
<uses-feature android:name="android.hardware.camera.any" /> <!-- 存储图像或者视频权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- 录制音频权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
这里若需要读取相册中的文件进行上传等操作时需要在application中添加:
android:requestLegacyExternalStorage="true"
2.Activity中动态申请权限
代码如下(示例):
PermissionX.init(this).permissions(
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO)
.request{ allGranted, deniedList, _ ->
if(allGranted){
setUpCamera( binding.previewView )
listener()
}
else{
Toast.makeText(this," You denied ${deniedList}", Toast.LENGTH_SHORT).show()
}
}
这里使用的viewBinding进行的布局绑定binding.previewView即为布局文件中的预览控件
3.布局文件
主要是PreviewView用以相机预览
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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=".MainActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbarvideo"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:background="@color/colorPrimary"
app:layout_collapseMode="pin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="25dp"
android:text="录制视频">
</TextView>
</androidx.appcompat.widget.Toolbar>
<androidx.camera.view.PreviewView
android:id="@+id/previewView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/toolbarvideo" />
<ImageView
android:id="@+id/recording"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@drawable/start"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:foreground="?android:attr/selectableItemBackground"/>
</RelativeLayout>
三、功能实现
1.预览
setUpCamera函数具体实现
private fun setUpCamera(previewView: PreviewView) {
val camerProviderFuture : ListenableFuture<ProcessCameraProvider> =
ProcessCameraProvider.getInstance(this)
camerProviderFuture.addListener({
try {
cameraProvider = camerProviderFuture.get()
bindPreview(cameraProvider, previewView)
}catch (e: Exception){
e.printStackTrace()
}
}, ContextCompat.getMainExecutor(this))
}
@SuppressLint("RestrictedApi")
private fun bindPreview(
cameraProvider: ProcessCameraProvider,
previewView: PreviewView)
{
cameraProvider.unbindAll()
preview = Preview.Builder().build()
videoCapture = VideoCapture.Builder()
.setVideoFrameRate(25)
.setBitRate(3*1024*1024)
.build()
camera = cameraProvider.bindToLifecycle(
this,
CameraSelector.DEFAULT_BACK_CAMERA, preview, videoCapture
)
preview?.setSurfaceProvider(previewView.surfaceProvider)
}
2.录制
oncreate()中添加监听事件
binding.recording.setOnClickListener {
if(!inRecording){
startRecording()
inRecording = true
binding.recording.setImageResource(R.drawable.stop)
}else{
videoCapture?.stopRecording()
binding.recording.setImageResource(R.drawable.start)
inRecording = false
}
}
startRecording函数实现
@SuppressLint("RestrictedApi", "MissingPermission")
private fun startRecording(){
val contentValues = ContentValues()
contentValues.put(
MediaStore.MediaColumns.DISPLAY_NAME,
RECORDED_FILE_NAME+"_"+System.currentTimeMillis()
)
contentValues.put(MediaStore.MediaColumns.MIME_TYPE,RECORDED_FILE_NAME_END)
val outputFileOptions = VideoCapture.OutputFileOptions.Builder(
contentResolver,
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues
).build()
videoCapture?.startRecording(
outputFileOptions,
ContextCompat.getMainExecutor(this),
object : VideoCapture.OnVideoSavedCallback{
override fun onVideoSaved(outputFileResults: VideoCapture.OutputFileResults) {
val proj = arrayOf(MediaStore.Images.Media.DATA)
val actualimagecursor = managedQuery(outputFileResults.savedUri, proj, null, null, null)
val actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(
MediaStore.Images.Media.DATA);
actualimagecursor.moveToFirst();
val img_path = actualimagecursor.getString(actual_image_column_index);
Log.i("TAG", "视频路径: " + img_path);
Log.i("TAG", "视频保存成功: ${outputFileResults.savedUri}")
}
override fun onError(videoCaptureError: Int, message: String, cause: Throwable?) {
Log.i("TAG", "出现异常 cause:$cause")
}
}
)
}
2.对焦功能(附加)
添加监听事件
binding.previewView.setOnTouchListener { view , event ->
val action = FocusMeteringAction.Builder(
binding.previewView.meteringPointFactory.createPoint(event.x, event.y)
).build();
showTapView(event.x.toInt(), event.y.toInt())
camera?.cameraControl?.startFocusAndMetering((action))
true
}
showTapView函数实现
private fun showTapView( x:Int, y:Int ) {
val popupWindow = PopupWindow(
100,
100
)
val imageView = ImageView(this)
imageView.setImageResource(R.drawable.ic_focus_view)
popupWindow.contentView = imageView
popupWindow.showAsDropDown(binding.previewView, x,y)
binding.previewView.postDelayed({popupWindow.dismiss()}, 600)
binding.previewView.playSoundEffect(SoundEffectConstants.CLICK)
}
总结
现在就可以实现点击imageview录制再次点击结束录制,并可在相册中看到录制的视频
|