最近在做OpenCV 开发,android中现成的轮子不多,c\c++中的轮子倒是挺多的,所以就有心自己用NDK生成一个so库去使用,由于也是第一次接触NDK,还处于边看边学习的状态,不过最终还是做出了个小demo出来,其中也看了好多篇文章看的也是懵懵懂懂的,废话不多说了开始我的NDK学习之旅吧。
NDK开发工具:
1.Andoid studio :
2.Ndk 开发包:
ndk下载路径: https://dl.google.com/android/repository/android-ndk-r13b-windows-x86_64.zip
下载完后将它解压到一个合适位置就好了,最好没有中文路径
Android studio环境配置:
JDK 和 SDK的环境配置我就不多说了,这里说一下NDK的环境配置,它的配置和JDK 和 SDK 都差不多,你只需要在环境变量的path中加入NDK的根目录就好如下:
E:\NDK\android-ndk-r13b这是我的NDK路径,将其添加到环境变量就行。
在dos命令行中输入 ndk-build来判断是否配置成功,成功的话会输出以下信息:
Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
E:\NDK\android-ndk-r13b\build\..\build\core\build-local.mk:151: Android NDK: Aborting . Stop.
它有点像错误信息,不过不用在意,这就是已经成功了。
NDK配置成功,接下来就是对我们的开发工具Android studio的配置了,配置也很简单只需要修改两个地方就好,如下:
第一个位置,在gradle.properties中添加android.useDeprecatedNdk=true
第二个位置,在local.properties中添加你的NDK路径
其实也可以通过另一种方法添加NDK路径,如下:
在这里配置完NDK路径,会在local.properties中自动生成你的ndk路径的配置文字
—————————到这里准备工作我们就已经完成了————————–
现在开启我们的NDK初体验之旅
第一步:
创建一个类,类里面只有短短的几行代码,初体验吗没必要写那么多,如下:
这里直接把代码给出,你们复制粘贴吗,没必要去写:
public static native String stringFromJNI();
static {
System.loadLibrary("hello");
}
由于是初体验你们可能不知道,android中c\c++的代码书写规范,所以我们要通过命令来生成一个帮助我们写c\c++代码.h文件,命令如下:
首先通过命令进入到你的java目录下,然后通过以下命令生成.h文件,如图
这个命令要根据你们自己到包名去写,最终生成.h文件:
.h文件中的内容是这样的:
#ifndef _Included_com_guangzong_zl_testjni_TestJni
#define _Included_com_guangzong_zl_testjni_TestJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_guangzong_zl_testjni_TestJni
* Method: stringFromJNI
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_guangzong_zl_testjni_TestJni_stringFromJNI
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
其实就Java_com_guangzong_zl_testjni_TestJni_stringFromJNI这句话有用,这句话的格式就是c\c++代码方法的命名格式,要严格按照这种方式去命名,你们自己找规律吧我就不说了。
第二步:
通过在你的工程的main节点上右键,new –> Folder –> JNI Folder 创建一个Jni文件夹,
接下啦我们要为这个文件夹添加两个文件,他们分别是Android.mk和hello.c ,其中Android.mk文件必需得命名为Android,而.C文件就无所谓了你乐意起什么名字就叫什么名字。
.c文件通过以下方式生成:
接下来我们要给.c文件中添加代码,如下:
#include <jni.h>
jstring
Java_com_guangzong_zl_testjni_TestJni_stringFromJNI( JNIEnv* env, jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI! Compiled with ABI ");
}
这段代码的意思就是向外return 一段字符串
再往后我们要为Android.mk文件中添加以下内容:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello //要生成的so库的名字
LOCAL_SRC_FILES := hello.c //要将哪个.c文件生成so库
include $(BUILD_SHARED_LIBRARY)
第三步:
生成so库文件,通过 ndk-build命令生成
操作方法:
记着要先进入到main目录下再去执行ndk-build命令,生成完so库文件后的目录结构,如下:
可以看出这里多出了两个文件夹,libs中是你的so库文件,而这个obj没啥用,你可以把它删掉。
第四步:
使用我们生成的so文件,首先将libs重命名为JniLibs,然后直接通过我们的TestJni这个类去调用stringFromJNI()方法就行了,以下是ManActivity中的代码:
public class MainActivity extends AppCompatActivity {
private TextView main_text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
main_text = (TextView) findViewById(R.id.main_text);
main_text.setText(TestJni.stringFromJNI());
}
}
最终的效果图:
可以看到我们成功的获取到了C代码返回的字符串,好啦Android NDK初体验到这里就结束了