赞
踩
JNI是一种协议
NDK是用来开发JNI的谷歌工具包
编译C代码就需要用到NDK工具
提高JNI开发的效率
了解"NDK"开发流程
Android Studio下的 NDK 环境配置(两篇均可以)
https://blog.csdn.net/weixin_42814000/article/details/105259159
https://blog.csdn.net/weixin_42814000/article/details/105259289
Eclipse下的 NDK 环境配置
https://blog.csdn.net/weixin_42814000/article/details/105259122
在Java类中定义native方法
在Activity类中声明: public native String helloJNI();
生成包含对应JNI函数声明的头文件
1). 在命令行窗口中执行: javah Activity全类名(在src下执行)
说明有的电脑可能会提示GBK的不可映射字符: 添加 -encoding utf-8
2). 在src下会生成一个头文件: com_atguigu_hellojni_MainActivity.h
3). 头文件中包含一个native方法对应的JNI函数声明(需要后面实现):
JNIEXPORT jstring JNICALL Java_com_atguigu_hellojni_MainActivity_helloJNI(JNIEnv *, jobject)
实现生成的JNI函数
1). 在应用下创建一个文件夹: jni
2). 将刚才生成的头文件复制到此文件夹下
3). 创建一个c文件来实现生成的JNI函数声明: test.c
#include "com_atguigu_hellojni_MainActivity.h"
JNIEXPORT jstring JNICALL Java_com_atguigu_hellojni_MainActivity_helloJNI
(JNIEnv * env, jobject jobj) {
return (*env)->NewStringUTF(env, "Hello from C");
}
借助NDK编译生成动态链接库文件(.so)
1). 解压NDK包, 配置NDK文件夹到path(不能包含空格)
2). 借助NDK下的文档(ANDROID-MK.html)编写用于编译的文件(jni/Android.mk)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni #指定生成的so文件的唯一标识
LOCAL_SRC_FILES := test.c #指定包含JNI函数的c文件名
include $(BUILD_SHARED_LIBRARY)
3). 在命令行窗口中进入应用根目录, 执行ndk-build命令, 生成so动态链接库文件
so文件路径: /libs/armeabi/libhello-jni.so
在Java类中加载动态连接库并调用native的方法
1). 在静态代码块中加载so文件:
static {
System.loadLibrary("hello-jni");
}
2). 调用native方法:
String result = helloJNI();
JNIEXPORT :
在Jni编程中所有本地语言实现Jni接口的方法前面都有一个"JNIEXPORT",这个可以看做是Jni的一个标志,至今为止没发现它有什么特殊的用处。
JNICALL :
这个可以理解为Jni 和Call两个部分,和起来的意思就是 Jni调用XXX(后面的XXX就是JAVA的方法名)。
安装配置NDK
1). 解压NDK的zip包到非中文目录
2). 配置path : 解压后NDK的根目录----->ndk-build
将NDK关联到eclipse
Window–>Preferences–>Android–>NDK–>配置NDK的根目录
为当前应用自动生成c文件和mk文件
1). 选中当前应用右键–>Android Tools–>Add Native Support
2). 将生成的.cpp文件改为.c文件
3). 修改mk文件: 将.cpp改为.c
配置关联jni.h (见"配置关联jni.h文件"截图)
1). 选中当前应用右键–>Properties–>C/C++ General–>Paths and Symbols
2). 选择add–>选择File System–>选择文件夹android-ndk-r9\platforms\android-18\arch-arm\usr\include
3). 点击ok–>点击apply
定义naitve方法
public native String helloNDK();
实现native方法对应的JNI函数
1). 使用javah命令, 生成JNI头文件, 将其复制到jni文件下
2). 在c文件中实现h文件中的函数声明
3). 利用* 的NewStringUTF()函数, 返回字符串
一锤编译生成so文件
1). 使用工具栏中的"Build"工具点击锤子按钮生成
2). 文件路径: /libs/armeabi/libNDKTest.so
加载动态库, 并调用native方法
static {
System.loadLibrary("NDKTest");
}
String result = helloNDK();
修改C函数, 不需要再单独编译生成so文件, 可直接运行安装
APK只是将so打包了, 本质并不需要jni文件夹下的相关文件
多平台交叉编译
1、 arm
2、 intel
3、 mips
Android.mk详细介绍
#必须定义好LOCAL_PATH变量。它用于在开发树中查找源文件 #宏函数’my-dir’,由编译系统提供,用于返回当前路径(包含c/c++文件) LOCAL_PATH := $(call my-dir) #清除除LOCAL_PATH之外的LOCAL_XXX变量 #CLEAR_VARS由编译系统提供 include $(CLEAR_VARS) #以标识你在Android.mk文件中描述的每个模块。名称必须是唯一的 #编译会产生的链接库文件(lib+名称+.so): libtest2-jni.so LOCAL_MODULE := test2-jni #指定将要编译打包进模块中的C或C++源代码文件 #如果有多个, 以空格隔开 LOCAL_SRC_FILES := test2.c #编译生成动态库(也就是.so文件) include $(BUILD_SHARED_LIBRARY) #编译生成静态库(也就是.a文件) #include $(BUILD_STATIC_LIBRARY)
编写Android.mk
配置关联jni.h文件
编写Application.mk
安装配置NDK
1).
https://github.com/inferjay/AndroidDevTools
根据自己的系统选择
2). 解压NDK的zip包到非中文目录
注意文件夹名字不能有空格
3). 配置Path环境变量 : 解压后NDK的根目录----->ndk-build
然后点击环境变量(建议配置在上面 用户变量,因为如果配置在系统变量的话,如果有一天你删除了系统变量的,那么会导致系统用不了,如果配置在用户变量,要进行删除时,如果用不了,只用重新创建一个用户就可以了,电脑还是可以使用。)
配置Path的原因就是可以通过cmd操作命令
如果没有配置Path,不会弹出下面的信息,它会说命令没有被找到
给AS配置关联NDK
1). local.properties中添加配置
ndk.dir=G\:\\android-ndk-r10(=号后面为ndk的解压路径)
2). gradle.properties中添加配置
兼容老的ndk(老的版本):android.useDeprecatedNdk=true
android.useDeprecatedNdk=true
public class JNIS {
public native String helloJNI();
}
定义对应的JNI
1). 在main下创建jni文件夹
2). 生成native方法对应的JNI函数声明头文件: 命令窗口中, 进入java文件夹
执行命令: javah com.atguigu.jnitests2.JNIS
生成头文件: com_atguigu_jnitests2_JNIS.h
函数声明: JNIEXPORT jstring JNICALL Java_com_atguigu_jnitests2_JNIS_helloJNI(JNIEnv *, jobject);
3). 将生成的头文件转移到jni文件夹下
4). 在jni下定义对应的函数文件: test.c
#include "com_atguigu_jnitests2_JNIS.h"
JNIEXPORT jstring JNICALL Java_com_atguigu_jnitests2_JNIS_helloJNI
(JNIEnv * env, jobject jobj) {
return (*env)->NewStringUTF(env, "Hello from C");
}
5). 在jni文件夹下创建一个空的C文件: empty.c
说明: 这是AS的bug, 必须至少2个C文件才能通过编译
指定编译的不同CPU
defaultConfig {
ndk{
moduleName "HelloJni" //so文件: lib+moduleName+.so
abiFilters "armeabi", "armeabi-v7a", "x86" //cpu的类型
}
}
编译生成不同平台下的动态链接文件
1). 执行rebuild, 生成so文件
2). so文件目录: build\intermediates\ndk\debug\lib…
调用native方法:
1). 在native方法所在的类中加载so文件
static {
System.loadLibrary("HelloJni");
}
2). 在Activity中调用native方法:
String result = new JNIS().helloJNI();
Log.e("TAG", "result="+result);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。