[关闭]
@linux1s1s 2017-08-22T11:21:47.000000Z 字数 6398 阅读 898

Android NDK 开发基本流程

AndroidNDK 2017-08


本文从开发NDK的基本流程出发,一步一步完整的记录整个NDK开发过程。

配置NDK开发环境

新增一行:

  1. android.useDeprecatedNdk=true

此处输入图片的描述

编写Java对接层

使用Android Studio新建项目HelloNDK,在MainActivity中简单添加几行代码如下:

  1. package ndk.hello.com.hellondk;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.widget.Toast;
  5. public class MainActivity extends Activity {
  6. @Override
  7. protected void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.activity_main);
  10. Toast.makeText(this, test(), Toast.LENGTH_SHORT).show();
  11. }
  12. public static String test() {
  13. String result = null;
  14. try {
  15. result = jni_test();
  16. } catch (UnsatisfiedLinkError error) {
  17. error.printStackTrace();
  18. }
  19. return result;
  20. }
  21. private static native String jni_test();
  22. }

自动生成头文件

使用javah自动生成头文件,打开终端,进入main目录,如下:

此处输入图片的描述

因为javah需要生成的class文件,所以需要run一下项目,然后我们可以在一下目录中找到对应的MainActivity.class文件。

此处输入图片的描述

  1. H:\workspace\Native\HelloNDK\app\build\intermediates\classes\debug

类完整包名:

  1. ndk.hello.com.hellondk.MainActivity
  1. H:\Android\sdk\platforms\android-25\android.jar
  1. javah -d jni -classpath H:\Android\sdk\platforms\android-25\android.jar;H:\workspace\Native\HelloNDK\app\build\intermediates\classes\debug ndk.hello.com.hellondk.MainActivity

如图所示:
此处输入图片的描述

简要说明:
-d 后面的jni表示生成头文件的具体目录名称
-classpath 后面接两个内容,用号隔开。

  • 分号第一部分表示使用的android.jar绝对路径,如果不加该部分,则会出现某些android中的类找不到,比如android.content.Context
  • 分号第二部分表示需要生成头文件的具体类,这里要指定该类所在的绝对路径,注意,决定路径+全包名,中间有空格

执行javah以后,会在如图所示目录中自动生成头文件,该文件不需要修改。
此处输入图片的描述

