我使用的是 android studio 2.3.3 版本,搭建 ndk 开发环境比较简单,打开 File----Settings----Appearance&Behavior----System Settings----Android SDK,选择 SDK Tools, 将 CMake,LLDB,NDK 前的复选框勾上,点击 Apply,然后就是等待 ndk 下载完成。
安装成功后, 右键项目 ----open module setting,Android NDK location 会自动赋值
创建 ndk 项目和普通 android 项目有一点区别,需要把 Include C++ support 前面的复选框勾上,然后直接下一步。但在最后一步,有一个 c++ 下拉框选项,可以根据你的实际情况适当修改,C++ Standard :点击下拉框,可以选择标准 C++,或者选择默认 CMake 设置的 Toolchain Default 选项。Exceptions Support :如果你想使用有关 C++ 异常处理的支持,就勾选它。勾选之后,Android Studio 会在 module 层的 build.gradle 文件中的 cppFlags 中添加 -fexcetions 标志。Runtime Type Information Support :如果你想支持 RTTI,那么就勾选它。勾选之后,Android Studio 会在 module 层的 build.gradle 文件中的 cppFlags 中添加 -frtti 标志。
项目创建好后,app 下多了一个 cpp 目录,该目录用于存放 c 程序的源码,头文件,预编译项目等,android studio 会默认帮我们创建一个 native-lib.cpp 文件,该文件已有一个测试方法,结构图如下:
通过上图看到,在 External Build Files 下面多了一个 CMakeLists.txt 文件,该文件用于 c 程序需要生成 so 文件的配置文件。
cmake_minimum_required(VERSION 3.4.1): 这是版本信息,我们不用管它
add_library():这个命令是,
- 通过add.library()定义多个库,CMake会去自动构建他们,一个*.cpp文件对应一个add_library命令.
- add_library( # Sets the name of the library.生成so文件的名字,建议和cpp文件同名
- native-lib
- # Sets the library as a shared library.
- SHARED
- # Provides a relative path to your source file(s). 需要生成so文件的cpp文件名称
- src/main/cpp/native-lib.cpp )
find_library(): 定位 NDK library 的位置,并将其位置存储在一个变量之中。在构建脚本的其他地方使用这个变量,来代指 NDK library。下面的示例代码将 Android-specific log support library 的位置存储到变量 log-lib 中
- find_library( # Sets the name of the path variable.
- log-lib
- # Specifies the name of the NDK library that
- # you want CMake to locate.
- log )
现在我们来看 native-lib.cpp 文件,这是 as 帮我们自动生成好的,返回是一个 Hello from C++ 的字符串。
- #include <jni.h>
- #include <string>
- extern "C"
- JNIEXPORT jstring JNICALL
- Java_serialport_com_ndkjnidemo_MainActivity_stringFromJNI(
- JNIEnv* env,
- jobject /* this */) {
- std::string hello = "Hello from C++";
- return env->NewStringUTF(hello.c_str());
- }
- JNIEXPORT jstring JNICALL 这里的jstring代表返回值, 参数JNIEnv* env,代表指针,jobject 代表调用这个方法的对像,方法命名规则:Java_包名_调用jni方法的类名_方法名,android studio 帮我们
- 生成的程序,activity包名是serialport.com.ndkjnidemo,类名是MainActivity,方法名是stringFromJNI,所以native-lib.cpp方法名称为:Java_serialport_com_ndkjnidemo_MainActivity_stringFromJNI,其中返回值类型和java数据类型对应如下
如果我们需要写多个 jni 方法,*.cpp 格式如下:
- //方法一
- extern "C"
- JNIEXPORT jstring JNICALL
- Java_serialport_com_ndkjnidemo_MainActivity_test1(
- JNIEnv* env,
- jobject /* this */) {
- std::string hello = "Hello from C++";
- return env->NewStringUTF(hello.c_str());
- }
- //方法二
- extern "C"//如果不写extern "C" java是无法调用到这里定义的方法
- JNIEXPORT jstring JNICALL
- Java_serialport_com_ndkjnidemo_MainActivity_test2(
- JNIEnv* env,
- jobject /* this */) {
- std::string hello = "Hello from C++";
- return env->NewStringUTF(hello.c_str());
- }
最后我们来看自动生成的 MainActivity, 在 onCreate 中调用 stringFromJNI,然后给文本组件赋值,软件运行参见图一
- package serialport.com.ndkjnidemo;
- import android.support.v7.app.AppCompatActivity;
- import android.os.Bundle;
- import android.widget.TextView;
- public class MainActivity extends AppCompatActivity {
- static {
- //native-lib值来自,CMakeLists.txt文件中,add_library命令的第一个参数
- System.loadLibrary("native-lib");
- }
}
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- TextView tv = (TextView) findViewById(R.id.sample_text);
- tv.setText(stringFromJNI());
- }
- public native String stringFromJNI();
代码都是 android studio 自动自成的,所以此处不上传代码,demo 运行结果:
参考文章:
Android NDK 开发(五) AndroidStudio 2.2 NDK 的开发环境搭建
来源: https://www.cnblogs.com/cq-jiang/p/8145281.html