Android Camerax 在真实设备上崩溃

Posted

技术标签:

【中文标题】Android Camerax 在真实设备上崩溃【英文标题】:Android Camerax crash on real devices 【发布时间】:2020-04-23 03:19:34 【问题描述】:

我开始在我的 android 应用程序中使用 CameraX (1.0.8 alpha) 库,并且在真正的三星 A50 设备 + 模拟器上进行开发期间一切正常。但是当它发布到 Play 商店时 - 我在 Pixel 2XLNexus 5X 设备上看到了很多崩溃(我在此设备的模拟器上尝试了我的应用程序,但一切都是工作正常)。

我只是调用 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)

有人遇到过这样的问题吗?

初始化代码:

@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);

【问题讨论】:

请分享您用于设置相机的代码。有两点需要注意: 1. 所有设备对不同格式支持的分辨率都有不同的支持。 2. 对不同配置的支持也因设备而异:有的可以支持full resolution jpeg + full resolution yuv,有的不能。请分享用于设置的代码。 嗨@Minhaz。当然,这是用于初始化的标准代码 - 我已添加到主要问题中。我很惊讶像 Pixel 2 和 Nexus(都是 Google Native)这样的流行设备有这个问题。 补充了我的想法,甚至可能不起作用,但完全值得一试。 【参考方案1】:

这可能无法完美回答,我可能是错的,但请尝试以下:

您用于绑定到生命周期的 Preview 实例具有允许使用 setTargetResoltion 或 setTargetAspectRation 设置目标分辨率或目标纵横比的 Builder。

如果没有设置,它会调用

如果未设置,默认选择的分辨率将是与设备屏幕分辨率或 1080p (1920x1080) 匹配的最佳尺寸,以较小者为准。

如果未设置,将优先考虑纵横比为 4:3 的分辨率。

分别。

根据错误信息

在格式支持的最大值下无法获得支持的输出大小

它似乎无法获得它试图为某些设备的默认值查找的输出大小。这是可能的,因为相机的 HAL 实现是由 OEM(如诺基亚、华为等)完成的,并且可以支持不同的支持尺寸。如果您想查看给定设备支持的分辨率,可以使用此应用:Camera2Api Probe

指向how Camera X selects automatic resolution的指针

TL;DR; 虽然 API 应该隐式提供这种支持,但在 alpha 中考虑它,尝试显式设置纵横比或目标分辨率,以便它适用于大多数设备。为了使其高度可配置,您可以使用this api查询支持的分辨率

请注意,我与提到的应用程序 Camera2Api 没有链接或所有权,但我用它来查询我工作中设备的 Camera2 信息。

【讨论】:

【参考方案2】:

当您使用旧版本或新版本的 lib 时,有时会发生这种情况。尝试改变它

【讨论】:

【参考方案3】:

来自官方文档: “CameraX 库处于 alpha 阶段,因为它的 API 表面尚未最终确定。我们不建议在生产中使用 Alpha 库。库应严格避免在生产中依赖 Alpha 库,因为它们的 API 表面可能会在源和二进制不兼容的方式。” 您可以等待稳定版本或使用Camera或Camera2的api。

【讨论】:

【参考方案4】:

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);
    

我在支持旧版相机的设备上也有同样的功能。希望对找到答案有所帮助。


UPD:发生这种情况是因为 CameraX 库无法找到适合显示分辨率的相机输出的最佳分辨率。例如:

显示分辨率:1280x720 支持的最接近的相机分辨率:1920x720 DispRes

如果显示分辨率小于相机分辨率,Lib 可以工作。

例如: 显示分辨率:1280x800 支持的最接近的相机分辨率:1280x720 DispRes > CamRes。成功!

【讨论】:

【参考方案5】:

您可以使用这个函数(用 Kotlin 编写)来获取可能的输出大小:

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

只需尝试它们,直到其中一个起作用:

for (outputSize in getOutputSizes()!!) 
    try 
        CameraX.bindToLifecycle(this, qrCodePreview.useCase, qrCodeImageAnalysis.useCase)
        return
    
    catch (e: IllegalArgumentException) 

TODO("No valid output size found, handle error ...")

【讨论】:

以上是关于Android Camerax 在真实设备上崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin表单,在Visual Studio Android Emulator上运行的应用程序但在真实设备上崩溃

Play商店预发布报告中的Android应用程序崩溃但在真实设备中工作

在flutter中从image_picker包中打开相机会导致真实设备上的应用程序崩溃,但在模拟器(android)中运行良好

当我在真实设备中打开活动时应用程序崩溃

如何使用 Android CameraX ImageAnalysis 提高帧速率?

应用程序在模拟器上运行良好,但在真实设备上崩溃