You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:52:22