搭建 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

图1

第2步,新建工程:

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

图2

第3步,编写 C++侧的配置文件和代码:

在工程中新建以下文件和文件夹,如图3所示。
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 文件,程序当然也会闪退。

全文完。

posted @ 2025-07-04 17:20  安联酋长  阅读(51)  评论(0)    收藏  举报