[关闭]
@linux1s1s 2017-08-22T16:13:39.000000Z 字数 3381 阅读 2817

Android NDK 开发初步

AndroidNDK


由于工作关系,接触一点NDK开发的内容,这篇博客仅仅涉及简单NDK开发的步骤,如果想进一步了解NDK开发的细节,请参考 Android NDK 开发文档

配置NDK开发环境

新增一行:

  1. android.useDeprecatedNdk=true

此处输入图片的描述

新建Android工程

首先新建Android工程HelloNDK,在LibMonitor中添加一行本地方法如下:

  1. public class LibMonitor
  2. {
  3. public static native String getStringFromNative();
  4. }

然后直接运行程序,在Studio环境下,会在xxxx\app\build\intermediates\classes\debug目录下生成class文件

此处输入图片的描述

执行javah

接下来执行javah,自动生成头文件。
定位到工程所在的目录下:D:\Workspace\HelloNDK,然后执行javah,我们先来看看javah有哪些可执行命令:

此处输入图片的描述

此处输入图片的描述

  1. javah -d jni -classpath H:\Android\sdk\platforms\android-22\android.jar;H:\workspace\FaceMonitor\app\build\intermediates\classes\debug\ com.xxx.app.monitor.core.LibMonitor

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

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

执行完上面的命令,如下图所示:

此处输入图片的描述

表示生成头文件成功,然后我们可以在jni文件下面可以看到com_example_hellondk_MainActivity.h文件已经生成,注意这个文件是规则命名的,接下来一起来看看这个头文件长啥样

  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class com_xx_app_monitor_core_LibMonitor */
  4. #ifndef _Included_com_xx_app_monitor_core_LibMonitor
  5. #define _Included_com_xx_app_monitor_core_LibMonitor
  6. #ifdef __cplusplus
  7. extern "C" {
  8. #endif
  9. /*
  10. * Class: com_xx_app_monitor_core_LibMonitor
  11. * Method: jni_init
  12. * Signature: (Landroid/content/Context;ILjava/lang/String;)Z
  13. */
  14. JNIEXPORT jboolean JNICALL Java_com_xx_app_monitor_core_LibMonitor_jni_1init
  15. (JNIEnv *, jclass, jobject, jint, jstring);
  16. /*
  17. * Class: com_xx_app_monitor_core_LibMonitor
  18. * Method: jni_start
  19. * Signature: (Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;
  20. */
  21. JNIEXPORT jobject JNICALL Java_com_xx_app_monitor_core_LibMonitor_jni_1start
  22. (JNIEnv *, jclass, jobject);
  23. /*
  24. * Class: com_xx_app_monitor_core_LibMonitor
  25. * Method: jni_close
  26. * Signature: ()V
  27. */
  28. JNIEXPORT void JNICALL Java_com_xx_app_monitor_core_LibMonitor_jni_1close
  29. (JNIEnv *, jclass);
  30. #ifdef __cplusplus
  31. }
  32. #endif
  33. #endif

头文件里面声明的方法JNIEXPORT jstring JNICALL Java_com_example_hellondk_MainActivity_getStringFromNative
(JNIEnv *, jclass);
同样也是规则命名的,接下来一起看看C文件如何完成。

完成C文件

上面已经生成了头文件,所以我们直接实现头文件中声明的方法即可

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "com_example_hellondk_MainActivity.h"
  4. JNIEXPORT jstring JNICALL Java_com_example_hellondk_MainActivity_getStringFromNative(
  5. JNIEnv * env, jclass jcl) {
  6. return (*env)->NewStringUTF(env, "Hello from JNI ! ");
  7. }

为了简单起见,我们仅仅返回一个字符串即可,接下来完成.mk文件。

Android.mk文件

还是在jni目录中完成Android.mk文件,我们来直接看看这个文件其中的参数如何定义即可:

  1. LOCAL_PATH := $(call my-dir)
  2. include $(CLEAR_VARS)
  3. LOCAL_MODULE := hello
  4. LOCAL_SRC_FILES := hello.c
  5. include $(BUILD_SHARED_LIBRARY)

ndk-build

接下来我们需要生成so文件,bat脚本直接定位到jni目录下,运行ndk-build即可生成so文件

此处输入图片的描述

接下来我们就可以在Eclipse工程下看到so文件已经生成了。

此处输入图片的描述

MainActivity中测试

为了验证我们NDK是否可用,在MainActivity中加入以下代码:

  1. public class MainActivity extends Activity
  2. {
  3. static
  4. {
  5. System.loadLibrary("hello");
  6. }
  7. public static native String getStringFromNative();
  8. @Override
  9. protected void onCreate(Bundle savedInstanceState)
  10. {
  11. super.onCreate(savedInstanceState);
  12. setContentView(R.layout.activity_main);
  13. final TextView textView = (TextView) findViewById(R.id.text);
  14. if (textView != null)
  15. {
  16. textView.setText(getStringFromNative());
  17. }
  18. }
  19. }

Run以后可以看到TextView上显示 Hello from JNI !,至此NDK开发完整结束,开发过程就是这么简单,当然了这里仅仅是介绍开发流程,比较复杂的功能实现几乎全在C/C++层,所以这里就不在赘述了。

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