集成Google Cardboard SDK时出现BaseDexClassLoader类找不到异常
问题分析
运行Cardboard_initializeAndroid时触发ClassNotFoundException,找不到CardboardParamsUtils和QrCodeCaptureActivity,但APK中存在对应smali文件;minSdkVersion=26默认开启Multidex,原生代码编译正常,异常来自qr_code.cc的LoadJNIResources函数。
解决方案
1. 修正JNI类加载逻辑
原生代码加载Java类时可能使用了系统类加载器,导致找不到应用内的类。修改qr_code.cc的LoadJNIResources函数,改用应用上下文的类加载器查找类:
// 获取应用上下文的类加载器 jclass context_cls = env->FindClass("android/content/Context"); jmethodID get_class_loader = env->GetMethodID(context_cls, "getClassLoader", "()Ljava/lang/ClassLoader;"); jobject class_loader = env->CallObjectMethod(android_context, get_class_loader); env->DeleteLocalRef(context_cls); // 通过类加载器加载目标类 jclass loader_cls = env->FindClass("java/lang/ClassLoader"); jmethodID load_class = env->GetMethodID(loader_cls, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); // 加载CardboardParamsUtils jstring params_utils_name = env->NewStringUTF("com.google.cardboard.sdk.qrcode.CardboardParamsUtils"); jclass params_utils_cls = (jclass)env->CallObjectMethod(class_loader, load_class, params_utils_name); env->DeleteLocalRef(params_utils_name); // 加载QrCodeCaptureActivity jstring capture_activity_name = env->NewStringUTF("com.google.cardboard.sdk.QrCodeCaptureActivity"); jclass capture_activity_cls = (jclass)env->CallObjectMethod(class_loader, load_class, capture_activity_name); env->DeleteLocalRef(capture_activity_name); env->DeleteLocalRef(loader_cls);
2. 补充ProGuard混淆规则
release构建开启了代码混淆,即使smali存在,也可能因类名被修改导致加载失败。在模块的proguard-rules.pro中添加保留规则:
# 保留Cardboard SDK所有类及方法 -keep class com.google.cardboard.sdk.** { *; } -keep class com.google.cardboard.proto.** { *; } # 保留JNI关联方法 -keepclasseswithmembernames class * { native <methods>; }
3. 修复library模块Build配置
你的build.gradle存在重复的defaultConfig块,可能导致配置异常,移除嵌套块:
defaultConfig { minSdkVersion 26 targetSdkVersion 31 testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' consumerProguardFiles 'proguard-rules.pro' // 移至外层defaultConfig }
执行./gradlew clean build清理缓存后重新构建模块,确保sourceSets配置的Java目录和protobuf生成路径无冲突。
4. 验证依赖与打包完整性
- 确认主项目通过
implementation project(...)正确引入Cardboard模块 - 使用Android Studio的
Build > Analyze APK功能,检查APK的classes.dex中是否存在完整的com.google.cardboard.sdk包结构(仅smali存在不代表dex类可正常加载)
5. 调整JNI初始化时机
确保Cardboard_initializeAndroid在Activity创建完成后调用,避免在Application的onCreate早期或未初始化Android上下文时执行,此时类加载器可能未准备就绪。
内容的提问来源于stack exchange,提问作者Stégosaure
相关产品推荐
相关产品推荐

