@linux1s1s
2017-08-22T16:13:39.000000Z
字数 3381
阅读 2811
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 __cplusplus
extern "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 := hello
LOCAL_SRC_FILES := hello.c
include $(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();
@Override
protected 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++层,所以这里就不在赘述了。