一. 前言

1. NDK && JNI ?

  • JDK:Java Development Kit
  • SDK:Software Development Kit
  • NDK:Native Development Kit
  • JNI:Java Native Interface

NDK 是 Android平台用来支持 C/C++ 开发的。

2. 使用 NDK 的优劣

① 优点:

  • 代码的保护。apk的java层代码很容易被反编译,而 C/C++库 反汇难度较大。
  • 可以方便地使用现存的开源库。很多现存的开源优秀库都是用 C/C++ 代码编写的。
  • 提高程序的执行效率。将要求高性能的应用逻辑使用 C开发,从而提高应用程序的执行效率。
  • 便于移植。用 C/C++ 写的库可以方便在其他嵌入式平台上再次使用。

② 缺点:

  • 开发麻烦。
  • 调试不方便。
  • 难度相对较高。

③ 注意:

  • 要不要使用?什么情况下使用它?
  • 使用 NDK 大部分情况是需要将一些已有的 C函数 移植到 Android平台 所选择的快捷方法,而不是作为提高代码效率的手段。

3. 学什么?

  • 一种是已经编译好的 .so 动态库。
  • 一种是使用 C/C++ 源代码开发。

二. 代码实战

首先放出:官方文档

1. 准备工作-下载 NDK 和工具

要为您的应用编译和调试原生代码,您需要以下组件:

  • Android 原生开发套件 (NDK):这套工具使您能在 Android 应用中使用 C 和 C++ 代码。
  • CMake:一款外部编译工具,可与 Gradle 搭配使用来编译原生库。如果您只计划使用 ndk-build,则不需要此组件。
  • LLDB:Android Studio 用于调试原生代码的调试程序。(我找不到哪里可以下载,我猜是默认集成了)

2. 创建一个 Native C++ 项目

C++ Standard:指定编译库的环境,其中Toolchain Default使用的是默认的CMake环境;C++ 11也就是C++环境。两种环境都可以编库。

我第一次出现以下的错误,我的理解是没有下载对应的版本,点击下载等待完成后同步一下即可。

3. 默认产生的文件

native-lib.cpp:原生的静态库,在使用的时候需要提前加载。

CMakeLists.txt:所有需要用到的cpp文件都需要放在其中,以便加入到项目中。

4. 自己创建 C++ 文件

① 创建C++文件,其中的内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef INC_06_05_NDKTEST_TEST_H
#define INC_06_05_NDKTEST_TEST_H

#include <string>
using namespace std;

class Test {
public:
string getTestString(string str);
};


#endif //INC_06_05_NDKTEST_TEST_H
1
2
3
4
5
#include "Test.h"

string Test::getTestString(string str) {
return "NDK开发测试函数:"+str;
}

② 创建C++文件之后,还需要添加到CMakeLists.txt文件中,native-lib.cpp已经默认被加入其中了。

5. 使用自己创建的C++类里面的方法

① Activity中的调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class MainActivity extends AppCompatActivity {

// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

// Example of a call to a native method
TextView tv = findViewById(R.id.sample_text);
tv.setText(getTestString("参数"));
}

/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();

/**
* 测试
* @return
*/
public native String getTestString(String str);
}

② native-lib.cpp文件中的调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <jni.h>
#include <string>
#include "Test.h"

extern "C" JNIEXPORT jstring JNICALL
Java_swu_xl_baidu_ndktest_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}

extern "C"
JNIEXPORT jstring JNICALL
Java_swu_xl_baidu_ndktest_MainActivity_getTestString(JNIEnv *env, jobject thiz, jstring str) {

const char *xl_str = (env->GetStringUTFChars(str, 0));

Test* test = new Test;
std::string result = test->getTestString(xl_str);

return env->NewStringUTF(result.c_str());
}

③ 运行效果

三. 源代码

NDKTest

参考文章

Android NDK开发(一)

NDK开发学习(一) —创建一个支持c/c++的项目

android jni 中jstring字符串的转化 和 一些常用数据转化

官方文档-NDK 入门指南