1.导入CameraX依赖到build.grade(Module:app)
2.CameraX需要Java8中的方法,确定build.grade(Module:app)中是否有以下两个方法
3.在清单中设置相机权限
4.这里使用网上demo,设置layout布局文件
设置一个button和一个Camera.view.PreviewView预览画面
<androidx.camera.view.PreviewView
android:id="@+id/viewFinder"
android:layout_width="match_parent"
android:layout_height="match_parent" />
5.在MainActivity.kt中设置请求权限和实现CameraX预览画面,可成功调用设备权限并展示预览
//初始化定义
private var preview: Preview? = null
private var imageCapture: ImageCapture? = null
private var imageAnalyzer: ImageAnalysis? = null
private var camera: Camera? = null
//权限判断
if (allPermissionsGranted()) {
startCamera()
} else {
ActivityCompat.requestPermissions(
this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)}
//定义图片输出文件位置
outputDirectory = createPhotoAlbum()
//预览
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener(Runnable {
// Used to bind the lifecycle of cameras to the lifecycle owner
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// Preview
preview = Preview.Builder()
.build()
imageCapture = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
.build()
// Select back camera
val cameraSelector = CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build()
try {
// Unbind use cases before rebinding
cameraProvider.unbindAll()
// Bind use cases to camera
camera = cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture)
preview?.setSurfaceProvider(viewFinder.surfaceProvider)
} catch(exc: Exception) {
Timber.d("Use case binding failed==$exc")
}
}, ContextCompat.getMainExecutor(this))
}
//权限设置
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(
baseContext, it) == PackageManager.PERMISSION_GRANTED
}
//权限返回结果
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>, grantResults:
IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
startCamera()
} else {
Toast.makeText(this,
"未获得权限",
Toast.LENGTH_SHORT).show()
finish()
}
}
}
6.拍照与图片存储,页面布局设置一个按钮
<Button
android:id="@+id/camera_capture_button"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="25dp"
android:text="拍照" />
7.在MainActivity.kt中实现拍照和图片存储,可成功实现
//初始化定义输出文件位置
private lateinit var outputDirectory: File
outputDirectory = createPhotoAlbum()
//按钮点击监听事件
camera_capture_button.setOnClickListener { takePhoto() }
private fun takePhoto() {
val imageCapture = imageCapture ?: return
// Create timestamped output file to hold the image
val photoFile = File(
outputDirectory,
SimpleDateFormat(FILENAME_FORMAT, Locale.US
).format(System.currentTimeMillis()) + ".jpg")
Timber.d("photoFile==$photoFile")
// Create output options object which contains file + metadata
val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
// Setup image capture listener which is triggered after photo has
// been taken
imageCapture.takePicture(
outputOptions, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback {
override fun onError(exc: ImageCaptureException) {
Log.e(TAG, "拍照失败: ${exc.message}", exc)
}
override fun onImageSaved(output: ImageCapture.OutputFileResults) {
val savedUri = Uri.fromFile(photoFile)
val msg = "拍照成功,图片存放地址: $savedUri"
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
Log.d(TAG, msg)
}
})
}
//自定义图片存储位置
fun createPhotoAlbum(): File {
val name = "loupeAlbum"
val albumDir = File(Environment.getExternalStorageDirectory(),name)
if (!albumDir.exists()){
albumDir.mkdirs()
}
return albumDir
}
8.实现闪光灯开关,同布局设置按钮,在MainActivity.kt实现
//activity_main.xml
<Button
android:id="@+id/camera_light_button"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:layout_marginLeft="25dp"
android:layout_marginBottom="25dp"
android:text="打开" />
//MainActivity.kt
//初始化定义判断开关参数
private var isOpenFlash = true
//按钮监听事件
camera_light_button.setOnClickListener{ toggleTorch() }
//闪光灯开关方法
private fun toggleTorch() {
if (isOpenFlash){
camera_light_button.text = "close"
}else{
camera_light_button.text = "open"
}
camera?.cameraControl?.enableTorch(isOpenFlash)
isOpenFlash = !isOpenFlash
}
9.实现进度条SeekBar调节设备亮度,同布局设置控件,在MainActivity.kt实现
//activity_main.xml
<TextView
android:layout_above="@+id/camera_capture_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="亮度"
android:textSize="20dp" />
<SeekBar
android:layout_above="@+id/camera_capture_button"
android:id="@+id/camera_seekbar_light"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_centerHorizontal="true"
android:max="255"/>
//MainActivity.kt
//获取设备当前亮度值
camera_seekbar_light.progress = Settings.System.getInt(
contentResolver,
Settings.System.SCREEN_BRIGHTNESS)
//亮度进度条监听事件
camera_seekbar_light.setOnSeekBarChangeListener(object : OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { changeP(progress.toFloat() / 255)}
override fun onStartTrackingTouch(seekBar: SeekBar) {}
override fun onStopTrackingTouch(seekBar: SeekBar) {}
})
//调节亮度方法
private fun changeP(f: Float) {
val param = window.attributes
param.screenBrightness = f
window.attributes = param
}