10

从更新后

androidx.camera:camera-core:1.0.0-alpha03

androidx.camera:camera-core:1.0.0-alpha06

方法 setTargetAspectRatio(在 ImageCaptureConfig.Builder 中)和 takePicture(在 ImageCapture 中)的签名已更改。

Web 中的官方文档和信息没有显示如何使用新方法(如何指定执行程序)。

更新后损坏的代码:

...
val captureConfig = ImageCaptureConfig.Builder()
    .setTargetAspectRatioCustom(Rational(1, 1)) //this method changed
    .setFlashMode(flashMode)
    .setLensFacing(lensFacing)
    .build()

val capture = ImageCapture(captureConfig)

binding.takeAPhoto.setOnClickListener {
    ...
    val imageFile = createTempFile(System.currentTimeMillis().toString(), ".jpg")
    capture.takePicture(imageFile, object : ImageCapture.OnImageSavedListener { //this method also changed

        override fun onImageSaved(file: File) {
            ...
        }

        override fun onError(useCaseError: ImageCapture.UseCaseError, message: String, cause: Throwable?) {
            ...
        })
    }
}

有没有人有(或知道在哪里可以找到)如何使用新方法的示例?提前致谢

4

7 回答 7

11

最近显然已经更新的官方 Google Codelabs 使用:Executors.newSingleThreadExecutor()

参考:https ://codelabs.developers.google.com/codelabs/camerax-getting-started/#4

编辑:由于@kos的回复对我来说也很有意义,所以我添加了这两个官方 Android 文档参考:

https://developer.android.com/reference/java/util/concurrent/Executors.html#newSingleThreadExecutor()

https://developer.android.com/reference/java/util/concurrent/Executors.html#newCachedThreadPool()

这样,本主题的每个读者都可以就执行者做出自己的决定。

进一步编辑:自 1.0.0-alpha07 以来,API 发生了重要变化,因此我研究了一些文档。有一个 GitHub 示例显示执行器检索,如下所示mainExecutor = ContextCompat.getMainExecutor(requireContext())来源

如果你们中的一些人已经实现了 CameraX 并且运行良好,我肯定会等待 Android发行说明所推荐的 beta 版本

于 2019-10-25T08:00:54.323 回答
1

我面临着和你一样的事情。我从我这边解决了。

class MainActivity : AppCompatActivity(), Executor {
    private var right: Int = 0
    private var bottom: Int = 0
    private var left: Int = 0
    private var top: Int = 0
    private lateinit var preview: Preview
    private val REQUEST_CODE_PERMISSIONS = 10
    private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
    private lateinit var imageCapture: ImageCapture
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        if (allPermissionsGranted()) {
            viewFinder.post { startCamera() }
        } else {
            ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
        }

        viewFinder.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
            updateTransform()
        }

        buttonPlus.setOnClickListener {
            if (right < 100) {
                right += 100
                bottom += 100
                left += 100
                top += 100
                val my = Rect(left, top, right, bottom)
                preview.zoom(my)
            }
        }

        buttonMinus.setOnClickListener {
            if (right > 0) {
                right -= 100
                bottom -= 100
                left -= 100
                top -= 100
                val my = Rect(left, top, right, bottom)
                preview.zoom(my)
            }
        }
    }

    @SuppressLint("RestrictedApi")
    private fun startCamera() {
        val metrics = DisplayMetrics().also { viewFinder.display.getRealMetrics(it) }
        val screenAspectRatio = Rational(metrics.widthPixels, metrics.heightPixels)
        val previewConfig = PreviewConfig.Builder().apply {
            setTargetAspectRatioCustom(screenAspectRatio)
            setTargetRotation(viewFinder.display.rotation)
        }.build()
        preview = Preview(previewConfig)
        preview.setOnPreviewOutputUpdateListener {
            val parent = viewFinder.parent as ViewGroup
            parent.removeView(viewFinder)
            parent.addView(viewFinder, 0)
            viewFinder.surfaceTexture = it.surfaceTexture
            updateTransform()
        }
        CameraX.bindToLifecycle(this, preview)

        captureImage()
    }

    @SuppressLint("RestrictedApi")
    private fun captureImage() {
        val imageCaptureConfig = ImageCaptureConfig.Builder()
                .apply {
                    setTargetAspectRatioCustom(Rational(1, 1))
                    setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)
                }.build()
        imageCapture = ImageCapture(imageCaptureConfig)
        CameraX.bindToLifecycle(this, imageCapture)
        capture_button.setOnClickListener {
            val file = File(this.externalMediaDirs.first(), "${System.currentTimeMillis()}.jpg")
            imageCapture.takePicture(file, this, object : ImageCapture.OnImageSavedListener {
                override fun onImageSaved(file: File) {
                    val msg = "Photo capture succeeded: ${file.absolutePath}"
                    Log.d("CameraXApp", msg)
                }

                override fun onError(imageCaptureError: ImageCapture.ImageCaptureError, message: String, cause: Throwable?) {
                    val msg = "Photo capture failed: $message"
                    Log.e("CameraXApp", msg)
                    cause?.printStackTrace()
                }
            })
        }
    }

    override fun execute(command: Runnable) {
        command.run()
    }

    private fun updateTransform() {
        val matrix = Matrix()
        val centerX = viewFinder.width / 2f
        val centerY = viewFinder.height / 2f
        val rotationDegrees = when (viewFinder.display.rotation) {
            Surface.ROTATION_0 -> 0
            Surface.ROTATION_90 -> 90
            Surface.ROTATION_180 -> 180
            Surface.ROTATION_270 -> 270
            else -> return
        }
        matrix.postRotate(-rotationDegrees.toFloat(), centerX, centerY)
        viewFinder.setTransform(matrix)
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
        if (requestCode == REQUEST_CODE_PERMISSIONS) {
            if (allPermissionsGranted()) {
                viewFinder.post { startCamera() }
            } else {
                Toast.makeText(this, "Permissions not granted by the user.", Toast.LENGTH_SHORT).show()
                finish()
            }
        }
    }

    private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
        ContextCompat.checkSelfPermission(baseContext, it) == PackageManager.PERMISSION_GRANTED
    }


    override fun onDestroy() {
        super.onDestroy()
        imageCapture.let {
            CameraX.unbind(imageCapture)
        }
    }
}

