Код: Выделить всё
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
previewView = binding.scannerPreviewView
scannerProgressBar = binding.scannerProgressBar
scannerTextView = binding.scannerTextView
previewView.previewStreamState.observe(viewLifecycleOwner) { state ->
when (state) {
PreviewView.StreamState.IDLE -> {
scannerProgressBar.visibility = View.VISIBLE
scannerTextView.visibility = View.GONE
}
PreviewView.StreamState.STREAMING -> {
scannerProgressBar.visibility = View.GONE
scannerTextView.visibility = View.VISIBLE
}
}
}
startCamera()
}
< /code>
и навигация на сам сканер, и, к сожалению, он также просто отображает черный экран. < /p>
Только когда я перевел разрешения с MainActivty в фрагмент, что камера запускается, когда я ввожу его во второй раз. Сканер начинается только после второго вызова. < /P>
abstract class QrScannerGenericFragment : Fragment() {
// UI
private lateinit var previewView: PreviewView
private lateinit var scannerProgressBar: ProgressBar
private lateinit var scannerTextView: TextView
// CAMERA
private val requestCameraPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
// Permission was granted – proceed to open camera
startCamera()
} else {
// Permission denied – show a message or disable camera functionality
}
}
private lateinit var cameraProvider: ProcessCameraProvider
private lateinit var analysisUseCase: ImageAnalysis
private var rgbaBitmap: Bitmap? = null
private val cameraExecutor by lazy { Executors.newSingleThreadExecutor() }
private val scanner by lazy {
val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(Barcode.FORMAT_QR_CODE)
.build()
BarcodeScanning.getClient(options)
}
// HELPERS
private var scanned = false
// private var cameraPermissionHelper: CameraPermissionHelper? = null
private var infoListener: InfoListener? = null
// BINDING
private var _binding: FragmentQrScannerBinding? = null
private val binding get() = _binding!!
override fun onAttach(context: Context) {
super.onAttach(context)
if (context is InfoListener) {
infoListener = context
} else {
throw RuntimeException("$context must implement InfoListener")
}
}
override fun onCreateView(
inflater: LayoutInflater,
parent: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentQrScannerBinding.inflate(inflater, parent, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
previewView = binding.scannerPreviewView
scannerProgressBar = binding.scannerProgressBar
scannerTextView = binding.scannerTextView
previewView.previewStreamState.observe(viewLifecycleOwner) { state ->
when (state) {
PreviewView.StreamState.IDLE -> {
scannerProgressBar.visibility = View.VISIBLE
scannerTextView.visibility = View.GONE
}
PreviewView.StreamState.STREAMING -> {
scannerProgressBar.visibility = View.GONE
scannerTextView.visibility = View.VISIBLE
}
}
}
view.post { checkAndRequestCameraPermission() }
}
private fun checkAndRequestCameraPermission() {
context?.let { ctx ->
when {
// 2a. If permission is already granted, just open the camera
ContextCompat.checkSelfPermission(ctx, Manifest.permission.CAMERA) ==
PackageManager.PERMISSION_GRANTED -> {
startCamera()
}
// 2c. Otherwise, directly request the permission
else -> {
requestCameraPermissionLauncher.launch(Manifest.permission.CAMERA)
}
}
}
}
private fun startCamera() {
scannerProgressBar.visibility = View.VISIBLE
val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())
cameraProviderFuture.addListener({
cameraProvider = cameraProviderFuture.get()
val previewUseCase = Preview.Builder()
.build()
.also { it.setSurfaceProvider(previewView.surfaceProvider) }
analysisUseCase = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888)
.build()
.also { useCase ->
useCase.setAnalyzer(cameraExecutor) { imageProxy ->
processImageProxy(imageProxy)
}
}
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
cameraProvider.unbindAll()
cameraProvider.bindToLifecycle(
viewLifecycleOwner,
cameraSelector,
previewUseCase,
analysisUseCase
)
}, ContextCompat.getMainExecutor(requireContext()))
}
private fun processImageProxy(imageProxy: ImageProxy) {
try {
val width = imageProxy.width
val height = imageProxy.height
if (rgbaBitmap == null
|| rgbaBitmap?.width != width
|| rgbaBitmap?.height != height
) {
rgbaBitmap?.recycle()
rgbaBitmap = createBitmap(width, height)
}
val buffer = imageProxy.planes[0].buffer
buffer.rewind()
rgbaBitmap!!.copyPixelsFromBuffer(buffer)
val inputImage =
InputImage.fromBitmap(rgbaBitmap!!, imageProxy.imageInfo.rotationDegrees)
scanner.process(inputImage)
.addOnSuccessListener { barcodes ->
if (!scanned) {
barcodes.firstOrNull()?.rawValue?.let { value ->
scanned = true
requireActivity().runOnUiThread {
onQrcodeDetected(value)
}
}
}
}
.addOnFailureListener { e ->
Log.e(LOGCAT_TAG, "Błąd skanowania", e)
}
} catch (e: Exception) {
Log.e(LOGCAT_TAG, "Error processing imageProxy", e)
} finally {
imageProxy.close()
}
}
override fun onResume() {
super.onResume()
scanned = false
}
override fun onStop() {
if (::cameraProvider.isInitialized) {
cameraProvider.unbindAll()
}
super.onStop()
}
override fun onDestroyView() {
super.onDestroyView()
if (::cameraProvider.isInitialized) {
cameraProvider.unbindAll()
}
cameraExecutor.shutdown()
scanner.close()
rgbaBitmap?.run {
if (!isRecycled) recycle()
}
rgbaBitmap = null
_binding = null
}
protected abstract fun onQrcodeDetected(value: String)
companion object {
private const val LOGCAT_TAG = "TagDebug"
}
}
Подробнее здесь: https://stackoverflow.com/questions/796 ... s-no-surfa