package com.yeyupiaoling.cameraxapp
import android.Manifest
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import com.blankj.utilcode.util.PathUtils
import kotlinx.android.synthetic.main.activity_main.*
import java.io.File
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
class MainActivity : AppCompatActivity() {
private var imageCapture: ImageCapture? = null
private lateinit var cameraExecutor: ExecutorService
companion object {
private const val TAG = "MainActivity"
private const val REQUEST_CODE_PERMISSIONS = 10
private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 请求权限 if (allPermissionsGranted()) {
startCamera()
} else {
ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
}
// 点击拍照 camera_capture_button.setOnClickListener { takePhoto() }
cameraExecutor = Executors.newSingleThreadExecutor()
}
// 启动相机 private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
cameraProviderFuture.addListener(Runnable {
// 绑定生命周期 val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
// 预览 val preview = Preview.Builder()
.build()
.also {
it.setSurfaceProvider(viewFinder.createSurfaceProvider())
}
imageCapture = ImageCapture.Builder().build()
// 使用后摄像头 val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
// 在重新绑定之前取消绑定用例 cameraProvider.unbindAll()
// 将用例绑定到摄像机 cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture)
} catch (exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
}, ContextCompat.getMainExecutor(this))
}
// 拍照 private fun takePhoto() {
// 保证相机可用 val imageCapture = imageCapture ?: return
// 保存路径 val photoFile = File(PathUtils.getExternalAppPicturesPath(), "" + System.currentTimeMillis() + ".jpg")
// 创建包含文件和metadata的输出选项对象 val outputOptions = ImageCapture.OutputFileOptions.Builder(photoFile).build()
// 设置图像捕获监听器,在拍照后触发 imageCapture.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 savedUri = Uri.fromFile(photoFile)
val msg = "拍照成功,保存路径: $savedUri"
Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
Log.d(TAG, msg)
}
})
}
override fun onDestroy() {
super.onDestroy()
cameraExecutor.shutdown()
}
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
startCamera()
} else {
Toast.makeText(this, "没有授权!", Toast.LENGTH_SHORT).show()
finish()
}
}
}
}