Search code examples
javaandroidkotlinconstructor

Android - Cannot access constructor of ResolutionStrategy


I'm creating an app that uses Google ML Kit to detect a human face on an image and draw a rectangle around it. The camera preview is provided by the CameraX (androidx.camera) library. Inspiration was taken from this question. Here is the problematic fragment of a code:

@OptIn(ExperimentalGetImage::class)
private fun startCamera(deviceSize: Pair<Float, Float>) {
    val cameraProviderFuture = ProcessCameraProvider.getInstance(this)

    cameraProviderFuture.addListener({
        val cameraProvider = cameraProviderFuture.get()
        val preview = Preview.Builder().build().also {
            it.surfaceProvider = PreviewView(this).surfaceProvider
        }

        val size = Size(deviceSize.first, deviceSize.second)

        val strategy = ResolutionStrategy(deviceSize, 2)

        val rs = ResolutionSelector.Builder().setResolutionStrategy(strategy)

        val imageAnalysis = ImageAnalysis.Builder()
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .setResolutionSelector(rs.build())
            .build()

        imageAnalysis.setAnalyzer(cameraExecutor) { imageProxy ->
             val rotationDegrees = imageProxy.imageInfo.rotationDegrees
             val mediaImage = imageProxy.image

             if (mediaImage != null) {
                val inputImage = InputImage.fromMediaImage(mediaImage, rotationDegrees)

                detectFaces(inputImage) { faces ->
                    drawRectangles(faces)
                    imageProxy.close()
                }
            } else {
                imageProxy.close()
            }
        }

        val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA

        try {
            cameraProvider.unbindAll()
            cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageAnalysis)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }, ContextCompat.getMainExecutor(this))
}

The only error shown by the IDE (Android Studio Ladybug 2024.2.1 Patch 3) is
"Cannot access 'constructor(): ResolutionStrategy': it is private in 'androidx/camera/core/resolutionselector/ResolutionStrategy'"
This seems very strange to me as there is a public constructor documented on the Android Developer Website and I can also navigate to the same public constructor by clicking Go To > Declaration. However when I hover over the constructor used by strategy, the IDE shows the private constructor. Why does it happen and how to fix it?

Edit: I found out that AspectRatioStrategy, which is very similar to ResolutionStrategy and can also be passed to the ResolutionSelector, is usable in my scenario:

val asp = AspectRatioStrategy(AspectRatio.RATIO_DEFAULT, 1) // no error

I hadn't also mentioned what's the deal about the resolution modification - the rectangles around the detected faces' bounding boxes are displayed but not in the correct ratio (printing mediaImage dimensions yields 640x480).


Solution

  • I found out that this error is actually a problem with IDE or project structure (I'm not really sure). I found out that the ResolutionStrategy constructor is only available in Java Classes, so I can use it like this:

    public class CameraUtils {
    
        public static ResolutionStrategy createStrategy(Size deviceSize) {
    
            return new ResolutionStrategy(deviceSize, ResolutionStrategy.FALLBACK_RULE_CLOSEST_HIGHER_THEN_LOWER);
        }
        public static ResolutionSelector createSelector(Size deviceSize) {
            return new ResolutionSelector.Builder().setResolutionStrategy(createStrategy(deviceSize)).build();
        }
    }
    

    And then call the helper class from my Kotlin code:

    val camera = LifecycleCameraController(this)
    camera.imageAnalysisBackpressureStrategy = ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST
    camera.imageAnalysisResolutionSelector = CameraUtils.createSelector(Size(width, height))