JNI 是一个协议, NDK 是Android用于开发Jni的工具包
1、下载android-ndk-r13b-windows-x86.zip
压缩文件,放到一个没有中文没有空格的目录下面,比如E:\AndroidDev\AndroidSDK
。然后解压缩到当前目录下面
2、将ndk目录配置到系统环境变量path中,将E:\AndroidDev\AndroidSDK\android-ndk-r13b-windows-x86\android-ndk-r13b
加到path中
过程:
path src
C:\ProgramData\Oracle\Java\javapath;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Skype\Phone\;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;E:\AndroidDev\GitDevTool\Git\cmd
path: dest
ASDKH : E:\AndroidDev\AndroidSDK
C:\ProgramData\Oracle\Java\javapath;%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;%SYSTEMROOT%\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Skype\Phone\;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;E:\AndroidDev\GitDevTool\Git\cmd;%ASDKH%\android-ndk-r13b-windows-x86\android-ndk-r13b;%ASDKH%\android-ndk-r13b-windows-x86\android-ndk-r13b\build;%ASDKH%\platform-tools;%ASDKH%\tools;%ASDKH%\build-tools
3、在as中关联NDK
3.1、在工程目录下 <工程目录>/local.properties
文件中加入NDK目录
ndk.dir=E\:\\AndroidDev\\AndroidSDK\\android-ndk-r10d
3.2、在工程目录下: <工程目录>/gradle.properties
文件加入兼容老的ndk
#兼容老的NDK
android.useDeprecatedNdk=true
4、环境配置好后要实现第一个AS 用java通过ndk调用c代码
4.1、 NDK开发流程
1、在java里面写使用的native代码,定义一个JniC类,用于调用对应的native C代码。下面是调用C代码的接口类
package com.org.vincent.appjni;
/**
* Created by Administrator on 2016/11/29.
*/
public class DemoJni {
//增加对so库的加载
static {
System.loadLibrary("app");
}
private native String getString();
public String getStringFromC(){
return new DemoJni().getString();
}
}
com.org.vincent.appjni.DemoJni 类名
com.org.vincent.appjni.DemoJni#getString 类名加方法名
写好接口方法之后接下来就是关键了,点击 Build -> Make Project
, 如下图
将上面定义的DemoJni 类源码文件编译成class文件;在app_path/build/intermediates/classes/debug
目录下看有没生产class文件
2、Build 成功之后,就在Terminal 命令行进入 工程目录\app\src\main的目录下中执行javah生成.h 文件;注意:需要注意的是要进入 <Project>\app\src\main
的目录下执行javah命令
javah -d jni -classpath E:\AndroidDev\AndroidSDK\platforms\android-23\android.jar;..\..\build\intermediates\classes\debug com.org.vincent.appjni.DemoJni
如下图:
注意 ;..\..\
不能有空格,这个条件有点坑爹
执行上面javah命令后在main目录下自动生成了jni目录,里面躺着了刚才我们需要的头文件。
在jni目录下新建一个名字为main.c的文件,完成生产的.h文件的接口方法。文件内容如下:
#include "com_org_vincent_appjni_DemoJni.h"
#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>
JNIEXPORT jstring JNICALL Java_com_org_vincent_appjni_DemoJni_getString
(JNIEnv * env, jobject job){
__android_log_print(0,"JNI","I LOVE YOU PENGRONGPENGRONGPENGRONGPENGRONGPENGRONG");
return (*env)->NewStringUTF(env,"PENGRONGPENGRONGPENGRONGPENGRONGPENGRONGPENGRONG");
}
关于生产java jni本地方法接口的头文件还有第二种方法
在终端中进入当前模块源代码目录的<模块名>/src/main/java目录下,执行如下命令:
javah 类全类名
就会在当前java目录下生产一个头文件,如图2指示一样。
生产头文件的第三种方法是在 <模块名>/build/intermediates/classes、debug/目录下,用如下命令执行生产头文件
javah -classpath . -jni 全类名
如下,在命令行窗口执行如下命令就可以在build->intermediates->classes->debug下生产头文件
javah -classpath . -jni com.org.vincent.javacallc.JNI
做最后的构建配置工作。
app/build.gradle文件下面android 节点子节点defaultConfig 下面增加NDK节点
ndk{
moduleName "app"
ldLibs "log"
abiFilters "armeabi", "armeabi-v7a", "x86"
}
moduleName 和static {System.loadLibrary(“json”);}名字一样的啊。
在android节点新增新子节点:这个不清楚为什么需要,我没有加入也可以正确执行。
sourceSets.main {
jniLibs.srcDirs 'libs'
jni.srcDirs = []
}
在新创建的jni目录下编辑C源文件实现原生代码逻辑 ,
5、期间出现
Error:Execution failed for task ':app:compileDebugNdk'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'E:\AndroidDev\AndroidSDK\android-ndk-r10d\ndk-build.cmd'' finished with non-zero exit value 2
的事情,查阅网上是在jni目录下新建一个空白的util.c文件
6、编译出来的库文件被Studio输出到了app_path/build/intermediates/ndk的路径下。
7、安装运行
运行图
参考文献:
http://www.cnblogs.com/SusieBlog/p/5378967.html
http://blog.youkuaiyun.com/u012295927/article/details/50990240
http://blog.youkuaiyun.com/sodino/article/details/41946607
http://blog.youkuaiyun.com/chengkaizone/article/details/51075720
http://blog.youkuaiyun.com/duancanmeng/article/details/7399416
http://blog.youkuaiyun.com/zhiyuan0932
http://www.cnblogs.com/ouyangduoduo/p/5900040.html
http://www.cnblogs.com/BlueTzar/articles/1136549.html
http://hanyongqiang.blog.51cto.com/409447/83834/