基于JNI、C++与Android SDK,无Android Studio能否创建Android Activity?
可以实现,但绝非单纯配置类路径就能搞定,核心问题是你当前的JVM是标准Java虚拟机,没有Android Runtime(ART)的底层支撑,而Android的Activity体系严重依赖系统内部组件。以下是关键细节:
为什么直接用android.jar行不通?
android.jar是SDK提供的桩(Stub)类库,里面的方法大多是空实现或直接抛出RuntimeException,真正的业务逻辑都在Android设备的ART核心库(如libandroid_runtime.so、libactivity.so)里。标准JVM无法加载这些系统库,就算能导入android.content.Intent等类,调用方法时也会直接报错。
必须解决的核心问题
获取有效的Context实例
Context的实际实现类(如ContextImpl)是Android系统内部类,你无法直接实例化。必须通过JNI调用ART提供的接口获取:- 可以反射
android.app.ActivityThread的静态方法currentActivityThread(),再从中获取Application Context; - 或者基于NDK的
NativeActivity,它会自动初始化ART并提供可用的Context。
- 可以反射
模拟Activity启动流程
Android的Activity启动依赖ActivityThread、ActivityManagerService等系统组件的协作,不是调用startActivity()就完事。你需要在JNI层触发Activity的生命周期回调(onCreate、onStart等),否则Activity无法正常运行。
可行的实操方案
方案1:基于NDK NativeActivity(最简便)
这是官方支持的纯C++启动Android应用的方式,NDK会帮你完成ART初始化、Context提供等工作:
- 编写C++代码,通过JNI创建并启动你的MainActivity;
- 手动编写
AndroidManifest.xml,声明NativeActivity作为入口,并关联你的C++库; - 用NDK构建工具(如
ndk-build)编译代码,配合aapt打包成APK。
方案2:手动初始化ART(难度高)
直接在C++中调用ART的JNI_CreateJavaVM(而非标准JVM的初始化方法),并加载Android系统核心库:
// 初始化ART虚拟机(参数需适配目标Android版本) JavaVM* vm; JNIEnv* env; JavaVMInitArgs args; // 设置类路径,包含系统framework.jar和你的应用类文件 args.options[0].optionString = "-Djava.class.path=/system/framework/framework.jar:/path/to/your/app/classes"; // 链接libart.so后调用ART的JNI_CreateJavaVM jint result = JNI_CreateJavaVM(&vm, (void**)&env, &args); // 反射获取ActivityThread与Application Context jclass activityThreadCls = env->FindClass("android/app/ActivityThread"); jmethodID currentMethod = env->GetStaticMethodID(activityThreadCls, "currentActivityThread", "()Landroid/app/ActivityThread;"); jobject activityThread = env->CallStaticObjectMethod(activityThreadCls, currentMethod); jmethodID getAppMethod = env->GetMethodID(activityThreadCls, "getApplication", "()Landroid/app/Application;"); jobject appContext = env->CallObjectMethod(activityThread, getAppMethod); // 创建Intent并启动MainActivity jclass intentCls = env->FindClass("android/content/Intent"); jmethodID intentCtor = env->GetMethodID(intentCls, "<init>", "(Landroid/content/Context;Ljava/lang/Class;)V"); jclass mainActivityCls = env->FindClass("com/your/package/MainActivity"); jobject intent = env->NewObject(intentCls, intentCtor, appContext, mainActivityCls); jclass contextCls = env->FindClass("android/content/Context"); jmethodID startActivityMethod = env->GetMethodID(contextCls, "startActivity", "(Landroid/content/Intent;)V"); env->CallVoidMethod(appContext, startActivityMethod, intent);
额外注意事项
- 必须在Android设备或模拟器上运行,因为ART和系统核心库仅存在于Android环境;
- 手动编写
AndroidManifest.xml,声明MainActivity的MAIN和LAUNCHERintent-filter,并用aapt打包; - 不同Android版本的ART接口、类结构可能有差异,需要针对性适配。
内容的提问来源于stack exchange,提问作者Dan D

