VladislavLysov
VladislavLysov

Reputation: 651

Android Camerax crash on real devices

I started to use CameraX (1.0.8 alpha) library in my Android application and during development on real Samnsung A50 device + emulators all working fine. But when it was release to Play Store - I see a lot of crashes on Pixel 2XL and Nexus 5X devices (I tried my app on emulators for this devices, but all is working fine).

I'm just call bindToLifecle:

Fatal Exception: java.lang.IllegalArgumentException: Can not get supported output size under supported maximum for the format: 34
   at androidx.camera.camera2.internal.SupportedSurfaceCombination.getSupportedOutputSizes(SupportedSurfaceCombination.java:29)
   at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.getSuggestedResolutions(Camera2DeviceSurfaceManager.java:29)
   at androidx.camera.core.CameraX.calculateSuggestedResolutions(CameraX.java:14)
   at androidx.camera.lifecycle.ProcessCameraProvider.bindToLifecycle(ProcessCameraProvider.java)

Does anybody had such issues?

Code for init:

@SuppressLint("RestrictedApi")
private void definePermissionsCallback() {
    allPermissionsCheck = Dexter.withActivity(this)
            .withPermissions(WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA)
            .withListener(new MultiplePermissionsListener() {
                @Override
                public void onPermissionsChecked(MultiplePermissionsReport report) {
                    if (report.areAllPermissionsGranted()) {
                        isFileStoragePermissionGiven = true;
                        isCameraPermissionGiven = true;

                        SharedPreferences sharedPreferences = getSharedPreferences(APPLICATION_SETTINGS, MODE_PRIVATE);
                        sharedPreferences.edit().putBoolean(ALLOW_CAMERA, true).apply();
                        findViewById(R.id.switch_camera).setEnabled(true);

                        cameraProviderFuture = ProcessCameraProvider.getInstance(MainActivity.this);
                        cameraProviderFuture.addListener(() -> {
                            try {
                                cameraProvider = (ProcessCameraProvider) cameraProviderFuture.get();
                                bindPreview();
                            } catch (ExecutionException | InterruptedException e) {
                                Crashlytics.logException(e);
                            }
                        }, ContextCompat.getMainExecutor(MainActivity.this));

                        return;
                    }...


void bindPreview() {
    cameraProvider.unbindAll();
    Preview preview = new Preview.Builder()
            .setTargetName("Preview")
            .build();

    preview.setPreviewSurfaceProvider(previewView.getPreviewSurfaceProvider());

    cameraSelector = new CameraSelector.Builder().requireLensFacing(lensFacing).build();
    cameraProvider.bindToLifecycle(this, cameraSelector, preview);
}

Upvotes: 3

Views: 2773

Answers (5)

Corbie
Corbie

Reputation: 1106

You could use this function (written in Kotlin) to get the possible output sizes:

private fun getOutputSizes(lensFacing: Int = CameraCharacteristics.LENS_FACING_BACK): Array<Size>? {
    val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager

    for (cameraId in manager.cameraIdList) {
        val characteristics = manager.getCameraCharacteristics(cameraId)
        val orientation = characteristics[CameraCharacteristics.LENS_FACING]!!

        if (orientation == lensFacing) {
            val configurationMap = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)!!
            return configurationMap.getOutputSizes(SurfaceTexture::class.java)
        }
    }
    return null
}

And simply try them until one of them is working:

for (outputSize in getOutputSizes()!!) {
    try {
        CameraX.bindToLifecycle(this, qrCodePreview.useCase, qrCodeImageAnalysis.useCase)
        return
    }
    catch (e: IllegalArgumentException) {}
}
TODO("No valid output size found, handle error ...")

Upvotes: 1

konovalov_k
konovalov_k

Reputation: 11

According to official code:

(outputSizeCandidates.isEmpty() && !isDefaultResolutionSupported) {
        throw new IllegalArgumentException(
                "Can not get supported output size for the desired output size quality for "
                        + "the format: "
                        + imageFormat);
    }

I've got the same on device with Legacy Camera Support. Hope it helps to find answer.


UPD: It happened because CameraX lib can't find best resolution to fit Camera output for Display resolution. For example:

Display resolution: 1280x720
Closest supported camera resolution: 1920x720
DispRes < CamRes. Failed! Lib can't properly setup size.

Lib works if display resolution smaller than camera resolution.

For example: Display resolution: 1280x800
Closest supported camera resolution: 1280x720
DispRes > CamRes. Success!

Upvotes: 0

Minhaz
Minhaz

Reputation: 977

This may not answer perfectly and I could be wrong, but give following a try:

The Preview instance you are using to bind to life cycle, has the Builder which allows setting either of target resolution or target aspect ratio with setTargetResoltion or setTargetAspectRation.

It calls out that if not set

If not set, the default selected resolution will be the best size match to the device's screen resolution, or to 1080p (1920x1080), whichever is smaller.

And

If not set, resolutions with aspect ratio 4:3 will be considered in higher priority.

Respectively.

Based on the error message

Can not get supported output size under supported maximum for the format

It looks like it's not able to get the output size that it's trying to find for the default values for certain devices. This is possible as the HAL implementation of the Camera is done by OEMs (like Nokia, Huawei etc) and can have support for different supported size. If you want to look at supported resolutions in a given device you can use this app: Camera2Api Probe

Pointer to how Camera X selects automatic resolution

TL;DR; While the API should provide this support implicitly, considering it in alpha, try to set the Aspect Ratio or the Target Resolution explicitly so it works for most of devices. To make it highly configurable you can query the supported resolution using this api

Note that, I have no link or ownership with the mentioned app Camera2Api, but I used it to query Camera2 information for devices in my job.

Upvotes: 2

easy_breezy
easy_breezy

Reputation: 1113

From the official documentation: "The CameraX library is in alpha stage, as its API surfaces aren't yet finalized. We do not recommend using Alpha libraries in production. Libraries should strictly avoid depending on Alpha libraries in production, as their API surfaces may change in source- and binary-incompatible ways." You can wait for a stable release or use api's of Camera or Camera2.

Upvotes: 0

Nurseyit Tursunkulov
Nurseyit Tursunkulov

Reputation: 9400

Sometimes this happens when you use the old or new version of lib. Try to change it

Upvotes: 0

Related Questions