Android NDK 开发流程

[TOC]

一、下载并配置NDK

下载地址:https://developer.android.google.cn/ndk/downloads/
下载成功,直接解压配置自己的NDK路径,注意中间不要有空格,否则后面开发中会出问题。

NDK配置

二、创建 Android 项目,进行NDK配置

1、配置好NDK路径之后记得在工程目录的local.properties文件中进行关联,注意要配置自己NDK的路径

NDK配置

2、如果建立的是普通的 Android 项目,可按照文章内容进行配置,如果直接建立C/C++项目,下面的配置可以直接忽略的,因为系统自动配置好了。

ndk配置

三、在 Android 项目中声明 native 方法

  1. public class Jnitest {
  2. // 声明所需的 native 方法
  3. static {
  4. System.loadLibrary("Jnitest");
  5. }
  6. public native String getString();
  7. public native void setString(String str);
  8. }

四、编译 native 方法生成 .h 头文件

1、点击 Build –> Make Project,生成 class 文件

2、找到class文件,在app->build->intermediates->classes->debug目录下:

class 文件位置

3、通过javah命令生成.h头文件,点击 Android Studio 底下菜单中的 Terminal ,一次输入:

  1. cd app\build\intermediates\classes\debug
  1. // 这里注意改成自己的包名
  2. javah -jni com.mtf.ndktest.Jnitest

入下图所示,您的 .h 头文件已经生成成功,默认位置在 debug 目录下

生成 .h 头文件

.h 文件位置

  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class com_mtf_ndktest_Jnitest */
  4. #ifndef _Included_com_mtf_ndktest_Jnitest
  5. #define _Included_com_mtf_ndktest_Jnitest
  6. #ifdef __cplusplus
  7. extern "C" {
  8. #endif
  9. /*
  10. * Class: com_mtf_ndktest_Jnitest
  11. * Method: getString
  12. * Signature: ()Ljava/lang/String;
  13. */
  14. JNIEXPORT jstring JNICALL Java_com_mtf_ndktest_Jnitest_getString
  15. (JNIEnv *, jobject);
  16. /*
  17. * Class: com_mtf_ndktest_Jnitest
  18. * Method: setString
  19. * Signature: (Ljava/lang/String;)V
  20. */
  21. JNIEXPORT void JNICALL Java_com_mtf_ndktest_Jnitest_setString
  22. (JNIEnv *, jobject, jstring);
  23. #ifdef __cplusplus
  24. }
  25. #endif
  26. #endif

五、创建 C/C++ 文件实现 .h 文件

创建jni目录,将刚才生成的.h文件复制过来,创建.c/.cpp文件,实现.h文件中的方法,方法名称可以直接从.h文件中复制过来。

创建.cpp文件实现.h头文件方法

六、编译生成 .so 文件

1、用cmake方式编译so库,创建CMakeLists.txt文件。

  1. # For more information about using CMake with Android Studio, read the
  2. # documentation: https://d.android.com/studio/projects/add-native-code.html
  3. # Sets the minimum version of CMake required to build the native library.
  4. cmake_minimum_required(VERSION 3.4.1)
  5. # Creates and names a library, sets it as either STATIC
  6. # or SHARED, and provides the relative paths to its source code.
  7. # You can define multiple libraries, and CMake builds them for you.
  8. # Gradle automatically packages shared libraries with your APK.
  9. add_library( # Sets the name of the library.
  10. Jnitest
  11. # Sets the library as a shared library.
  12. SHARED
  13. # Provides a relative path to your source file(s).
  14. src/main/jni/Jnitest.cpp )
  15. # Searches for a specified prebuilt library and stores the path as a
  16. # variable. Because CMake includes system libraries in the search path by
  17. # default, you only need to specify the name of the public NDK library
  18. # you want to add. CMake verifies that the library exists before
  19. # completing its build.
  20. find_library( # Sets the name of the path variable.
  21. log-lib
  22. # Specifies the name of the NDK library that
  23. # you want CMake to locate.
  24. log )
  25. # Specifies libraries CMake should link to your target library. You
  26. # can link multiple libraries, such as libraries you define in this
  27. # build script, prebuilt third-party libraries, or system libraries.
  28. target_link_libraries( # Specifies the target library.
  29. Jnitest
  30. # Links the target library to the log library
  31. # included in the NDK.
  32. ${log-lib} )

2、配置app module目录下的build.gradle文件

  1. android {
  2. ......
  3. defaultConfig {
  4. ......
  5. externalNativeBuild {
  6. cmake {
  7. cppFlags ""
  8. abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定cpu体系结构下的so库。
  9. }
  10. }
  11. }
  12. externalNativeBuild {
  13. cmake {
  14. path "CMakeLists.txt"
  15. }
  16. }
  17. ......
  18. }

3、编译并看一下结果

  1. public class MainActivity extends AppCompatActivity {
  2. @Override
  3. protected void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(R.layout.activity_main);
  6. TextView tv = (TextView) findViewById(R.id.tv_test);
  7. tv.setText(Jnitest.getString());
  8. }
  9. }

编译so运行结果

(完)