import
android.Manifest
import
android.content.pm.PackageManager
import
android.net.Uri
import
android.os.Bundle
import
android.util.Log
import
android.view.View
import
android.widget.Button
import
android.widget.ImageView
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
kotlinx.android.synthetic.main.activity_main.*
import
java.io.File
import
java.text.SimpleDateFormat
import
java.util.*
import
java.util.concurrent.ExecutorService
import
java.util.concurrent.Executors
class
MainActivity : AppCompatActivity() {
private
var imageCapture: ImageCapture? =
null
private
lateinit var outputDirectory: File
private
lateinit var cameraExecutor: ExecutorService
override fun onCreate(savedInstanceState: Bundle?) {
super
.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
supportActionBar?.hide()
if
(allPermissionsGranted()) {
startCamera()
}
else
{
ActivityCompat.requestPermissions(
this
, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
}
findViewById<Button>(R.id.camera_capture_button).setOnClickListener {
takePhoto()
}
outputDirectory = getOutputDirectory()
cameraExecutor = Executors.newSingleThreadExecutor()
}
private
fun takePhoto() {
val imageCapture = imageCapture ?:
return
val photoFile = File(
outputDirectory,
SimpleDateFormat(FILENAME_FORMAT, Locale.US).format(System.currentTimeMillis()) +
".jpg"
)
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)
findViewById<ImageView>(R.id.iv_capture).visibility = View.VISIBLE
findViewById<ImageView>(R.id.iv_capture).setImageURI(savedUri)
val msg =
"Photo capture succeeded: $savedUri"
Toast.makeText(baseContext, msg, Toast.LENGTH_LONG).show()
Log.d(TAG, msg)
}
})
}
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 allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
}
private
fun getOutputDirectory(): File {
val mediaDir = externalMediaDirs.firstOrNull()?.let {
File(it, resources.getString(R.string.app_name)).apply { mkdirs() }
}
return
if
(mediaDir !=
null
&& mediaDir.exists())
mediaDir
else
filesDir
}
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>, grantResults:
IntArray
) {
if
(requestCode == REQUEST_CODE_PERMISSIONS) {
if
(allPermissionsGranted()) {
startCamera()
}
else
{
Toast.makeText(
this
,
"Permissions not granted by the user."
, Toast.LENGTH_SHORT).show()
finish()
}
}
}
companion object {
private
const
val TAG =
"CameraXGFG"
private
const
val FILENAME_FORMAT =
"yyyy-MM-dd-HH-mm-ss-SSS"
private
const
val REQUEST_CODE_PERMISSIONS =
20
private
val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
}
override fun onDestroy() {
super
.onDestroy()
cameraExecutor.shutdown()
}
}