android - 获得相机权限后不显示预览
问题描述
我正在尝试读取 QR 码,当我在与我授予权限的运行不同的运行中加载此逻辑时,一切都很好
但是,当我想在权限运行期间执行此操作时,预览不会加载。我发现一些 SO 帖子说在您获得许可后加载 ui,但这也不起作用。
private fun startCamera() {
val previewConfig = PreviewConfig.Builder()
// We want to show input from back camera of the device
.setLensFacing(CameraX.LensFacing.BACK).build()
val preview = Preview(previewConfig)
preview.setOnPreviewOutputUpdateListener { previewOutput ->
textureView.surfaceTexture = previewOutput.surfaceTexture
}
val imageAnalysisConfig = ImageAnalysisConfig.Builder().build()
val imageAnalysis = ImageAnalysis(imageAnalysisConfig)
val qrCodeAnalyzer = QRCodeAnalyzer { qrCodes ->
qrCodes.forEach {
if (!TextUtils.isEmpty(it.rawValue)) {
previewAction?.onQRCodeResult(it.rawValue)
}
}
}
context?.let {
imageAnalysis.setAnalyzer(it.getExecutor(), qrCodeAnalyzer)
}
// We need to bind preview and imageAnalysis use cases
CameraX.bindToLifecycle(this as LifecycleOwner, preview, imageAnalysis)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
startCamera()
}
我错过了什么?
解决方案
下面是我的工作代码,您可以参考
fragment_camera.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextureView
android:id="@+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_capture_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:src="@drawable/ic_camera"
app:fabSize="auto"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:tint="@android:color/white" />
</androidx.constraintlayout.widget.ConstraintLayout>
相机片段.kt
package com.hardik.demos
import android.Manifest
import android.content.pm.PackageManager
import android.graphics.Matrix
import android.os.Bundle
import android.util.DisplayMetrics
import android.util.Rational
import android.util.Size
import android.view.*
import android.widget.Toast
import androidx.camera.core.*
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.fragment_camera.*
import java.io.File
/**
* A simple [Fragment] subclass.
*/
private const val REQUEST_CODE_CAMERA_PERMISSION = 101
private val PERMISSION_LIST = arrayOf(Manifest.permission.CAMERA)
class CameraFragment : Fragment() {
private lateinit var cameraPreview: TextureView
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_camera, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
cameraPreview = view.findViewById(R.id.camera_preview)
}
override fun onResume() {
super.onResume()
initCamera()
}
private fun initCamera() {
if (isAllPermissionGranted()) {
cameraPreview.post { startCamera() }
} else {
ActivityCompat.requestPermissions(
requireActivity(), PERMISSION_LIST,
REQUEST_CODE_CAMERA_PERMISSION
)
}
}
private fun startCamera() {
cameraPreview.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> updateCameraBuffer() }
val metrics = DisplayMetrics().also { cameraPreview.display.getRealMetrics(it) }
val screenSize = Size(metrics.widthPixels, metrics.heightPixels)
val screenAspectRatio = Rational(metrics.widthPixels, metrics.heightPixels)
//Setup preview config
val previewConfig = PreviewConfig.Builder().apply {
setLensFacing(CameraX.LensFacing.FRONT)
setTargetResolution(screenSize)
setTargetAspectRatio(screenAspectRatio)
setTargetRotation(requireActivity().windowManager.defaultDisplay.rotation)
setTargetRotation(cameraPreview.display.rotation)
}.build()
val preview = Preview(previewConfig)
//Update Preview as per config
preview.setOnPreviewOutputUpdateListener {
cameraPreview.surfaceTexture = it.surfaceTexture
updateCameraBuffer()
}
//Setup camera photo capture
val imageConfig = ImageCaptureConfig.Builder().apply {
setLensFacing(CameraX.LensFacing.FRONT)
setTargetAspectRatio(screenAspectRatio)
setTargetRotation(cameraPreview.display.rotation)
setCaptureMode(ImageCapture.CaptureMode.MIN_LATENCY)
}.build()
val imageCapture = ImageCapture(imageConfig)
fab_capture_photo.setOnClickListener {
val imageFile = File(
requireContext().getExternalFilesDir(null),
"${System.currentTimeMillis()}.jpg"
)
imageCapture.takePicture(imageFile,
object : ImageCapture.OnImageSavedListener {
override fun onImageSaved(file: File) {
val msg = "Photo capture Success"
Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show()
}
override fun onError(
imageCaptureError: ImageCapture.ImageCaptureError,
message: String,
cause: Throwable?
) {
val msg = "Photo capture failed: $message"
Toast.makeText(requireContext(), msg, Toast.LENGTH_SHORT).show()
}
})
}
CameraX.bindToLifecycle(viewLifecycleOwner, preview, imageCapture)
}
private fun updateCameraBuffer() {
val matrix = Matrix()
//find camera center
val centerX = cameraPreview.width / 2f
val centerY = cameraPreview.height / 2f
//Correct orientation
val rotateAt = when (cameraPreview.display.rotation) {
Surface.ROTATION_0 -> 0
Surface.ROTATION_90 -> 90
Surface.ROTATION_180 -> 180
Surface.ROTATION_270 -> 270
else -> return
}
matrix.postRotate(-rotateAt.toFloat(), centerX, centerY)
cameraPreview.setTransform(matrix)
}
private fun isAllPermissionGranted() = PERMISSION_LIST.all {
ContextCompat.checkSelfPermission(requireContext(), it) == PackageManager.PERMISSION_GRANTED
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == REQUEST_CODE_CAMERA_PERMISSION) {
if (isAllPermissionGranted()) {
initCamera()
} else {
Toast.makeText(
requireContext(),
"Permissions not granted by the user.",
Toast.LENGTH_LONG
).show()
}
}
}
}
让我知道寻求帮助
推荐阅读
- python - discord.py:在启动时运行命令
- c - AddressSanitizer:堆栈使用后范围
- python - 在Python中同时从列表中获取随机值及其位置
- c++ - Codeblocks 20.3 和 minGW_x64_Win_Build 之间有什么问题?
- javascript - Angular - 如何动态下载 Json 文件
- css - Django + Svelte 样式不起作用,MIME 类型('text/html')不是受支持的样式表 MIME 类型
- python - 为什么 numpy 数组比带有 for 循环的列表慢?
- flutter - 在第二页执行之前调用的回调函数
- powershell - 如何将 Powershell CanonicalName 格式化为单独的列?
- python - 为什么我不能在 tkinter 中使用 get 属性?