第一章:NDK开发环境搭建
各位同学好,我是你们的老朋友。今天咱们来聊聊NDK开发的第一步——环境搭建。说实话,这一步看似简单,但坑还真不少。我见过太多人卡在环境配置上,代码还没写一行,先被各种报错搞崩溃了。
嗯,咱们直接进入正题。
1.1 Android Studio配置NDK
先说说Android Studio。现在新版的AS其实已经内置了NDK支持,但默认不下载。你需要手动去SDK Manager里勾选。
具体操作:打开Settings → Appearance & Behavior → System Settings → Android SDK → SDK Tools。找到「NDK (Side by side)」和「CMake」,勾上,点Apply。等它下载完就行。
下载完后,记得检查一下local.properties文件。里面应该有类似这样的配置:
ndk.dir=/Users/你的用户名/Library/Android/sdk/ndk/26.1.10909125
cmake.dir=/Users/你的用户名/Library/Android/sdk/cmake/3.22.1
如果没自动生成,手动加上也行。我在项目中遇到过好几次,AS更新后这个文件被重置了,导致编译报错。所以每次更新完AS,我都会看一眼这个文件。
1.2 CMake vs ndk-build:到底选哪个?
这个问题我经常被问到。说白了,现在新项目基本都用CMake。为什么?
- CMake:语法更现代,跨平台支持好,Android Studio原生支持。你写个CMakeLists.txt,AS自动帮你处理编译流程。
- ndk-build:老古董了。基于Makefile,语法比较原始。但如果你在维护老项目,或者有现成的Android.mk文件,那也没必要硬改。
我个人建议:新项目一律用CMake。除非你接手的是遗留代码,否则别给自己找麻烦。
来看看CMakeLists.txt的基本结构:
cmake_minimum_required(VERSION 3.22.1)
project("my_native_lib")
add_library(
my_native_lib
SHARED
native-lib.cpp
)
find_library(
log-lib
log
)
target_link_libraries(
my_native_lib
${log-lib}
)
嗯,就这么简单。你只需要指定源文件、依赖库,CMake帮你搞定剩下的。
1.3 ABI架构详解
ABI,全称Application Binary Interface。说白了,就是你的so文件要跑在什么CPU上。
目前主流的有三种:
| ABI | 架构 | 适用设备 | 建议 |
|---|---|---|---|
| armeabi-v7a | 32位ARM | 老设备、低端机 | 保留,但非必须 |
| arm64-v8a | 64位ARM | 2015年后几乎所有新机 | 必须保留 |
| x86_64 | 64位x86 | 模拟器、少数平板 | 调试用,发布可去掉 |
你想想看,现在还有多少32位的新手机?很少了。所以我的建议是:
- 发布版本:只保留arm64-v8a。体积小,兼容性好。
- 调试版本:加上x86_64,方便模拟器测试。
- 兼容老设备:保留armeabi-v7a。但说实话,我去年开始已经放弃这个了。
在build.gradle里配置ABI过滤:
android {
defaultConfig {
ndk {
abiFilters 'arm64-v8a', 'x86_64'
}
}
}
这样编译时只会生成这两个架构的so文件。
1.4 实战:第一个NDK项目
光说不练假把式。咱们来创建一个真正的NDK项目。
- 打开Android Studio,新建项目,选择「Native C++」模板。
- AS会自动生成CMakeLists.txt和native-lib.cpp。
- 在MainActivity里调用native方法:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("my_native_lib");
}
public native String stringFromJNI();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
}
}
对应的C++代码:
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_myapp_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
运行一下,看到「Hello from C++」了吗?恭喜你,第一个NDK项目跑起来了。
好了,第一章的内容就到这里。环境搭好了,项目跑通了,接下来咱们就可以深入JNI和C++的混合编程了。记住:基础不牢,地动山摇。把环境搭建这一步走稳,后面会顺利很多。
有什么问题,欢迎在评论区留言。咱们下章见。