输出是(当我打印登录onImageSaved方法时)

Photo capture succeeded: /storage/emulated/0/Android/media/com.akshay.cameraxzoominoutdemo/1571052301192.jpg

对我来说效果很好,试试这个。

于 2019-10-14T11:27:24.160 回答
1

你可以这样做。

imageCapture.takePicture(file, { it.run() }, object : ImageCapture.OnImageSavedListener {
    override fun onImageSaved(file: File) {}
    override fun onError(useCaseError: ImageCapture.ImageCaptureError, message: String, cause: Throwable?) {}
})
于 2019-10-15T07:50:28.143 回答
0

这是 alpha06 更改的更改日志:https ://developer.android.com/jetpack/androidx/releases/camera

  • setTargetAspectRatio()方法现在采用带有或值的AspectRatio枚举。4_316_9
  • takePicture()方法采用(file, metadata, executor, imageSavedListener)// 可以根据您的情况/需要使用执行器。例子是val executor = Executors.newSingleThreadExecutor()
  • 而不是useCase.onPreviewOutputUpdateListener =使用useCase.setOnPreviewOutputUpdateListener()

仅供参考:CameraX 将于 2019 年 12 月进入 Beta 版

于 2019-10-29T09:24:38.770 回答
0

在您的点击侦听器中调用此函数/方法:

    private fun saveImage(){

        val file = File(this.externalMediaDirs.first(), "${System.currentTimeMillis()}.jpg")
        val fileB = ImageCapture.OutputFileOptions.Builder(file).build()

        imageCapture.takePicture(fileB, ContextCompat.getMainExecutor(this), object : ImageCapture.OnImageSavedCallback {
            override fun onImageSaved(fileB: ImageCapture.OutputFileResults) {
                val msg = "${fileB.savedUri} - ${file.absolutePath} - ${file.toURI()}"
            }

            override fun onError(imageCaptureError: ImageCaptureException) {
                val msg = "Photo capture failed: ${imageCaptureError.toString()}"
            }
        })
    }

msgin 将onImageSaved包含如下内容:

null - /storage/emulated/0/Android/media/com.mua.camx/1607589430984.jpg - file:/storage/emulated/0/Android/media/com.mua.camx/1607589430984.jpg
于 2020-12-10T08:22:21.560 回答
-1

您只需运行以下命令。

@Override
public void execute(Runnable command) {
    command.run(); // <-- THIS IS NEEDED
}
于 2019-11-24T11:19:47.557 回答
-2

CameraX 提供了内置的执行器,拍照可以实现如下:

imgCaptureButton.setOnClickListener(new View.OnClickListener() {
    @Override
    @SuppressLint("RestrictedApi")
    public void onClick(View v) {
        imgCap.takePicture(CameraXExecutors.mainThreadExecutor(),new ImageCapture.OnImageCapturedListener() {
            @Override
            public void onCaptureSuccess(ImageProxy image, int rotationDegrees) {
                super.onCaptureSuccess(image, rotationDegrees);

                // Play with the Image here.
            }
        });
    }
});

它不使用 File 来保存图像,而是将图像作为缓冲区保存在内存中。

于 2019-10-20T09:48:09.030 回答