@linux1s1s
2017-08-22T08:13:39.000000Z
字数 3381
阅读 3152
AndroidNDK
由于工作关系,接触一点NDK开发的内容,这篇博客仅仅涉及简单NDK开发的步骤,如果想进一步了解NDK开发的细节,请参考 Android NDK 开发文档
进入工程配置NDK路径

配置gradle.properties
新增一行:
android.useDeprecatedNdk=true

首先新建Android工程HelloNDK,在LibMonitor中添加一行本地方法如下:
public class LibMonitor{public static native String getStringFromNative();}
然后直接运行程序,在Studio环境下,会在xxxx\app\build\intermediates\classes\debug目录下生成class文件

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

bin\classes,而对于Studio开发的项目一般指定目录: \build\intermediates\classes(找到这个目录需要先 Make Project(Ctrl+F9))
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文件已经生成,注意这个文件是规则命名的,接下来一起来看看这个头文件长啥样
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_xx_app_monitor_core_LibMonitor */#ifndef _Included_com_xx_app_monitor_core_LibMonitor#define _Included_com_xx_app_monitor_core_LibMonitor#ifdef __cplusplusextern "C" {#endif/** Class: com_xx_app_monitor_core_LibMonitor* Method: jni_init* Signature: (Landroid/content/Context;ILjava/lang/String;)Z*/JNIEXPORT jboolean JNICALL Java_com_xx_app_monitor_core_LibMonitor_jni_1init(JNIEnv *, jclass, jobject, jint, jstring);/** Class: com_xx_app_monitor_core_LibMonitor* Method: jni_start* Signature: (Ljava/nio/ByteBuffer;)Ljava/nio/ByteBuffer;*/JNIEXPORT jobject JNICALL Java_com_xx_app_monitor_core_LibMonitor_jni_1start(JNIEnv *, jclass, jobject);/** Class: com_xx_app_monitor_core_LibMonitor* Method: jni_close* Signature: ()V*/JNIEXPORT void JNICALL Java_com_xx_app_monitor_core_LibMonitor_jni_1close(JNIEnv *, jclass);#ifdef __cplusplus}#endif#endif
头文件里面声明的方法JNIEXPORT jstring JNICALL Java_com_example_hellondk_MainActivity_getStringFromNative 同样也是规则命名的,接下来一起看看C文件如何完成。
(JNIEnv *, jclass);
上面已经生成了头文件,所以我们直接实现头文件中声明的方法即可
#include <stdio.h>#include <stdlib.h>#include "com_example_hellondk_MainActivity.h"JNIEXPORT jstring JNICALL Java_com_example_hellondk_MainActivity_getStringFromNative(JNIEnv * env, jclass jcl) {return (*env)->NewStringUTF(env, "Hello from JNI ! ");}
为了简单起见,我们仅仅返回一个字符串即可,接下来完成.mk文件。
还是在jni目录中完成Android.mk文件,我们来直接看看这个文件其中的参数如何定义即可:
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := helloLOCAL_SRC_FILES := hello.cinclude $(BUILD_SHARED_LIBRARY)
接下来我们需要生成so文件,bat脚本直接定位到jni目录下,运行ndk-build即可生成so文件

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

为了验证我们NDK是否可用,在MainActivity中加入以下代码:
public class MainActivity extends Activity{static{System.loadLibrary("hello");}public static native String getStringFromNative();@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final TextView textView = (TextView) findViewById(R.id.text);if (textView != null){textView.setText(getStringFromNative());}}}
Run以后可以看到TextView上显示 Hello from JNI !,至此NDK开发完整结束,开发过程就是这么简单,当然了这里仅仅是介绍开发流程,比较复杂的功能实现几乎全在C/C++层,所以这里就不在赘述了。
