Qt for Android JNI报错:java.lang.NoSuchMethodError问题求助
解决Qt Android C++调用Java静态方法时的NoSuchMethodError问题
咱先从最明显的问题说起——你贴的Java代码里根本没实现getSSIDList这个静态方法啊!错误日志里说找不到Lcom/test/myTest/JniTest;.getSSIDList(V)[Ljava/lang/String;,就是因为JNI在你的JniTest类里找不到对应方法,直接抛出了错误。
第一步:补全Java类里的getSSIDList方法
先把缺失的静态方法补上,如果你需要返回String数组,参考下面的示例代码:
package com.test.myTest; import java.util.ArrayList; import java.util.List; public class JniTest { public static int fibonacci(int n) { if(n<0) return -1; else if(n==0 || n==1) return n; else return fibonacci(n-1)+fibonacci(n-2); } // 新增你需要的getSSIDList静态方法 public static String[] getSSIDList() { // 这里可以写你的业务逻辑,比如获取WiFi列表 List<String> ssidList = new ArrayList<>(); ssidList.add("HomeWiFi"); ssidList.add("OfficeWiFi"); // 把List转成String数组返回 return ssidList.toArray(new String[0]); } }
第二步:确保JNI调用的方法签名完全匹配
JNI对方法签名的要求非常严格,哪怕一点小错误都会导致找不到方法。在Qt C++里调用时,要注意这几点:
- 包名和类名要对应:用斜杠代替点,即
com/test/myTest/JniTest - 方法名大小写完全一致:必须是
getSSIDList - 签名要正确:无参数的话是
(),返回String数组的签名是[Ljava/lang/String;(注意末尾的分号不能丢)
给你一个完整的Qt C++调用示例,转成QStringList后可以直接给QML使用:
#include <QAndroidJniEnvironment> #include <QDebug> #include <QStringList> QStringList getSSIDListFromJava() { QStringList result; JNIEnv *env = QAndroidJniEnvironment(); // 查找JniTest类 jclass jniTestCls = env->FindClass("com/test/myTest/JniTest"); if (!jniTestCls) { qDebug() << "ERROR: 找不到JniTest类"; return result; } // 获取getSSIDList的静态方法ID jmethodID getSSIDListMethod = env->GetStaticMethodID(jniTestCls, "getSSIDList", "()[Ljava/lang/String;"); if (!getSSIDListMethod) { qDebug() << "ERROR: 找不到getSSIDList方法"; env->DeleteLocalRef(jniTestCls); return result; } // 调用静态方法获取String数组 jobjectArray jSsidArray = (jobjectArray)env->CallStaticObjectMethod(jniTestCls, getSSIDListMethod); if (!jSsidArray) { qDebug() << "ERROR: 调用getSSIDList返回空"; env->DeleteLocalRef(jniTestCls); return result; } // 把Java String数组转成QStringList int arrayLength = env->GetArrayLength(jSsidArray); for (int i = 0; i < arrayLength; ++i) { jstring jSsid = (jstring)env->GetObjectArrayElement(jSsidArray, i); const char *ssidUtf8 = env->GetStringUTFChars(jSsid, nullptr); if (ssidUtf8) { result.append(QString::fromUtf8(ssidUtf8)); env->ReleaseStringUTFChars(jSsid, ssidUtf8); } env->DeleteLocalRef(jSsid); } // 释放JNI局部引用,避免内存泄漏 env->DeleteLocalRef(jSsidArray); env->DeleteLocalRef(jniTestCls); return result; }
第三步:检查Qt Android项目配置
- 确保你的
JniTest.java文件放在Qt项目的android/src/com/test/myTest目录下,对应包名的目录结构,这样编译时才能被正确打包进APK。 - 如果你的
getSSIDList是用来获取WiFi列表的,记得在AndroidManifest.xml里添加必要权限:<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- Android 6.0+需要这个权限才能扫描WiFi -->
最后再提几个容易踩的坑
- 方法名大小写敏感:Java是区分大小写的,别把
getSSIDList写成GetSSIDList或者其他变体。 - 签名格式别写错:返回String数组的签名是
[Ljava/lang/String;,不是[Ljava/String;或者其他写法。 - 记得释放JNI引用:JNI的局部引用如果不手动释放,可能会导致内存泄漏甚至崩溃。
内容的提问来源于stack exchange,提问作者user4072916
相关产品推荐
相关产品推荐

