Native Activity中C++调用自定义Java WebView类失败问题排查
解决Native Activity环境下JNI找不到自定义Java类的问题
1. 配置Module级build.gradle
确保Java代码被正确编译打包,同时关联CMake构建流程:
- 确认
sourceSets配置正确识别源码路径,默认src/main/java会被自动扫描,若有自定义路径需明确声明:
android { sourceSets { main { java.srcDirs = ['src/main/java'] jni.srcDirs = ['src'] // 你的C++代码根目录 } } defaultConfig { externalNativeBuild { cmake { path file('CMakeLists.txt') // 指向项目根目录的CMake配置文件 } } } externalNativeBuild { cmake { version "3.22.1" // 使用与你的NDK版本适配的CMake版本 } } }
- 添加WebView依赖(按需选择对应版本):
dependencies { implementation 'androidx.webkit:webkit:1.6.1' }
2. 修改AndroidManifest.xml
确保Java类可被正确加载,同时配置WebView必需的权限与属性:
<!-- 添加WebView所需权限 --> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:hardwareAccelerated="true" <!-- WebView必须开启硬件加速 --> android:supportsRtl="true"> <!-- 声明Native Activity --> <activity android:name="android.app.NativeActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="android.app.lib_name" android:value="你的Native库名称" /> <!-- 需与CMake配置的库名一致 --> </activity> </application>
3. 修正JNI调用代码
Native Activity的系统类加载器无法识别自定义类,需改用应用类加载器加载:
JNIEnv* env = nullptr; JavaVM* jvm = gapp->activity->vm; // 附加当前线程到JVM int attachResult = jvm->AttachCurrentThread(&env, nullptr); if (attachResult != JNI_OK) { return; } // 获取NativeActivity的Java对象 jobject activityObj = gapp->activity->clazz; // 获取Activity的ClassLoader jclass activityClass = env->GetObjectClass(activityObj); jmethodID getClassLoaderMethod = env->GetMethodID(activityClass, "getClassLoader", "()Ljava/lang/ClassLoader;"); jobject classLoaderObj = env->CallObjectMethod(activityObj, getClassLoaderMethod); // 通过ClassLoader加载自定义类 jclass classLoaderClass = env->FindClass("java/lang/ClassLoader"); jmethodID loadClassMethod = env->GetMethodID(classLoaderClass, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); jstring classNameStr = env->NewStringUTF("com.my.app.CustomWebView"); // 注意用点分隔包名 jclass customWebViewClass = (jclass)env->CallObjectMethod(classLoaderObj, loadClassMethod, classNameStr); // 释放局部引用 env->DeleteLocalRef(classNameStr); env->DeleteLocalRef(classLoaderClass); env->DeleteLocalRef(classLoaderObj); env->DeleteLocalRef(activityClass); // 检查加载结果,若失败可打印JNI异常信息 if (customWebViewClass == nullptr) { jthrowable exc = env->ExceptionOccurred(); if (exc) { env->ExceptionDescribe(); env->ExceptionClear(); } } // 按需分离线程 jvm->DetachCurrentThread();
关键注意点
- Native Activity默认使用系统类加载器,仅能加载系统类,自定义类必须通过应用级的Activity ClassLoader加载,这是直接调用
FindClass失败的核心原因。 - 确保Java类的包名与文件路径完全对应,
src/main/java/com/my/app/CustomWebView.java中必须声明package com.my.app;。 - CMake配置的Native库名称必须与Manifest中
android.app.lib_name的取值一致。
内容的提问来源于stack exchange,提问作者dan123123
相关产品推荐
相关产品推荐

