(一)概述
CameraX 是Jetpack的相机组件,具有强大的参数支持和兼容性,可以实现视频拍摄、预览等操作,且API简单易用。
// cameraX
api 'androidx.camera:camera-core:1.0.0-alpha04'
api 'androidx.camera:camera-camera2:1.0.0-alpha04'
api 'androidx.camera:camera-view:1.0.0-alpha01'
api 'androidx.camera:camera-extensions:1.0.0-alpha01'
// gesture imageview
api 'com.github.chrisbanes:PhotoView:2.3.0@aar'
(二)示例代码
1.初始化相机
private fun bindCameraX() {// 取消绑定生命周期中的所有用例,并将其从CameraX中删除。CameraX.unbindAll()// 检查是否有后置摄像头var hasCameraWithLensFacing = falsetry {hasCameraWithLensFacing = CameraX.hasCameraWithLensFacing(mLensFacing)} catch (e: CameraInfoUnavailableException) {e.printStackTrace()}if (!hasCameraWithLensFacing) {InteractionPresenter.showToast("无设备cameraId!,请检查设备的相机是否被占用")return finish()}// 然后检查后置摄像头是否可用var cameraIdForLensFacing: String? = nulltry {cameraIdForLensFacing = CameraX.getCameraFactory().cameraIdForLensFacing(mLensFacing)} catch (e: CameraInfoUnavailableException) {e.printStackTrace()}if (TextUtils.isEmpty(cameraIdForLensFacing)) {InteractionPresenter.showToast("无可用的设备cameraId!,请检查设备的相机是否被占用")return finish()}// =====================重点=======================//// CameraX 视频预览val config = PreviewConfig.Builder().setLensFacing(mLensFacing) //前后摄像头.setTargetRotation(rotation)//旋转角度.setTargetResolution(resolution) //分辨率.setTargetAspectRatio(rational)//宽高比.build()preview = Preview(config)// 需要设置preview视频流回调事件,和textureview绑定。// 请注意textureview一定还要先移除再添加preview?.setOnPreviewOutputUpdateListener {val tv = binding.textureView(tv.parent as ViewGroup).run {removeView(tv)addView(tv, 0)}tv.setSurfaceTexture(it.surfaceTexture)textureView = tv}// CameraX 点击拍摄照片imageCapture = ImageCapture(ImageCaptureConfig.Builder().setTargetAspectRatio(rational).setTargetResolution(resolution).setLensFacing(mLensFacing).setTargetRotation(rotation).build())// CameraX 视频录制videoCapture = VideoCapture(VideoCaptureConfig.Builder().setTargetRotation(rotation).setLensFacing(mLensFacing).setTargetResolution(resolution).setTargetAspectRatio(rational).setVideoFrameRate(25) // 视频帧率.setBitRate(3 * 1024 * 1024).build()// bit率)// 上面配置的都是我们期望的分辨率val newUseList: MutableList<UseCase> = java.util.ArrayList()newUseList.add(preview!!)newUseList.add(imageCapture!!)newUseList.add(videoCapture!!)// 下面我们要查询一下 当前设备它所支持的分辨率有哪些,然后再更新一下 所配置的几个usecaseval resolutions = CameraX.getSurfaceManager().getSuggestedResolutions(cameraIdForLensFacing, null, newUseList)resolutions.forEach { (useCase, value) ->val suggestedResolutionMap = HashMap<String, Size>()suggestedResolutionMap[cameraIdForLensFacing!!] = valueuseCase.updateSuggestedResolution(suggestedResolutionMap)}// 最后绑定宿主生命周期CameraX.bindToLifecycle(this, preview, imageCapture, videoCapture)
}
2.视频全屏预览:
/*** 预览视频: 视频的全屏预览需要区分本地视频资源&网络视频资源*/
private fun previewVideo(previewUrl: String) {mPreviewBinding.playerView.visibility = View.VISIBLE// 播放器player = ExoPlayerFactory.newSimpleInstance(this,DefaultRenderersFactory(this),DefaultTrackSelector(),DefaultLoadControl())var uri: Uri? = nullval file = File(previewUrl)if (file.exists()) {// 如果是本地视频val dataSpec = DataSpec(Uri.fromFile(file))val fileDataSource = FileDataSource()try {fileDataSource.open(dataSpec)uri = fileDataSource.uri} catch (e: FileDataSourceException) {e.printStackTrace()}} else {// 网络视频uri = Uri.parse(previewUrl)}val factory = ProgressiveMediaSource.Factory(DefaultDataSourceFactory(this, Util.getUserAgent(this,packageName)))val mediaSource = factory.createMediaSource(uri)player?.apply {prepare(mediaSource)// 加载视频playWhenReady = true// 播放视频mPreviewBinding.playerView.player = this// playerView与player绑定}
}
3)图片全屏预览:
<!--图片的全屏预览我们使用PhotoView来实现,
请注意它的scaleType需要设置成fitCenter, 否则宽高可能会被裁减-->
<com.github.chrisbanes.photoview.PhotoViewandroid:id="@+id/photo_view"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center"android:layout_marginTop="90dp"android:layout_marginBottom="@dimen/dp_60"android:scaleType="fitCenter"android:visibility="gone" />
// 预览图片
Glide.with(this).load(previewUrl).into(mPreviewBinding.photoView)