打开文件看看自动生成的头文件如下:

  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class ndk_hello_com_hellondk_MainActivity */
  4. #ifndef _Included_ndk_hello_com_hellondk_MainActivity
  5. #define _Included_ndk_hello_com_hellondk_MainActivity
  6. #ifdef __cplusplus
  7. extern "C" {
  8. #endif
  9. #undef ndk_hello_com_hellondk_MainActivity_BIND_ABOVE_CLIENT
  10. #define ndk_hello_com_hellondk_MainActivity_BIND_ABOVE_CLIENT 8L
  11. #undef ndk_hello_com_hellondk_MainActivity_BIND_ADJUST_WITH_ACTIVITY
  12. #define ndk_hello_com_hellondk_MainActivity_BIND_ADJUST_WITH_ACTIVITY 128L
  13. #undef ndk_hello_com_hellondk_MainActivity_BIND_ALLOW_OOM_MANAGEMENT
  14. #define ndk_hello_com_hellondk_MainActivity_BIND_ALLOW_OOM_MANAGEMENT 16L
  15. #undef ndk_hello_com_hellondk_MainActivity_BIND_AUTO_CREATE
  16. #define ndk_hello_com_hellondk_MainActivity_BIND_AUTO_CREATE 1L
  17. #undef ndk_hello_com_hellondk_MainActivity_BIND_DEBUG_UNBIND
  18. #define ndk_hello_com_hellondk_MainActivity_BIND_DEBUG_UNBIND 2L
  19. #undef ndk_hello_com_hellondk_MainActivity_BIND_EXTERNAL_SERVICE
  20. #define ndk_hello_com_hellondk_MainActivity_BIND_EXTERNAL_SERVICE -2147483648L
  21. #undef ndk_hello_com_hellondk_MainActivity_BIND_IMPORTANT
  22. #define ndk_hello_com_hellondk_MainActivity_BIND_IMPORTANT 64L
  23. #undef ndk_hello_com_hellondk_MainActivity_BIND_NOT_FOREGROUND
  24. #define ndk_hello_com_hellondk_MainActivity_BIND_NOT_FOREGROUND 4L
  25. #undef ndk_hello_com_hellondk_MainActivity_BIND_WAIVE_PRIORITY
  26. #define ndk_hello_com_hellondk_MainActivity_BIND_WAIVE_PRIORITY 32L
  27. #undef ndk_hello_com_hellondk_MainActivity_CONTEXT_IGNORE_SECURITY
  28. #define ndk_hello_com_hellondk_MainActivity_CONTEXT_IGNORE_SECURITY 2L
  29. #undef ndk_hello_com_hellondk_MainActivity_CONTEXT_INCLUDE_CODE
  30. #define ndk_hello_com_hellondk_MainActivity_CONTEXT_INCLUDE_CODE 1L
  31. #undef ndk_hello_com_hellondk_MainActivity_CONTEXT_RESTRICTED
  32. #define ndk_hello_com_hellondk_MainActivity_CONTEXT_RESTRICTED 4L
  33. #undef ndk_hello_com_hellondk_MainActivity_MODE_APPEND
  34. #define ndk_hello_com_hellondk_MainActivity_MODE_APPEND 32768L
  35. #undef ndk_hello_com_hellondk_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING
  36. #define ndk_hello_com_hellondk_MainActivity_MODE_ENABLE_WRITE_AHEAD_LOGGING 8L
  37. #undef ndk_hello_com_hellondk_MainActivity_MODE_MULTI_PROCESS
  38. #define ndk_hello_com_hellondk_MainActivity_MODE_MULTI_PROCESS 4L
  39. #undef ndk_hello_com_hellondk_MainActivity_MODE_NO_LOCALIZED_COLLATORS
  40. #define ndk_hello_com_hellondk_MainActivity_MODE_NO_LOCALIZED_COLLATORS 16L
  41. #undef ndk_hello_com_hellondk_MainActivity_MODE_PRIVATE
  42. #define ndk_hello_com_hellondk_MainActivity_MODE_PRIVATE 0L
  43. #undef ndk_hello_com_hellondk_MainActivity_MODE_WORLD_READABLE
  44. #define ndk_hello_com_hellondk_MainActivity_MODE_WORLD_READABLE 1L
  45. #undef ndk_hello_com_hellondk_MainActivity_MODE_WORLD_WRITEABLE
  46. #define ndk_hello_com_hellondk_MainActivity_MODE_WORLD_WRITEABLE 2L
  47. #undef ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_DIALER
  48. #define ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_DIALER 1L
  49. #undef ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_DISABLE
  50. #define ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_DISABLE 0L
  51. #undef ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL
  52. #define ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_SEARCH_GLOBAL 4L
  53. #undef ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL
  54. #define ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_SEARCH_LOCAL 3L
  55. #undef ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_SHORTCUT
  56. #define ndk_hello_com_hellondk_MainActivity_DEFAULT_KEYS_SHORTCUT 2L
  57. #undef ndk_hello_com_hellondk_MainActivity_RESULT_CANCELED
  58. #define ndk_hello_com_hellondk_MainActivity_RESULT_CANCELED 0L
  59. #undef ndk_hello_com_hellondk_MainActivity_RESULT_FIRST_USER
  60. #define ndk_hello_com_hellondk_MainActivity_RESULT_FIRST_USER 1L
  61. #undef ndk_hello_com_hellondk_MainActivity_RESULT_OK
  62. #define ndk_hello_com_hellondk_MainActivity_RESULT_OK -1L
  63. /*
  64. * Class: ndk_hello_com_hellondk_MainActivity
  65. * Method: jni_test
  66. * Signature: ()Ljava/lang/String;
  67. */
  68. JNIEXPORT jstring JNICALL Java_ndk_hello_com_hellondk_MainActivity_jni_1test
  69. (JNIEnv *, jclass);
  70. #ifdef __cplusplus
  71. }
  72. #endif
  73. #endif

接下来我们手动写一个C文件,实现头文件中声明的方法

手动生成C/C++文件

对照头文件的方法,增加简单实现即可。

  1. #include "ndk_hello_com_hellondk_MainActivity.h"
  2. /*
  3. * Class: ndk_hello_com_hellondk_MainActivity
  4. * Method: jni_test
  5. * Signature: ()Ljava/lang/String;
  6. */
  7. JNIEXPORT jstring JNICALL Java_ndk_hello_com_hellondk_MainActivity_jni_1test
  8. (JNIEnv *env, jclass c){
  9. return (*env)->NewStringUTF(env, "Hello NDK");
  10. }

上面完成以后,如果 没有 在gradle.properties中配置

新增一行:

  1. android.useDeprecatedNdk=true

直接运行项目会报如下错误
此处输入图片的描述

配置build.gradle文件生成so

新增配置生成so文件
此处输入图片的描述

  1. android {
  2. compileSdkVersion 25
  3. buildToolsVersion "25.0.2"
  4. defaultConfig {
  5. applicationId "ndk.hello.com.hellondk"
  6. minSdkVersion 15
  7. targetSdkVersion 25
  8. versionCode 1
  9. versionName "1.0"
  10. testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  11. ndk {
  12. moduleName "hellondk"
  13. abiFilters "armeabi", "armeabi-v7a", "x86"
  14. stl "stlport_static"
  15. }
  16. }
  17. buildTypes {
  18. release {
  19. minifyEnabled false
  20. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  21. }
  22. debug {
  23. jniDebuggable true
  24. }
  25. }
  26. }

run一下项目,即可生成so文件,如下所示:
此处输入图片的描述

将so文件直接放在工程中使用

我们将上面生成的so文件,直接拿到别的工程中使用即可,这里为了演示方法,直接放在当前项目中演示(项目中的jni目录可以直接 删除,直接用so文件即可)

此处输入图片的描述

验证C++层返回的数据

运行项目,在启动进入首屏后会弹出Toast,上面显示Hello NDK 表示成功。(请读者自行测试)

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注