二维码扫描应用启动崩溃:NoClassDefFoundError问题求助
二维码扫描应用启动崩溃:NoClassDefFoundError 问题解决
我正在开发一款二维码扫描应用,每次启动都会崩溃并抛出NoClassDefFoundError。查看Logcat后得到如下错误信息:
2023-01-02 08:53:29.552 27370-27370/com.cheesypc.qrcodescanner E/AndroidRuntime: FATAL EXCEPTION: main Process: com.cheesypc.qrcodescanner, PID: 27370 java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/camera/core/impl/utils/AspectRatioUtil$CompareAspectRatiosByDistanceToTargetRatio; at androidx.camera.camera2.internal.SupportedSurfaceCombination.getSupportedOutputSizes(SupportedSurfaceCombination.java:468) at androidx.camera.camera2.internal.SupportedSurfaceCombination.getSuggestedResolutions(SupportedSurfaceCombination.java:240) at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.getSuggestedResolutions(Camera2DeviceSurfaceManager.java:197) at androidx.camera.core.internal.CameraUseCaseAdapter.calculateSuggestedResolutions(CameraUseCaseAdapter.java:431) at androidx.camera.core.internal.CameraUseCaseAdapter.addUseCases(CameraUseCaseAdapter.java:239) at androidx.camera.lifecycle.LifecycleCamera.bind(LifecycleCamera.java:206) at androidx.camera.lifecycle.LifecycleCameraRepository.bindToLifecycleCamera(LifecycleCameraRepository.java:283) at androidx.camera.lifecycle.ProcessCameraProvider.bindToLifecycle(ProcessCameraProvider.java:538) at androidx.camera.lifecycle.ProcessCameraProvider.bindToLifecycle(ProcessCameraProvider.java:363) at com.cheesypc.qrcodescanner.HomeScreenKt$Scanner$1$2.invoke(HomeScreen.kt:79) at com.cheesypc.qrcodescanner.HomeScreenKt$Scanner$1$2.invoke(HomeScreen.kt:60) at androidx.compose.ui.viewinterop.ViewFactoryHolder.setFactory(AndroidView.android.kt:174) at androidx.compose.ui.viewinterop.AndroidView_androidKt$AndroidView$1.invoke(AndroidView.android.kt:116) at androidx.compose.ui.viewinterop.AndroidView_androidKt$AndroidView$1.invoke(AndroidView.android.kt:113) at androidx.compose.ui.viewinterop.AndroidView_androidKt$AndroidView$$inlined$ComposeNode$1.invoke(Composables.kt:254) at androidx.compose.runtime.ComposerImpl$createNode$2.invoke(Composer.kt:1537) at androidx.compose.runtime.ComposerImpl$createNode$2.invoke(Composer.kt:1535) at androidx.compose.runtime.ComposerImpl$recordInsert$2.invoke(Composer.kt:3395) at androidx.compose.runtime.ComposerImpl$recordInsert$2.invoke(Composer.kt:3392) at androidx.compose.runtime.CompositionImpl.applyChangesInLocked(Composition.kt:782) at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:813) at androidx.compose.runtime.Recomposer.composeInitial$runtime_release(Recomposer.kt:827) at androidx.compose.runtime.CompositionImpl.setContent(Composition.kt:519) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:140) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131) at androidx.compose.ui.platform.AndroidComposeView.setOnViewTreeOwnersAvailable(AndroidComposeView.android.kt:1015) at androidx.compose.ui.platform.WrappedComposition.setContent(Wrapper.android.kt:131) at androidx.compose.ui.platform.WrappedComposition.onStateChanged(Wrapper.android.kt:182) at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:360) at androidx.lifecycle.LifecycleRegistry.addObserver(LifecycleRegistry.java:202) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:138) at androidx.compose.ui.platform.WrappedComposition$setContent$1.invoke(Wrapper.android.kt:131) at androidx.compose.ui.platform.AndroidComposeView.onAttachedToWindow(AndroidComposeView.android.kt:1102) at android.view.View.dispatchAttachedToWindow(View.java:18359) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3397) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3404) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3404) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3404) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3404) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1773) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1471) 2023-01-02 08:53:29.556 27370-27370/com.cheesypc.qrcodescanner E/AndroidRuntime: at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7211) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1004) at android.view.Choreographer.doCallbacks(Choreographer.java:816) at android.view.Choreographer.doFrame(Choreographer.java:751) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:990) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:193) at android.app.ActivityThread.main(ActivityThread.java:6692) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) Caused by: java.lang.ClassNotFoundException: Didn't find class "androidx.camera.core.impl.utils.AspectRatioUtil$CompareAspectRatiosByDistanceToTargetRatio" on path: DexPathList[[zip file "/data/app/com.cheesypc.qrcodescanner-Bpfcr28b32Uq7ZGMUq2TGQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.cheesypc.qrcodescanner-Bpfcr28b32Uq7ZGMUq2TGQ==/lib/arm64, /data/app/com.cheesypc.qrcodescanner-Bpfcr28b32Uq7ZGMUq2TGQ==/base.apk!/lib/arm64-v8a, /system/lib64, /vendor/lib64]] at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:134) at java.lang.ClassLoader.loadClass(ClassLoader.java:379) at java.lang.ClassLoader.loadClass(ClassLoader.java:312) ... 53 more
错误发生在AndroidView()以及try代码块中的cameraProviderFuture.get().bindToLifecycle处,相关代码如下:
AndroidView( factory = { context -> val previewView = PreviewView(context) val preview = Preview.Builder().build() val selector = CameraSelector.Builder() .requireLensFacing(CameraSelector.LENS_FACING_BACK) .build() preview.setSurfaceProvider(previewView.surfaceProvider) val imageAnalysis = ImageAnalysis.Builder() .setTargetResolution(Size(previewView.width, previewView.height)) .setBackpressureStrategy(STRATEGY_KEEP_ONLY_LATEST) .build() imageAnalysis.setAnalyzer( ContextCompat.getMainExecutor(context), QrCodeAnalyser { result -> code = result } ) try { cameraProviderFuture.get().bindToLifecycle( lifecycleOwner, selector, preview, imageAnalysis ) } catch (e: Exception) { e.printStackTrace() } previewView }, modifier = Modifier.weight(1f) )
问题原因
该错误源于CameraX库版本不兼容或依赖缺失,导致运行时无法找到AspectRatioUtil$CompareAspectRatiosByDistanceToTargetRatio类。
解决步骤
- 统一CameraX依赖版本
确保所有CameraX相关依赖使用相同的稳定版本,避免版本冲突。在Module级别的build.gradle中配置:
dependencies { // CameraX核心依赖 implementation "androidx.camera:camera-core:1.3.0" implementation "androidx.camera:camera-camera2:1.3.0" implementation "androidx.camera:camera-lifecycle:1.3.0" implementation "androidx.camera:camera-view:1.3.0" // 若使用ML Kit扫描二维码,添加对应依赖 implementation "com.google.mlkit:barcode-scanning:17.2.0" }
可根据官方文档调整为最新稳定版本。
清理重建项目
执行Build > Clean Project,再执行Build > Rebuild Project;必要时删除项目根目录的.gradle和模块下的build文件夹,然后重新同步项目。检查MultiDex配置
如果项目方法数超过限制,需启用MultiDex:- 在
AndroidManifest.xml的application标签中添加:
android:name="androidx.multidex.MultiDexApplication"- 在Module级别的
build.gradle中配置:
android { defaultConfig { multiDexEnabled true } } dependencies { implementation "androidx.multidex:multidex:2.0.1" }- 在
修复分辨率设置问题
原代码中previewView初始化时宽高可能为0,导致无效的目标分辨率。可替换为固定宽高比或动态获取屏幕尺寸:
// 使用固定宽高比 val imageAnalysis = ImageAnalysis.Builder() .setTargetAspectRatio(AspectRatio.RATIO_16_9) .setBackpressureStrategy(STRATEGY_KEEP_ONLY_LATEST) .build() // 或动态获取屏幕尺寸 val displayMetrics = context.resources.displayMetrics val screenSize = Size(displayMetrics.widthPixels, displayMetrics.heightPixels) val imageAnalysis = ImageAnalysis.Builder() .setTargetResolution(screenSize) .setBackpressureStrategy(STRATEGY_KEEP_ONLY_LATEST) .build()
- 优化CameraProvider初始化逻辑
避免在AndroidView的factory中直接调用get()阻塞线程,改用监听回调确保初始化完成后再绑定生命周期:
val cameraProviderFuture = ProcessCameraProvider.getInstance(context) cameraProviderFuture.addListener({ val cameraProvider = cameraProviderFuture.get() // 执行bindToLifecycle操作 cameraProvider.bindToLifecycle( lifecycleOwner, selector, preview, imageAnalysis ) }, ContextCompat.getMainExecutor(context))
内容的提问来源于stack exchange,提问作者Gnanesh023
相关产品推荐
相关产品推荐

