JNI启动新Activity遇构造方法找不到错误求助
解决JNI中启动Activity的NoSuchMethodError问题
你的问题根源很明确:Intent构造方法的签名写错了,而且最后调用startActivity时传错了调用对象,咱们一步步来修正:
错误分析
你想在JNI中调用Java的Intent(Context, Class<?>)构造方法,但你写的方法签名是(Landroid/content/Context;Ljava/lang/String;)Landroid/content/Intent——把第二个参数的Class类型写成了String,这就导致VM找不到对应的构造方法,抛出NoSuchMethodError。另外,最后CallVoidMethod(intent, startActivity)也错了,startActivity是Activity的方法,得用Activity实例(也就是你的context)来调用,不是Intent对象。
修正后的完整代码
// 1. 获取Intent类引用 jclass intentClass = env->FindClass("android/content/Intent"); if (intentClass == nullptr) { // 可添加错误日志或处理逻辑 return; } // 2. 获取TestActivity的Class对象(类名要换成你实际的完整路径,用/代替.) jclass testActivityClass = env->FindClass("com/test/package/TestActivity"); if (testActivityClass == nullptr) { env->DeleteLocalRef(intentClass); // 处理找不到类的情况 return; } // 3. 获取正确的Intent构造方法签名:(Context, Class) jmethodID intentConstructor = env->GetMethodID(intentClass, "<init>", "(Landroid/content/Context;Ljava/lang/Class;)Landroid/content/Intent"); if (intentConstructor == nullptr) { env->DeleteLocalRef(intentClass); env->DeleteLocalRef(testActivityClass); // 处理找不到构造方法的情况 return; } // 4. 创建Intent实例 jobject intent = env->NewObject(intentClass, intentConstructor, context, testActivityClass); if (intent == nullptr) { env->DeleteLocalRef(intentClass); env->DeleteLocalRef(testActivityClass); // 处理创建失败 return; } // (可选)如果context不是Activity类型,必须添加NEW_TASK标记 jmethodID setFlagsMethod = env->GetMethodID(intentClass, "setFlags", "(I)Landroid/content/Intent;"); if (setFlagsMethod != nullptr) { intent = env->CallObjectMethod(intent, setFlagsMethod, 0x10000000); // FLAG_ACTIVITY_NEW_TASK } // 5. 获取Activity类的startActivity方法 jclass activityClass = env->FindClass("android/app/Activity"); if (activityClass == nullptr) { // 清理引用后返回 env->DeleteLocalRef(intentClass); env->DeleteLocalRef(testActivityClass); env->DeleteLocalRef(intent); return; } jmethodID startActivityMethod = env->GetMethodID(activityClass, "startActivity", "(Landroid/content/Intent;)V"); if (startActivityMethod == nullptr) { // 清理引用后返回 env->DeleteLocalRef(intentClass); env->DeleteLocalRef(testActivityClass); env->DeleteLocalRef(intent); env->DeleteLocalRef(activityClass); return; } // 6. 正确调用startActivity:用context(Activity实例)作为调用对象 env->CallVoidMethod(context, startActivityMethod, intent); // 7. 释放所有本地引用,避免内存泄漏 env->DeleteLocalRef(intentClass); env->DeleteLocalRef(testActivityClass); env->DeleteLocalRef(intent); env->DeleteLocalRef(activityClass);
关键注意点
- 方法签名必须精准:JNI的方法签名要严格对应Java方法的参数类型,你可以用
javap -s命令生成类的方法签名,比如对Intent类执行javap -s android.content.Intent,就能看到所有构造方法的正确签名。 - Class对象而非字符串:Java中
Intent(this, TestActivity.class)的第二个参数是Class类型,所以JNI里必须通过FindClass获取对应的Class实例,不能直接传类名字符串。 - 调用对象要正确:
startActivity是Activity的成员方法,必须传入Activity类型的实例(你的context),如果用Intent对象调用,会触发找不到方法的错误。 - 非Activity Context的处理:如果你的
context是Application Context,必须给Intent添加FLAG_ACTIVITY_NEW_TASK标记,否则会抛出ActivityNotFoundException。
内容的提问来源于stack exchange,提问作者Julian
相关产品推荐
相关产品推荐

