这两个路径目录下有睁凳什么区别?
经AS编译后,生成so如下:
其中obj是中间耐早山生成so,用的话可以用merged_native_libs和stripped_native_libs下的;
区别:直接看大小就明白,stripped下203KB, merged是昌中1129KB,应该是merged下包含一些map信息、地址等,调试用比较合适;stripped移除了这部分,release比较合适
配置NDK下载ndk
解压配置环境变歼肆量
验证配置成功
设置android studio ndk路径
JNI开发
添加native接口注意写好native接口和System.loadLibrary()。
执行Build->Make Project,生成了.class文件,.class文件的生成路径是在 app/build/intermediates/classes/debug下
javah生成c头文件
点击”View->Tool Windows->Terminal“,打开终端,进入 \app\src\main的目录下执行javah命令:
javah -d jni -classpath <SDK_android.jar><APP_classes><class>
然后就氏正轿看到\app\src\main\jni\com_fy_administrator_jnitoso_JniUtil.h出现了.
1
然后根据.h文件,创建相对应的.cpp文件
创建Android.mk和Application.mk文件
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JNIDemo
LOCAL_SRC_FILES := testJni.cpp
LOCAL_SRC_FILES += CAdd.cpp
include $(BUILD_SHARED_LIBRARY)
其中LOCAL_PATH是C/C++代码所在目录,也就是我们的jni目录。
LOCAL_MODULE是要编译的库的名称。编译器会自动在前面加上lib,在后面加上.so。
LOCAL_SRC_FILES是要编译的C/C++文件。
Application.mk
APP_ABI := all
#APP_ABI := armeabi armeabi-v7a x86 mips arm64-v8a mips64 x86_64
配置清纯gradle
在defaultConfig下,配置ndk:
ndk {
moduleName "JNIDemo" // 生成的so名字
}
在android标签内配置sourceSets:
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
执行ndk-build命令生成所有cpu架构的so库
1、编译环境的搭建正所谓:“工欲善其事必先利其器”嘛,所以先把改准备工具准备一下,因为是在studio下编译的,所以啊,什么studio、什么sdk、什么jdk,这些都自己去弄吧,这里说一下ndk这个编译C文件工具怎么下载安装
下载完了之后直接是一个zip的压缩包,解压即可
然后你会在local.properties文件中看到:
不要急,还没有完,ndk环境搭建还有最后一步,在gradle.properties的文件末尾加上android.useDeprecatedNdk=true这段代码:
好了,到此处环境就搭建完毕了。
2、java代码和C代码的编写步骤及过程
首先新建一个java类JNIUtils.java
源弯 public class JNIUtils {
static {
System.loadLibrary("huazict")
}
//java调C中的方法都需要用native声明且方法名必须陵裂友和c的方法名一样
public native String getString()
}
然后如下图所示重新Make Project一下工程:
会在工程目录E:\work\MyApplication\stujni\build\intermediates\classes\debug\com\huazi\stujni\jni中看到自己编译后的class文件JNIUtils.class
其次就是生成.h文件了
在studio打开Terminal命令行工具,打开步骤是View->Tool Windows->Terminal
(或直接按Alt+F12
然后在命令行中先进入到工程的main目录下
输入命令:javah -d jni -classpath 自己编译后的class文件的绝对路径
例如:javah -d jni -classpath
E:\work\MyApplication\stujni\build\intermediates\classes\debug
com.huazi.stujni.jni.JNIUtils(注意debug后的空格)
看到上图,图中命令行中是直接进入到了工程的main目录下(在哪个目录下运行就会在哪个目录下自动生成jni文件夹),按回车之后就会在main目录下生成jni文件夹,同时生成.h文件,
这个文件.h文件不需要做任何修改,默认即可。
现在我们来写一个test的C文件huazict.c同.h文件一样放到jni文件夹下,代码如下:
#include "com_huazi_stujni_jni_JNIUtils.h"
/**
尺槐 * 上边的引用标签一定是.h的文件名家后缀,方法名一定要和.h文件中的方法名称一样
*/
JNIEXPORT jstring JNICALL Java_com_huazi_stujni_jni_JNIUtils_getString
(JNIEnv *env, jobject obj) {
return (*env)->NewStringUTF(env, "这是我测试的jni")
}
最后在构建文件中的默认配置中加上:
//ndk编译生成.so文件
ndk {
moduleName "huazict" //生成的so名字
abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定三种abi体系结构下的so库。
}
到这里,通过jni调C就完成了,现在我们来测试一下,写个TextView显示一下调用的C:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
TextView tv = (TextView)findViewById(R.id.tv)
tv.setText(new JNIUtils().getString())
}
}
ok,没问题,可以调用,其实也没有想象中的那么难,是吧!
三、调用编译过的.so库
上边编译完成了,有人会问:我要的是编译后的.so库,别人用的时候直接拿来用就可以了,那编译后的.so库在哪呢?
根据这个路径就可以找到指定输出的三种体系结构下的.so库文件,然后把.so文件复制出来,如下图所示的放到相应的文件夹下就ok了:
再次运行,结果还是一样的,跟上边贴的那张图的显示效果是是一样的,同样能调用到,代码我就不上传了,都在上边贴上去了,而且也上传不了,公司的所有文件都是加密的,想上传都上传不了。
到这里,整个jni的调用过程就结束了,包括调用jni需要的环境以及调用的过程,最后.so文件的导出,都在上边了,如果上边的jni调用过程有什么问题,欢迎留言,谢谢。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)