注:本文仅讲述操作步骤,至于用到的工具、插件或者不懂的名词请自行百度。
同时因为很多人在开始使用时会遇到一些列的BUG在这里给大家提供另一篇博客,
里面列出可能出现的异常以及解决方案:
不想使用NDK而是使用CMake的请移步至:
博主用到的工具:
1.Android Studio 2.3.1 (2017-04-01更新的)
2.NDK 14.1.3816874 (直接在AS使用SDK Manager下载安装即可)
步骤一:
新建一个Android工程,和平常没有任何区别。
步骤二:
切换目录视图到”project“
步骤三:
在main->src下新建一个包,随便命名(博主是 jnidemo);在包里面新建一个类,同样随便命名(博主是 JNIDemo.java)。
然后类在里面声明native方法,例如:
步骤4:
菜单:build->rebuild project重新编译工程。然后在打开目录
ps:rebuild是有的人会遇到一下异常:
Error:Execution failed for task ':app:clean'.
> Unable to delete directory: E:\Android\AndroidStudioProjects\JNIDemo\app\build\....
这是因为你没有关闭Terminal,在Terminal里面输入exit回车,然后在重新rebuild即可
app->build->intermediates->classes->debug->你的包名结构,看看是否已经生成 你刚才的类名.class,例如:
如果已经生成,则这个步骤完成。如果没生成,请重复步骤三。
步骤五:
打开Android studio 底部工具栏的 ”Terminal“ 然后切换目录到生成的.calss文件所在的目录(到debug就行了):
输入指令:
cd app\build\intermediates\classes\debug
然后:
javah -jni 你的完整包名.类名
例如:
然后你会在debug目录下看到多了一个 .h 的头文件:
步骤六:
把生成的.h头文件复制或者剪切,然后在目录app->src->main下创建一个名字为jni的文件夹,把.h头文件粘贴进去。
然后在这个文件夹里面继续新建一个名字任意的.cpp文件,这时jni文件夹里面就有两个文件,一个.h一个.cpp文件。
最后在.cpp文件里面实现函数的功能(就是步骤三声明的方法的实现,博主这里是两个数相加)
需要注意的是:
1..cpp文件里面必须包含生成的.h文件(#include <xxxx.h>)
2..cpp文件里面实现.h声明的方法,为了避免出错请直接在.h文件复制,然后补全功能代码即可。
例如 :图一是.h内容,图二是.cpp内容
到此为止,基本已经完成了native方法的声明以及实现了。
步骤七(其实到这里还不能运行,还会出现系列错误,请继续往下看):
测试功能:在布局文件里面声明一个TextView和一个Button,然后功能为:点击button后,调用native方法实现任意两个数相加,并把结果显示到textview上。
步骤八:
当你点击运行程序的时候肯定会报这么一个异常:
Error:Execution failed for task ':app:compileDebugNdk'. > Error: NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin. For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental. Set "$USE_DEPRECATED_NDK=true" in gradle.properties to continue using the current NDK integration.
根据提示,打开gradle.properties在最后一行加上android.useDeprecatedNdk=true即可
ps:如果之后运行还出现这么一个异常
Execution failed for task ':jnidemo:compileDebugNdk'.
> com.android.ide.common.internal.LoggedErrorException: Failed to run command:
请在jni文件夹新建一个空的的.cpp文件。这个据说是NDK的一个BUG,但是博主使用新版的NDK并没有出现这个异常.
步骤九:
在app 的build.gradle 的defaultConfig标签下添加
ndk{
moduleName "jinlib" //这个jinlib是随便命名的
}
然后在之前声明native方法的java文件里面加上:
static {
System.loadLibrary("jinlib");//名字和build.gradle对应即可
}
ok,重新编译运行。到此为止,一个JNI程序就可以运行了。
额外:
我们平常是不是看到我们使用人家的库明明是.so文件,那我怎么生成.so文件给别人用呢?
其实我们在编译的时候NDK已经帮我们生成了。打开目录
app->build->intermediates->ndk->debug->lib底下就能看到针对不同架构的.so文件了。.....请看图:
我们把lib里面的文件复制到工程的libs文件夹,然后把jni文件夹删除,看看还能不能运行程序?
文章到这里结束了,希望能帮到大家。
附上一张运行截图:
the end.