搭建 Windows 下的 Android Studio C++ 开发调试环境
公司有一套祖传的安卓代码,里面用到 C++,因为历史原因,每次 C++ 侧的改动都要在 ubuntu 虚拟机上编译打包,然后再复制到共享文件夹,再在 Windows 上复制到工程中运行,不仅麻烦,而且不能断点调试,所以我花了些时间把它改成可以在 Windows 上编译和调试。公司的代码这里就不展示了,本文以一个测试工程来讲解整个过程,目标是搭建一个在 Windows 下仅用 Android Studio 的开发调试 C++ 的环境,既可以编写 C++ 代码又可以断点调试和打包,不用 CMake 及其它第三方软件,也不用 javah 生成 .h 文件。
第1步,安装 NDK:
在 AS 的 SDK Manager 中安装,如图1所示。安装过程有可能中断,只要反复重试最后一定会成功。记住 NDK 的版本号,后面要用到(版本号可随意选择,越高版本的 C++ 规范越严格)。

图1
第2步,新建工程:
新建工程,如图2所示。这里以传统的 View 框架为例,Compose 框架也是一样的。

图2
第3步,编写 C++侧的配置文件和代码:
在工程中新建以下文件和文件夹,如图3所示。

图3
表1是各文件(夹)的说明。
文件(夹) 说明
app/src/main/cpp/Application.mk 整个工程中所有 C/C++ 模块的配置文件,包含所有模块通用的配置信息
app/src/main/cpp/Android.mk 整个工程中所有 C/C++ 模块的编译描述文件,在这个文件中包含所有 C/C++ 模块的路径
app/src/main/cpp/Test Test 模块的文件夹
app/src/main/cpp/Test/Android.mk Test 模块的编译描述文件
app/src/main/cpp/Test/Test.cpp Test 模块的源代码文件
表1
以下是各文件的内容。
app/src/main/cpp/Application.mk
APP_ABI := arm64-v8a
APP_CPPFLAGS += -fexceptions
APP_PLATFORM := android-24
APP_STL := c++_static
APP_OPTIMA := debug
app/src/main/cpp/Android.mk
my_build_path :=$(call my-dir)
include $(my_build_path)/Test/Android.mk
app/src/main/cpp/Test/Android.mk
my_module_path :=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_PATH := /.
LOCAL_MODULE := Test
LOCAL_C_INCLUDES := $(my_module_path)/
LOCAL_CFLAGS := -D__linux__
-DANDROID_SUPPORT
-DUNICODE
-D_UNICODE
-DLINUX
-DCHART_MERGE
-DMACRO_WH
-DNO_COMM_SUPPORT
-DSUPPORT_ITS
-DSUPPORT_HTML
-fsigned-char
-fno-exceptions
-DSUPPORT_LUA
-DUSE_AUTHORIZE
LOCAL_SRC_FILES := $(wildcard $(my_module_path)/*.cpp)
include $(BUILD_SHARED_LIBRARY)
app/src/main/cpp/Test/Test.cpp
include <jni.h>
include
// 测试用的本地方法
jstring GetTestString(JNIEnv* env, jobject) {
const char* str = "hello c++";
return env->NewStringUTF(str);
}
// 本地方法数组
JNINativeMethod method_table[] = {
{ "getTestString", "()Ljava/lang/String;", (void*)GetTestString }
};
/**
-
jni 加载事件的响应函数。在这个函数中注册本地方法。
-
@param jvm java 虚拟机
/
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM jvm, void) {
// 获取 jni 环境
jint jniVersion = JNI_VERSION_1_6;
JNIEnv env;
jvm->GetEnv((void**)&env, jniVersion);// 获取使用本地方法的类,注意 className 和 java 侧一致
const char* className = "com/dlmu/test_android6/MainActivity";
jclass clazz = env->FindClass(className);
if (clazz == nullptr) {
return JNI_FALSE;
}// 注册本地方法
if (env->RegisterNatives(clazz, method_table, sizeof(method_table) / sizeof(JNINativeMethod)) < 0) {
return JNI_FALSE;
}return jniVersion;
}
第4步,修改 build.gradle
打开使用 本地方法的模块的 build.gradle(本实例是 app 下的 build.gradle),在文件中追加注释部分的内容。
plugins {
alias(libs.plugins.android.application)
}
android {
namespace 'com.dlmu.test_android6'
compileSdk 35
defaultConfig {
applicationId "com.dlmu.test_android6"
minSdk 24
targetSdk 35
versionCode 1
versionName "1.0"
}
buildTypes {
debug {
// 允许调试本地方法
jniDebuggable true
}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
buildFeatures {
viewBinding true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
// 设置 C++ 的编译配置文件路径
externalNativeBuild {
ndkBuild {
path "src/main/cpp/Android.mk"
}
}
// 设置 NDK 版本号
ndkVersion '27.0.12077973'
}
dependencies {
implementation libs.appcompat
implementation libs.material
implementation libs.activity
implementation libs.constraintlayout
}
第5步,编写 java 侧代码
public class MainActivity extends AppCompatActivity {
/**
* 测试用的本地方法。
*/
public native String getTestString();
/**
* 静态构造方法。在这个方法中加载动态库。
*/
static {
System.loadLibrary("Test");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
final ActivityMainBinding binding = ActivityMainBinding.inflate(super.getLayoutInflater());
super.setContentView(binding.getRoot());
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
// 调用测试方法
binding.tvTest.setText(this.getTestString());
}
}
第6步,运行
同步一下工程就可以运行了,在手机屏幕上显示 hello c++,也可以在 C++ 文件中下断点。
最后补充一点,如果是在非 app 模块中使用 C++,且在该模块的 build.gradle 中设置了
ndk {
abiFilters "......"
}
那么 app 模块中也要有相同的设置,否则打包后的 apk 中没有 so 文件,程序当然也会闪退。
全文完。

浙公网安备 33010602011771号