Android      在Android中使用JNA   
文章目录  [隐藏]

一.JNA简述

略。



二.so文件的编译

本文以C语言为例。


1.C源文件



2.Android.mk文件



3.Application.mk文件



4.使用NDK编译

有些网络文章中讲到的,可以不用App.mk文件。
这里只使用NDK进行编译。即 你电脑上没有安装AndroidStudio和Eclipse也无所谓。
建议将NDK的根路径配置到系统的环境变量,在cmd中输入ndk-build能看到如下信息:



这里以csource文件夹为例,将源码和mk文件放入,然后cmd的工作路径也切换到这里:



执行命令 ndk-build 进行编译,如果这时你还看到上图所示的2行信息,说明编译失败,Could not find application project directory !


此时可以直接指定编译入口:




当前文件夹里生成新的目录,libs,其中就是我们的目标so文件。



三.JNA依赖的准备

前往 https://github.com/java-native-access/jna/releases ,下载最新的zip包。



将zip文件解码,打开 dist 目录,找到7个android-*.jar文件,解压得到其中的so库,并对应的放到7个平台目录中。当然这7个并非都需要,armeabi、armeabi-v7a是最常用的。



除了这些so文件,还需要2个jar。jna-min.jar 和 jna-platform.jar 。



四.在AndroidStudio中集成so的形式

按照平常的路子创意几个普通的AS项目。


1.libs方式

常用的方式,就是将so、jar、arr等依赖一股脑儿放到项目默认的libs目录里。直接强硬干脆利落。通常集成第三方的地图、推送、一些功能框架时这么做。



将第三方依赖加入libs后不用做其它过多配置,就可以在java代码中直接使用了。因为gradle里默认加载此目录中的依赖:



现在,在libs下放入我们需要的JNA依赖和之前编译好的so文件:



往常就可以直接java开黑,没有任何问题。但JNA的特殊性会导致一个异常:

com.cuiweiyou.jnaprj E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.cuiweiyou.jnaprj, PID: 31846
java.lang.UnsatisfiedLinkError: Native library (com/sun/jna/android-arm/libjnidispatch.so) not found in resource path (.)
at com.sun.jna.Native.loadNativeDispatchLibraryFromClasspath(Native.java:962)
at com.sun.jna.Native.loadNativeDispatchLibrary(Native.java:922)
at com.sun.jna.Native.(Native.java:190)
at com.sun.jna.Native.loadLibrary(Native.java:544)





此时,需要在Module的gradle里配置一下:



这样,无论是JNA的还是我们自己的so都能比较统一的管理。

2.jniLibs方式

相较于上面的方式1,这个多了一个目录,但gradle里不用过多配置。
jar包仍然放在默认的libs里。
然后在 src/main/ 下新建“jniLibs”目录,将so库文件放进去。



Module的gradle按照默认配置,无修改。



五.在Java中使用JNA

相较于JNI省事多了,JNA直接api调用即可。


接口的属性是public公共的、static静态的、final最终的,相当于全局常量。

1. 接口JNATest继承自sun的Library,这个Library也是个接口。
2. JNATest内部通过sun的Native调用了loadLibrary方法,传入的第一个参数就是我们自己编译的so文件名(去掉‘lib’和后缀)。方法内部调用了第2个参数JNATest.class的类加载器,并为这个class创建了一个InvocationHandler,这个Handler去加载我们的自己的so。最终使用Proxy将准备好的种种生成一个代理使用。
3. INSTANCE这个代理就是实现了“add”方法的一个JNATest的实例。JNATest的add方法对应c代码中的add函数。须注意java的数据类型和c的数据类型的差异。本文为了简便而仅涉及int类型。



如此,当java调用INSTANCE的add时,最终通过代理反射去执行C定义的原生代码。



承接App定制、企业web站点、办公系统软件 设计开发,外包项目,毕设